Merge "Add resource reference annotations"
diff --git a/Android.mk b/Android.mk
index eeec9458..84d5dc5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -85,6 +85,8 @@
 	core/java/android/app/IWallpaperManager.aidl \
 	core/java/android/app/IWallpaperManagerCallback.aidl \
 	core/java/android/app/admin/IDevicePolicyManager.aidl \
+	core/java/android/app/trust/ITrustManager.aidl \
+	core/java/android/app/trust/ITrustListener.aidl \
 	core/java/android/app/backup/IBackupManager.aidl \
 	core/java/android/app/backup/IFullBackupRestoreObserver.aidl \
 	core/java/android/app/backup/IRestoreObserver.aidl \
@@ -117,6 +119,8 @@
 	core/java/android/content/ISyncContext.aidl \
 	core/java/android/content/ISyncServiceAdapter.aidl \
 	core/java/android/content/ISyncStatusObserver.aidl \
+	core/java/android/content/pm/ILauncherApps.aidl \
+	core/java/android/content/pm/IOnAppsChangedListener.aidl \
 	core/java/android/content/pm/IPackageDataObserver.aidl \
 	core/java/android/content/pm/IPackageDeleteObserver.aidl \
 	core/java/android/content/pm/IPackageInstallObserver.aidl \
@@ -190,9 +194,17 @@
 	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/trust/ITrustAgentService.aidl \
+	core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
 	core/java/android/service/wallpaper/IWallpaperConnection.aidl \
 	core/java/android/service/wallpaper/IWallpaperEngine.aidl \
 	core/java/android/service/wallpaper/IWallpaperService.aidl \
+	core/java/android/tv/ITvInputClient.aidl \
+	core/java/android/tv/ITvInputManager.aidl \
+	core/java/android/tv/ITvInputService.aidl \
+	core/java/android/tv/ITvInputServiceCallback.aidl \
+	core/java/android/tv/ITvInputSession.aidl \
+	core/java/android/tv/ITvInputSessionCallback.aidl \
 	core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
 	core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
@@ -289,6 +301,7 @@
 	telephony/java/com/android/internal/telephony/ISms.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
+	wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl \
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	packages/services/PacProcessor/com/android/net/IProxyService.aidl \
 	packages/services/Proxy/com/android/net/IProxyCallback.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 4f0e603..ffdac4e 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -188,6 +188,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*)
 $(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/)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index faeab39..3230bd8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,6 +28,8 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
+    field public static final java.lang.String BIND_TRUST_AGENT_SERVICE = "android.permission.BIND_TRUST_AGENT_SERVICE";
+    field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
@@ -245,6 +247,7 @@
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
     field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
+    field public static final int actionBarTheme = 16843837; // 0x101043d
     field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
     field public static final int actionButtonStyle = 16843480; // 0x10102d8
     field public static final int actionDropDownStyle = 16843479; // 0x10102d7
@@ -287,7 +290,7 @@
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
     field public static final int angle = 16843168; // 0x10101a0
-    field public static final int animate = 16843822; // 0x101042e
+    field public static final int animate = 16843823; // 0x101042f
     field public static final int animateFirstView = 16843477; // 0x10102d5
     field public static final int animateLayoutChanges = 16843506; // 0x10102f2
     field public static final int animateOnClick = 16843356; // 0x101025c
@@ -374,19 +377,19 @@
     field public static final int clipChildren = 16842986; // 0x10100ea
     field public static final int clipOrientation = 16843274; // 0x101020a
     field public static final int clipToPadding = 16842987; // 0x10100eb
-    field public static final int clipToPath = 16843821; // 0x101042d
+    field public static final int clipToPath = 16843822; // 0x101042e
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorButtonNormal = 16843828; // 0x1010434
-    field public static final int colorButtonNormalColored = 16843830; // 0x1010436
-    field public static final int colorButtonPressed = 16843829; // 0x1010435
-    field public static final int colorButtonPressedColored = 16843831; // 0x1010437
-    field public static final int colorControlActivated = 16843827; // 0x1010433
-    field public static final int colorControlNormal = 16843826; // 0x1010432
+    field public static final int colorButtonNormal = 16843829; // 0x1010435
+    field public static final int colorButtonNormalColored = 16843831; // 0x1010437
+    field public static final int colorButtonPressed = 16843830; // 0x1010436
+    field public static final int colorButtonPressedColored = 16843832; // 0x1010438
+    field public static final int colorControlActivated = 16843828; // 0x1010434
+    field public static final int colorControlNormal = 16843827; // 0x1010433
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -754,7 +757,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
-    field public static final int limitTo = 16843823; // 0x101042f
+    field public static final int limitTo = 16843824; // 0x1010430
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -864,10 +867,11 @@
     field public static final int permissionFlags = 16843719; // 0x10103c7
     field public static final int permissionGroup = 16842762; // 0x101000a
     field public static final int permissionGroupFlags = 16843717; // 0x10103c5
+    field public static final int persistable = 16843833; // 0x1010439
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
-    field public static final int pinned = 16843825; // 0x1010431
+    field public static final int pinned = 16843826; // 0x1010432
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -932,7 +936,7 @@
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredForProfile = 16843824; // 0x1010430
+    field public static final int requiredForProfile = 16843825; // 0x1010431
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
@@ -1018,6 +1022,7 @@
     field public static final int shrinkColumns = 16843082; // 0x101014a
     field public static final deprecated int singleLine = 16843101; // 0x101015d
     field public static final int singleUser = 16843711; // 0x10103bf
+    field public static final int slideEdge = 16843836; // 0x101043c
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -1070,9 +1075,11 @@
     field public static final int stretchMode = 16843030; // 0x1010116
     field public static final int stroke = 16843811; // 0x1010423
     field public static final int strokeLineCap = 16843820; // 0x101042c
+    field public static final int strokeLineJoin = 16843821; // 0x101042d
     field public static final int strokeOpacity = 16843812; // 0x1010424
     field public static final int strokeWidth = 16843813; // 0x1010425
     field public static final int subtitle = 16843473; // 0x10102d1
+    field public static final int subtitleTextAppearance = 16843835; // 0x101043b
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int subtypeExtraValue = 16843674; // 0x101039a
     field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1188,6 +1195,7 @@
     field public static final int tintMode = 16843798; // 0x1010416
     field public static final int title = 16843233; // 0x10101e1
     field public static final int titleCondensed = 16843234; // 0x10101e2
+    field public static final int titleTextAppearance = 16843834; // 0x101043a
     field public static final int titleTextStyle = 16843512; // 0x10102f8
     field public static final int toAlpha = 16843211; // 0x10101cb
     field public static final int toDegrees = 16843188; // 0x10101b4
@@ -1759,13 +1767,13 @@
     field public static final int TextAppearance_DeviceDefault_Widget = 16974265; // 0x10301b9
     field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Menu = 16974286; // 0x10301ce
     field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle = 16974279; // 0x10301c7
-    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
+    field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
     field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title = 16974278; // 0x10301c6
-    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
+    field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
     field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle = 16974281; // 0x10301c9
-    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
+    field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
     field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title = 16974280; // 0x10301c8
-    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
+    field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
     field public static final int TextAppearance_DeviceDefault_Widget_Button = 16974266; // 0x10301ba
     field public static final int TextAppearance_DeviceDefault_Widget_DropDownHint = 16974271; // 0x10301bf
     field public static final int TextAppearance_DeviceDefault_Widget_DropDownItem = 16974272; // 0x10301c0
@@ -1820,46 +1828,50 @@
     field public static final int TextAppearance_Medium = 16973892; // 0x1030044
     field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
     field public static final int TextAppearance_Quantum = 16974346; // 0x103020a
-    field public static final int TextAppearance_Quantum_Body1 = 16974534; // 0x10302c6
-    field public static final int TextAppearance_Quantum_Body2 = 16974533; // 0x10302c5
-    field public static final int TextAppearance_Quantum_Button = 16974537; // 0x10302c9
-    field public static final int TextAppearance_Quantum_Caption = 16974535; // 0x10302c7
+    field public static final int TextAppearance_Quantum_Body1 = 16974538; // 0x10302ca
+    field public static final int TextAppearance_Quantum_Body2 = 16974537; // 0x10302c9
+    field public static final int TextAppearance_Quantum_Button = 16974541; // 0x10302cd
+    field public static final int TextAppearance_Quantum_Caption = 16974539; // 0x10302cb
     field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974347; // 0x103020b
-    field public static final int TextAppearance_Quantum_Display1 = 16974529; // 0x10302c1
-    field public static final int TextAppearance_Quantum_Display2 = 16974528; // 0x10302c0
-    field public static final int TextAppearance_Quantum_Display3 = 16974527; // 0x10302bf
-    field public static final int TextAppearance_Quantum_Display4 = 16974526; // 0x10302be
-    field public static final int TextAppearance_Quantum_Headline = 16974530; // 0x10302c2
+    field public static final int TextAppearance_Quantum_Display1 = 16974533; // 0x10302c5
+    field public static final int TextAppearance_Quantum_Display2 = 16974532; // 0x10302c4
+    field public static final int TextAppearance_Quantum_Display3 = 16974531; // 0x10302c3
+    field public static final int TextAppearance_Quantum_Display4 = 16974530; // 0x10302c2
+    field public static final int TextAppearance_Quantum_Headline = 16974534; // 0x10302c6
     field public static final int TextAppearance_Quantum_Inverse = 16974348; // 0x103020c
     field public static final int TextAppearance_Quantum_Large = 16974349; // 0x103020d
     field public static final int TextAppearance_Quantum_Large_Inverse = 16974350; // 0x103020e
     field public static final int TextAppearance_Quantum_Medium = 16974351; // 0x103020f
     field public static final int TextAppearance_Quantum_Medium_Inverse = 16974352; // 0x1030210
-    field public static final int TextAppearance_Quantum_Menu = 16974536; // 0x10302c8
+    field public static final int TextAppearance_Quantum_Menu = 16974540; // 0x10302cc
     field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974353; // 0x1030211
     field public static final int TextAppearance_Quantum_SearchResult_Title = 16974354; // 0x1030212
     field public static final int TextAppearance_Quantum_Small = 16974355; // 0x1030213
     field public static final int TextAppearance_Quantum_Small_Inverse = 16974356; // 0x1030214
-    field public static final int TextAppearance_Quantum_Subhead = 16974532; // 0x10302c4
-    field public static final int TextAppearance_Quantum_Title = 16974531; // 0x10302c3
+    field public static final int TextAppearance_Quantum_Subhead = 16974536; // 0x10302c8
+    field public static final int TextAppearance_Quantum_Title = 16974535; // 0x10302c7
     field public static final int TextAppearance_Quantum_Widget = 16974358; // 0x1030216
     field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974359; // 0x1030217
     field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974360; // 0x1030218
-    field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974361; // 0x1030219
-    field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974362; // 0x103021a
-    field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974363; // 0x103021b
-    field public static final int TextAppearance_Quantum_Widget_Button = 16974364; // 0x103021c
-    field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974365; // 0x103021d
-    field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974366; // 0x103021e
-    field public static final int TextAppearance_Quantum_Widget_EditText = 16974367; // 0x103021f
-    field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974368; // 0x1030220
-    field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974369; // 0x1030221
-    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974370; // 0x1030222
-    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974371; // 0x1030223
-    field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974372; // 0x1030224
-    field public static final int TextAppearance_Quantum_Widget_TextView = 16974373; // 0x1030225
-    field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974374; // 0x1030226
-    field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974375; // 0x1030227
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle_Inverse = 16974361; // 0x1030219
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974362; // 0x103021a
+    field public static final int TextAppearance_Quantum_Widget_ActionBar_Title_Inverse = 16974363; // 0x103021b
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974364; // 0x103021c
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle_Inverse = 16974365; // 0x103021d
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974366; // 0x103021e
+    field public static final int TextAppearance_Quantum_Widget_ActionMode_Title_Inverse = 16974367; // 0x103021f
+    field public static final int TextAppearance_Quantum_Widget_Button = 16974368; // 0x1030220
+    field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974369; // 0x1030221
+    field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974370; // 0x1030222
+    field public static final int TextAppearance_Quantum_Widget_EditText = 16974371; // 0x1030223
+    field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974372; // 0x1030224
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974373; // 0x1030225
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974374; // 0x1030226
+    field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974375; // 0x1030227
+    field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974376; // 0x1030228
+    field public static final int TextAppearance_Quantum_Widget_TextView = 16974377; // 0x1030229
+    field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974378; // 0x103022a
+    field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974379; // 0x103022b
     field public static final int TextAppearance_Quantum_WindowTitle = 16974357; // 0x1030215
     field public static final int TextAppearance_Small = 16973894; // 0x1030046
     field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047
@@ -1955,34 +1967,34 @@
     field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007
     field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a
     field public static final int Theme_Panel = 16973913; // 0x1030059
-    field public static final int Theme_Quantum = 16974376; // 0x1030228
-    field public static final int Theme_Quantum_Dialog = 16974377; // 0x1030229
-    field public static final int Theme_Quantum_DialogWhenLarge = 16974381; // 0x103022d
-    field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974382; // 0x103022e
-    field public static final int Theme_Quantum_Dialog_MinWidth = 16974378; // 0x103022a
-    field public static final int Theme_Quantum_Dialog_NoActionBar = 16974379; // 0x103022b
-    field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974380; // 0x103022c
-    field public static final int Theme_Quantum_InputMethod = 16974383; // 0x103022f
-    field public static final int Theme_Quantum_Light = 16974391; // 0x1030237
-    field public static final int Theme_Quantum_Light_DarkActionBar = 16974392; // 0x1030238
-    field public static final int Theme_Quantum_Light_Dialog = 16974393; // 0x1030239
-    field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974397; // 0x103023d
-    field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974398; // 0x103023e
-    field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974394; // 0x103023a
-    field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974395; // 0x103023b
-    field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974396; // 0x103023c
-    field public static final int Theme_Quantum_Light_NoActionBar = 16974399; // 0x103023f
-    field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974400; // 0x1030240
-    field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974401; // 0x1030241
-    field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974402; // 0x1030242
-    field public static final int Theme_Quantum_Light_Panel = 16974403; // 0x1030243
-    field public static final int Theme_Quantum_NoActionBar = 16974384; // 0x1030230
-    field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974385; // 0x1030231
-    field public static final int Theme_Quantum_NoActionBar_Overscan = 16974386; // 0x1030232
-    field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974387; // 0x1030233
-    field public static final int Theme_Quantum_Panel = 16974388; // 0x1030234
-    field public static final int Theme_Quantum_Wallpaper = 16974389; // 0x1030235
-    field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974390; // 0x1030236
+    field public static final int Theme_Quantum = 16974380; // 0x103022c
+    field public static final int Theme_Quantum_Dialog = 16974381; // 0x103022d
+    field public static final int Theme_Quantum_DialogWhenLarge = 16974385; // 0x1030231
+    field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974386; // 0x1030232
+    field public static final int Theme_Quantum_Dialog_MinWidth = 16974382; // 0x103022e
+    field public static final int Theme_Quantum_Dialog_NoActionBar = 16974383; // 0x103022f
+    field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974384; // 0x1030230
+    field public static final int Theme_Quantum_InputMethod = 16974387; // 0x1030233
+    field public static final int Theme_Quantum_Light = 16974395; // 0x103023b
+    field public static final int Theme_Quantum_Light_DarkActionBar = 16974396; // 0x103023c
+    field public static final int Theme_Quantum_Light_Dialog = 16974397; // 0x103023d
+    field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974401; // 0x1030241
+    field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974402; // 0x1030242
+    field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974398; // 0x103023e
+    field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974399; // 0x103023f
+    field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974400; // 0x1030240
+    field public static final int Theme_Quantum_Light_NoActionBar = 16974403; // 0x1030243
+    field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974404; // 0x1030244
+    field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974405; // 0x1030245
+    field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974406; // 0x1030246
+    field public static final int Theme_Quantum_Light_Panel = 16974407; // 0x1030247
+    field public static final int Theme_Quantum_NoActionBar = 16974388; // 0x1030234
+    field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974389; // 0x1030235
+    field public static final int Theme_Quantum_NoActionBar_Overscan = 16974390; // 0x1030236
+    field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974391; // 0x1030237
+    field public static final int Theme_Quantum_Panel = 16974392; // 0x1030238
+    field public static final int Theme_Quantum_Wallpaper = 16974393; // 0x1030239
+    field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974394; // 0x103023a
     field public static final int Theme_Translucent = 16973839; // 0x103000f
     field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010
     field public static final int Theme_Translucent_NoTitleBar_Fullscreen = 16973841; // 0x1030011
@@ -2047,18 +2059,18 @@
     field public static final int Widget_DeviceDefault_Light = 16974196; // 0x1030174
     field public static final int Widget_DeviceDefault_Light_ActionBar = 16974243; // 0x10301a3
     field public static final int Widget_DeviceDefault_Light_ActionBar_Solid = 16974247; // 0x10301a7
-    field public static final int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
+    field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
     field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar = 16974246; // 0x10301a6
-    field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
+    field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
     field public static final int Widget_DeviceDefault_Light_ActionBar_TabText = 16974245; // 0x10301a5
-    field public static final int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
+    field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
     field public static final int Widget_DeviceDefault_Light_ActionBar_TabView = 16974244; // 0x10301a4
-    field public static final int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
+    field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
     field public static final int Widget_DeviceDefault_Light_ActionButton = 16974239; // 0x103019f
     field public static final int Widget_DeviceDefault_Light_ActionButton_CloseMode = 16974242; // 0x10301a2
     field public static final int Widget_DeviceDefault_Light_ActionButton_Overflow = 16974240; // 0x10301a0
     field public static final int Widget_DeviceDefault_Light_ActionMode = 16974241; // 0x10301a1
-    field public static final int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
+    field public static final deprecated int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
     field public static final int Widget_DeviceDefault_Light_AutoCompleteTextView = 16974203; // 0x103017b
     field public static final int Widget_DeviceDefault_Light_Button = 16974197; // 0x1030175
     field public static final int Widget_DeviceDefault_Light_Button_Borderless_Small = 16974201; // 0x1030179
@@ -2186,6 +2198,7 @@
     field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127
     field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
     field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
+    field public static final int Widget_Holo_Light_Button_Borderless = 16974542; // 0x10302ce
     field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b
     field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8
     field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
@@ -2270,128 +2283,128 @@
     field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c
     field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e
     field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d
-    field public static final int Widget_Quantum = 16974404; // 0x1030244
-    field public static final int Widget_Quantum_ActionBar = 16974405; // 0x1030245
-    field public static final int Widget_Quantum_ActionBar_Solid = 16974406; // 0x1030246
-    field public static final int Widget_Quantum_ActionBar_TabBar = 16974407; // 0x1030247
-    field public static final int Widget_Quantum_ActionBar_TabText = 16974408; // 0x1030248
-    field public static final int Widget_Quantum_ActionBar_TabView = 16974409; // 0x1030249
-    field public static final int Widget_Quantum_ActionButton = 16974410; // 0x103024a
-    field public static final int Widget_Quantum_ActionButton_CloseMode = 16974411; // 0x103024b
-    field public static final int Widget_Quantum_ActionButton_Overflow = 16974412; // 0x103024c
-    field public static final int Widget_Quantum_ActionButton_TextButton = 16974413; // 0x103024d
-    field public static final int Widget_Quantum_ActionMode = 16974414; // 0x103024e
-    field public static final int Widget_Quantum_AutoCompleteTextView = 16974415; // 0x103024f
-    field public static final int Widget_Quantum_Button = 16974416; // 0x1030250
-    field public static final int Widget_Quantum_ButtonBar = 16974422; // 0x1030256
-    field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974423; // 0x1030257
-    field public static final int Widget_Quantum_Button_Borderless = 16974417; // 0x1030251
-    field public static final int Widget_Quantum_Button_Borderless_Small = 16974418; // 0x1030252
-    field public static final int Widget_Quantum_Button_Inset = 16974419; // 0x1030253
-    field public static final int Widget_Quantum_Button_Paper = 16974522; // 0x10302ba
-    field public static final int Widget_Quantum_Button_Paper_Color = 16974523; // 0x10302bb
-    field public static final int Widget_Quantum_Button_Small = 16974420; // 0x1030254
-    field public static final int Widget_Quantum_Button_Toggle = 16974421; // 0x1030255
-    field public static final int Widget_Quantum_CalendarView = 16974424; // 0x1030258
-    field public static final int Widget_Quantum_CheckedTextView = 16974425; // 0x1030259
-    field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974426; // 0x103025a
-    field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974427; // 0x103025b
-    field public static final int Widget_Quantum_CompoundButton_Star = 16974428; // 0x103025c
-    field public static final int Widget_Quantum_DatePicker = 16974429; // 0x103025d
-    field public static final int Widget_Quantum_DropDownItem = 16974430; // 0x103025e
-    field public static final int Widget_Quantum_DropDownItem_Spinner = 16974431; // 0x103025f
-    field public static final int Widget_Quantum_EditText = 16974432; // 0x1030260
-    field public static final int Widget_Quantum_ExpandableListView = 16974433; // 0x1030261
-    field public static final int Widget_Quantum_FastScroll = 16974434; // 0x1030262
-    field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974435; // 0x1030263
-    field public static final int Widget_Quantum_GridView = 16974436; // 0x1030264
-    field public static final int Widget_Quantum_HorizontalScrollView = 16974437; // 0x1030265
-    field public static final int Widget_Quantum_ImageButton = 16974438; // 0x1030266
-    field public static final int Widget_Quantum_Light = 16974463; // 0x103027f
-    field public static final int Widget_Quantum_Light_ActionBar = 16974464; // 0x1030280
-    field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974465; // 0x1030281
-    field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974466; // 0x1030282
-    field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974467; // 0x1030283
-    field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974468; // 0x1030284
-    field public static final int Widget_Quantum_Light_ActionButton = 16974469; // 0x1030285
-    field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974470; // 0x1030286
-    field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974471; // 0x1030287
-    field public static final int Widget_Quantum_Light_ActionMode = 16974472; // 0x1030288
-    field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974473; // 0x1030289
-    field public static final int Widget_Quantum_Light_Button = 16974474; // 0x103028a
-    field public static final int Widget_Quantum_Light_ButtonBar = 16974479; // 0x103028f
-    field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974480; // 0x1030290
-    field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974475; // 0x103028b
-    field public static final int Widget_Quantum_Light_Button_Inset = 16974476; // 0x103028c
-    field public static final int Widget_Quantum_Light_Button_Paper = 16974524; // 0x10302bc
-    field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974525; // 0x10302bd
-    field public static final int Widget_Quantum_Light_Button_Small = 16974477; // 0x103028d
-    field public static final int Widget_Quantum_Light_Button_Toggle = 16974478; // 0x103028e
-    field public static final int Widget_Quantum_Light_CalendarView = 16974481; // 0x1030291
-    field public static final int Widget_Quantum_Light_CheckedTextView = 16974482; // 0x1030292
-    field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974483; // 0x1030293
-    field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974484; // 0x1030294
-    field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974485; // 0x1030295
-    field public static final int Widget_Quantum_Light_DropDownItem = 16974486; // 0x1030296
-    field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974487; // 0x1030297
-    field public static final int Widget_Quantum_Light_EditText = 16974488; // 0x1030298
-    field public static final int Widget_Quantum_Light_ExpandableListView = 16974489; // 0x1030299
-    field public static final int Widget_Quantum_Light_FastScroll = 16974490; // 0x103029a
-    field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974491; // 0x103029b
-    field public static final int Widget_Quantum_Light_GridView = 16974492; // 0x103029c
-    field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974493; // 0x103029d
-    field public static final int Widget_Quantum_Light_ImageButton = 16974494; // 0x103029e
-    field public static final int Widget_Quantum_Light_ListPopupWindow = 16974495; // 0x103029f
-    field public static final int Widget_Quantum_Light_ListView = 16974496; // 0x10302a0
-    field public static final int Widget_Quantum_Light_ListView_DropDown = 16974497; // 0x10302a1
-    field public static final int Widget_Quantum_Light_MediaRouteButton = 16974498; // 0x10302a2
-    field public static final int Widget_Quantum_Light_PopupMenu = 16974499; // 0x10302a3
-    field public static final int Widget_Quantum_Light_PopupWindow = 16974500; // 0x10302a4
-    field public static final int Widget_Quantum_Light_ProgressBar = 16974501; // 0x10302a5
-    field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974502; // 0x10302a6
-    field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974503; // 0x10302a7
-    field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974504; // 0x10302a8
-    field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974505; // 0x10302a9
-    field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974506; // 0x10302aa
-    field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974507; // 0x10302ab
-    field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974508; // 0x10302ac
-    field public static final int Widget_Quantum_Light_RatingBar = 16974509; // 0x10302ad
-    field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974510; // 0x10302ae
-    field public static final int Widget_Quantum_Light_RatingBar_Small = 16974511; // 0x10302af
-    field public static final int Widget_Quantum_Light_ScrollView = 16974512; // 0x10302b0
-    field public static final int Widget_Quantum_Light_SeekBar = 16974513; // 0x10302b1
-    field public static final int Widget_Quantum_Light_SegmentedButton = 16974514; // 0x10302b2
-    field public static final int Widget_Quantum_Light_Spinner = 16974515; // 0x10302b3
-    field public static final int Widget_Quantum_Light_Tab = 16974516; // 0x10302b4
-    field public static final int Widget_Quantum_Light_TabWidget = 16974517; // 0x10302b5
-    field public static final int Widget_Quantum_Light_TextView = 16974518; // 0x10302b6
-    field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974519; // 0x10302b7
-    field public static final int Widget_Quantum_Light_WebTextView = 16974520; // 0x10302b8
-    field public static final int Widget_Quantum_Light_WebView = 16974521; // 0x10302b9
-    field public static final int Widget_Quantum_ListPopupWindow = 16974439; // 0x1030267
-    field public static final int Widget_Quantum_ListView = 16974440; // 0x1030268
-    field public static final int Widget_Quantum_ListView_DropDown = 16974441; // 0x1030269
-    field public static final int Widget_Quantum_MediaRouteButton = 16974442; // 0x103026a
-    field public static final int Widget_Quantum_PopupMenu = 16974443; // 0x103026b
-    field public static final int Widget_Quantum_PopupWindow = 16974444; // 0x103026c
-    field public static final int Widget_Quantum_ProgressBar = 16974445; // 0x103026d
-    field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974446; // 0x103026e
-    field public static final int Widget_Quantum_ProgressBar_Large = 16974447; // 0x103026f
-    field public static final int Widget_Quantum_ProgressBar_Small = 16974448; // 0x1030270
-    field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974449; // 0x1030271
-    field public static final int Widget_Quantum_RatingBar = 16974450; // 0x1030272
-    field public static final int Widget_Quantum_RatingBar_Indicator = 16974451; // 0x1030273
-    field public static final int Widget_Quantum_RatingBar_Small = 16974452; // 0x1030274
-    field public static final int Widget_Quantum_ScrollView = 16974453; // 0x1030275
-    field public static final int Widget_Quantum_SeekBar = 16974454; // 0x1030276
-    field public static final int Widget_Quantum_SegmentedButton = 16974455; // 0x1030277
-    field public static final int Widget_Quantum_Spinner = 16974456; // 0x1030278
-    field public static final int Widget_Quantum_Tab = 16974457; // 0x1030279
-    field public static final int Widget_Quantum_TabWidget = 16974458; // 0x103027a
-    field public static final int Widget_Quantum_TextView = 16974459; // 0x103027b
-    field public static final int Widget_Quantum_TextView_SpinnerItem = 16974460; // 0x103027c
-    field public static final int Widget_Quantum_WebTextView = 16974461; // 0x103027d
-    field public static final int Widget_Quantum_WebView = 16974462; // 0x103027e
+    field public static final int Widget_Quantum = 16974408; // 0x1030248
+    field public static final int Widget_Quantum_ActionBar = 16974409; // 0x1030249
+    field public static final int Widget_Quantum_ActionBar_Solid = 16974410; // 0x103024a
+    field public static final int Widget_Quantum_ActionBar_TabBar = 16974411; // 0x103024b
+    field public static final int Widget_Quantum_ActionBar_TabText = 16974412; // 0x103024c
+    field public static final int Widget_Quantum_ActionBar_TabView = 16974413; // 0x103024d
+    field public static final int Widget_Quantum_ActionButton = 16974414; // 0x103024e
+    field public static final int Widget_Quantum_ActionButton_CloseMode = 16974415; // 0x103024f
+    field public static final int Widget_Quantum_ActionButton_Overflow = 16974416; // 0x1030250
+    field public static final int Widget_Quantum_ActionButton_TextButton = 16974417; // 0x1030251
+    field public static final int Widget_Quantum_ActionMode = 16974418; // 0x1030252
+    field public static final int Widget_Quantum_AutoCompleteTextView = 16974419; // 0x1030253
+    field public static final int Widget_Quantum_Button = 16974420; // 0x1030254
+    field public static final int Widget_Quantum_ButtonBar = 16974426; // 0x103025a
+    field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974427; // 0x103025b
+    field public static final int Widget_Quantum_Button_Borderless = 16974421; // 0x1030255
+    field public static final int Widget_Quantum_Button_Borderless_Small = 16974422; // 0x1030256
+    field public static final int Widget_Quantum_Button_Inset = 16974423; // 0x1030257
+    field public static final int Widget_Quantum_Button_Paper = 16974526; // 0x10302be
+    field public static final int Widget_Quantum_Button_Paper_Color = 16974527; // 0x10302bf
+    field public static final int Widget_Quantum_Button_Small = 16974424; // 0x1030258
+    field public static final int Widget_Quantum_Button_Toggle = 16974425; // 0x1030259
+    field public static final int Widget_Quantum_CalendarView = 16974428; // 0x103025c
+    field public static final int Widget_Quantum_CheckedTextView = 16974429; // 0x103025d
+    field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974430; // 0x103025e
+    field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974431; // 0x103025f
+    field public static final int Widget_Quantum_CompoundButton_Star = 16974432; // 0x1030260
+    field public static final int Widget_Quantum_DatePicker = 16974433; // 0x1030261
+    field public static final int Widget_Quantum_DropDownItem = 16974434; // 0x1030262
+    field public static final int Widget_Quantum_DropDownItem_Spinner = 16974435; // 0x1030263
+    field public static final int Widget_Quantum_EditText = 16974436; // 0x1030264
+    field public static final int Widget_Quantum_ExpandableListView = 16974437; // 0x1030265
+    field public static final int Widget_Quantum_FastScroll = 16974438; // 0x1030266
+    field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974439; // 0x1030267
+    field public static final int Widget_Quantum_GridView = 16974440; // 0x1030268
+    field public static final int Widget_Quantum_HorizontalScrollView = 16974441; // 0x1030269
+    field public static final int Widget_Quantum_ImageButton = 16974442; // 0x103026a
+    field public static final int Widget_Quantum_Light = 16974467; // 0x1030283
+    field public static final int Widget_Quantum_Light_ActionBar = 16974468; // 0x1030284
+    field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974469; // 0x1030285
+    field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974470; // 0x1030286
+    field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974471; // 0x1030287
+    field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974472; // 0x1030288
+    field public static final int Widget_Quantum_Light_ActionButton = 16974473; // 0x1030289
+    field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974474; // 0x103028a
+    field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974475; // 0x103028b
+    field public static final int Widget_Quantum_Light_ActionMode = 16974476; // 0x103028c
+    field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974477; // 0x103028d
+    field public static final int Widget_Quantum_Light_Button = 16974478; // 0x103028e
+    field public static final int Widget_Quantum_Light_ButtonBar = 16974483; // 0x1030293
+    field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974484; // 0x1030294
+    field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974479; // 0x103028f
+    field public static final int Widget_Quantum_Light_Button_Inset = 16974480; // 0x1030290
+    field public static final int Widget_Quantum_Light_Button_Paper = 16974528; // 0x10302c0
+    field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974529; // 0x10302c1
+    field public static final int Widget_Quantum_Light_Button_Small = 16974481; // 0x1030291
+    field public static final int Widget_Quantum_Light_Button_Toggle = 16974482; // 0x1030292
+    field public static final int Widget_Quantum_Light_CalendarView = 16974485; // 0x1030295
+    field public static final int Widget_Quantum_Light_CheckedTextView = 16974486; // 0x1030296
+    field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974487; // 0x1030297
+    field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974488; // 0x1030298
+    field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974489; // 0x1030299
+    field public static final int Widget_Quantum_Light_DropDownItem = 16974490; // 0x103029a
+    field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974491; // 0x103029b
+    field public static final int Widget_Quantum_Light_EditText = 16974492; // 0x103029c
+    field public static final int Widget_Quantum_Light_ExpandableListView = 16974493; // 0x103029d
+    field public static final int Widget_Quantum_Light_FastScroll = 16974494; // 0x103029e
+    field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974495; // 0x103029f
+    field public static final int Widget_Quantum_Light_GridView = 16974496; // 0x10302a0
+    field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974497; // 0x10302a1
+    field public static final int Widget_Quantum_Light_ImageButton = 16974498; // 0x10302a2
+    field public static final int Widget_Quantum_Light_ListPopupWindow = 16974499; // 0x10302a3
+    field public static final int Widget_Quantum_Light_ListView = 16974500; // 0x10302a4
+    field public static final int Widget_Quantum_Light_ListView_DropDown = 16974501; // 0x10302a5
+    field public static final int Widget_Quantum_Light_MediaRouteButton = 16974502; // 0x10302a6
+    field public static final int Widget_Quantum_Light_PopupMenu = 16974503; // 0x10302a7
+    field public static final int Widget_Quantum_Light_PopupWindow = 16974504; // 0x10302a8
+    field public static final int Widget_Quantum_Light_ProgressBar = 16974505; // 0x10302a9
+    field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974506; // 0x10302aa
+    field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974507; // 0x10302ab
+    field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974508; // 0x10302ac
+    field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974509; // 0x10302ad
+    field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974510; // 0x10302ae
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974511; // 0x10302af
+    field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974512; // 0x10302b0
+    field public static final int Widget_Quantum_Light_RatingBar = 16974513; // 0x10302b1
+    field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974514; // 0x10302b2
+    field public static final int Widget_Quantum_Light_RatingBar_Small = 16974515; // 0x10302b3
+    field public static final int Widget_Quantum_Light_ScrollView = 16974516; // 0x10302b4
+    field public static final int Widget_Quantum_Light_SeekBar = 16974517; // 0x10302b5
+    field public static final int Widget_Quantum_Light_SegmentedButton = 16974518; // 0x10302b6
+    field public static final int Widget_Quantum_Light_Spinner = 16974519; // 0x10302b7
+    field public static final int Widget_Quantum_Light_Tab = 16974520; // 0x10302b8
+    field public static final int Widget_Quantum_Light_TabWidget = 16974521; // 0x10302b9
+    field public static final int Widget_Quantum_Light_TextView = 16974522; // 0x10302ba
+    field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974523; // 0x10302bb
+    field public static final int Widget_Quantum_Light_WebTextView = 16974524; // 0x10302bc
+    field public static final int Widget_Quantum_Light_WebView = 16974525; // 0x10302bd
+    field public static final int Widget_Quantum_ListPopupWindow = 16974443; // 0x103026b
+    field public static final int Widget_Quantum_ListView = 16974444; // 0x103026c
+    field public static final int Widget_Quantum_ListView_DropDown = 16974445; // 0x103026d
+    field public static final int Widget_Quantum_MediaRouteButton = 16974446; // 0x103026e
+    field public static final int Widget_Quantum_PopupMenu = 16974447; // 0x103026f
+    field public static final int Widget_Quantum_PopupWindow = 16974448; // 0x1030270
+    field public static final int Widget_Quantum_ProgressBar = 16974449; // 0x1030271
+    field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974450; // 0x1030272
+    field public static final int Widget_Quantum_ProgressBar_Large = 16974451; // 0x1030273
+    field public static final int Widget_Quantum_ProgressBar_Small = 16974452; // 0x1030274
+    field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974453; // 0x1030275
+    field public static final int Widget_Quantum_RatingBar = 16974454; // 0x1030276
+    field public static final int Widget_Quantum_RatingBar_Indicator = 16974455; // 0x1030277
+    field public static final int Widget_Quantum_RatingBar_Small = 16974456; // 0x1030278
+    field public static final int Widget_Quantum_ScrollView = 16974457; // 0x1030279
+    field public static final int Widget_Quantum_SeekBar = 16974458; // 0x103027a
+    field public static final int Widget_Quantum_SegmentedButton = 16974459; // 0x103027b
+    field public static final int Widget_Quantum_Spinner = 16974460; // 0x103027c
+    field public static final int Widget_Quantum_Tab = 16974461; // 0x103027d
+    field public static final int Widget_Quantum_TabWidget = 16974462; // 0x103027e
+    field public static final int Widget_Quantum_TextView = 16974463; // 0x103027f
+    field public static final int Widget_Quantum_TextView_SpinnerItem = 16974464; // 0x1030280
+    field public static final int Widget_Quantum_WebTextView = 16974465; // 0x1030281
+    field public static final int Widget_Quantum_WebView = 16974466; // 0x1030282
     field public static final int Widget_RatingBar = 16973857; // 0x1030021
     field public static final int Widget_ScrollView = 16973869; // 0x103002d
     field public static final int Widget_SeekBar = 16973856; // 0x1030020
@@ -3010,30 +3023,30 @@
   public abstract class ActionBar {
     ctor public ActionBar();
     method public abstract void addOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
-    method public abstract void addTab(android.app.ActionBar.Tab);
-    method public abstract void addTab(android.app.ActionBar.Tab, boolean);
-    method public abstract void addTab(android.app.ActionBar.Tab, int);
-    method public abstract void addTab(android.app.ActionBar.Tab, int, boolean);
+    method public abstract deprecated void addTab(android.app.ActionBar.Tab);
+    method public abstract deprecated void addTab(android.app.ActionBar.Tab, boolean);
+    method public abstract deprecated void addTab(android.app.ActionBar.Tab, int);
+    method public abstract deprecated void addTab(android.app.ActionBar.Tab, int, boolean);
     method public abstract android.view.View getCustomView();
     method public abstract int getDisplayOptions();
     method public abstract int getHeight();
-    method public abstract int getNavigationItemCount();
-    method public abstract int getNavigationMode();
-    method public abstract int getSelectedNavigationIndex();
-    method public abstract android.app.ActionBar.Tab getSelectedTab();
+    method public abstract deprecated int getNavigationItemCount();
+    method public abstract deprecated int getNavigationMode();
+    method public abstract deprecated int getSelectedNavigationIndex();
+    method public abstract deprecated android.app.ActionBar.Tab getSelectedTab();
     method public abstract java.lang.CharSequence getSubtitle();
-    method public abstract android.app.ActionBar.Tab getTabAt(int);
-    method public abstract int getTabCount();
+    method public abstract deprecated android.app.ActionBar.Tab getTabAt(int);
+    method public abstract deprecated int getTabCount();
     method public android.content.Context getThemedContext();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract void hide();
     method public abstract boolean isShowing();
-    method public abstract android.app.ActionBar.Tab newTab();
-    method public abstract void removeAllTabs();
+    method public abstract deprecated android.app.ActionBar.Tab newTab();
+    method public abstract deprecated void removeAllTabs();
     method public abstract void removeOnMenuVisibilityListener(android.app.ActionBar.OnMenuVisibilityListener);
-    method public abstract void removeTab(android.app.ActionBar.Tab);
-    method public abstract void removeTabAt(int);
-    method public abstract void selectTab(android.app.ActionBar.Tab);
+    method public abstract deprecated void removeTab(android.app.ActionBar.Tab);
+    method public abstract deprecated void removeTabAt(int);
+    method public abstract deprecated void selectTab(android.app.ActionBar.Tab);
     method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public abstract void setCustomView(android.view.View);
     method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
@@ -3052,11 +3065,11 @@
     method public void setHomeButtonEnabled(boolean);
     method public abstract void setIcon(int);
     method public abstract void setIcon(android.graphics.drawable.Drawable);
-    method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
+    method public abstract deprecated void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
     method public abstract void setLogo(int);
     method public abstract void setLogo(android.graphics.drawable.Drawable);
-    method public abstract void setNavigationMode(int);
-    method public abstract void setSelectedNavigationItem(int);
+    method public abstract deprecated void setNavigationMode(int);
+    method public abstract deprecated void setSelectedNavigationItem(int);
     method public void setSplitBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setStackedBackgroundDrawable(android.graphics.drawable.Drawable);
     method public abstract void setSubtitle(java.lang.CharSequence);
@@ -3069,9 +3082,9 @@
     field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
     field public static final int DISPLAY_SHOW_TITLE = 8; // 0x8
     field public static final int DISPLAY_USE_LOGO = 1; // 0x1
-    field public static final int NAVIGATION_MODE_LIST = 1; // 0x1
-    field public static final int NAVIGATION_MODE_STANDARD = 0; // 0x0
-    field public static final int NAVIGATION_MODE_TABS = 2; // 0x2
+    field public static final deprecated int NAVIGATION_MODE_LIST = 1; // 0x1
+    field public static final deprecated int NAVIGATION_MODE_STANDARD = 0; // 0x0
+    field public static final deprecated int NAVIGATION_MODE_TABS = 2; // 0x2
   }
 
   public static class ActionBar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
@@ -3081,6 +3094,7 @@
     ctor public ActionBar.LayoutParams(int);
     ctor public ActionBar.LayoutParams(android.app.ActionBar.LayoutParams);
     ctor public ActionBar.LayoutParams(android.view.ViewGroup.LayoutParams);
+    ctor public ActionBar.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
     field public int gravity;
   }
 
@@ -3088,11 +3102,11 @@
     method public abstract void onMenuVisibilityChanged(boolean);
   }
 
-  public static abstract interface ActionBar.OnNavigationListener {
+  public static abstract deprecated interface ActionBar.OnNavigationListener {
     method public abstract boolean onNavigationItemSelected(int, long);
   }
 
-  public static abstract class ActionBar.Tab {
+  public static abstract deprecated class ActionBar.Tab {
     ctor public ActionBar.Tab();
     method public abstract java.lang.CharSequence getContentDescription();
     method public abstract android.view.View getCustomView();
@@ -3114,7 +3128,7 @@
     field public static final int INVALID_POSITION = -1; // 0xffffffff
   }
 
-  public static abstract interface ActionBar.TabListener {
+  public static abstract deprecated interface ActionBar.TabListener {
     method public abstract void onTabReselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
     method public abstract void onTabSelected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
     method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
@@ -3140,6 +3154,7 @@
     method public void finishActivityFromChild(android.app.Activity, int);
     method public void finishAffinity();
     method public void finishFromChild(android.app.Activity);
+    method public void finishWithTransition();
     method public android.app.ActionBar getActionBar();
     method public final android.app.Application getApplication();
     method public android.content.ComponentName getCallingActivity();
@@ -3256,6 +3271,8 @@
     method public void reportFullyDrawn();
     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 setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(int);
     method public void setContentView(android.view.View);
@@ -3272,8 +3289,6 @@
     method public final void setProgressBarIndeterminate(boolean);
     method public final void setProgressBarIndeterminateVisibility(boolean);
     method public final void setProgressBarVisibility(boolean);
-    method public void setRecentsIcon(android.graphics.Bitmap);
-    method public void setRecentsLabel(java.lang.CharSequence);
     method public void setRequestedOrientation(int);
     method public final void setResult(int);
     method public final void setResult(int, android.content.Intent);
@@ -6464,6 +6479,7 @@
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
+    field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps";
     field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
     field public static final java.lang.String LOCATION_SERVICE = "location";
     field public static final java.lang.String MEDIA_ROUTER_SERVICE = "media_router";
@@ -6484,11 +6500,13 @@
     field public static final java.lang.String STORAGE_SERVICE = "storage";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+    field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
     field public static final java.lang.String UI_MODE_SERVICE = "uimode";
     field public static final java.lang.String USB_SERVICE = "usb";
     field public static final java.lang.String USER_SERVICE = "user";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
     field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+    field public static final java.lang.String WIFI_HOTSPOT_SERVICE = "wifihotspot";
     field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
     field public static final java.lang.String WIFI_SERVICE = "wifi";
     field public static final java.lang.String WINDOW_SERVICE = "window";
@@ -6829,6 +6847,8 @@
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
@@ -6920,6 +6940,7 @@
     field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
     field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK";
     field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY";
+    field public static final java.lang.String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
     field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
     field public static final java.lang.String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE";
     field public static final java.lang.String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE";
@@ -6977,6 +6998,7 @@
     field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
     field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
+    field public static final java.lang.String EXTRA_USER = "android.intent.extra.user";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
     field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -7633,6 +7655,32 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public class LauncherActivityInfo {
+    method public int getApplicationFlags();
+    method public android.graphics.drawable.Drawable getBadgedIcon(int);
+    method public android.content.ComponentName getComponentName();
+    method public long getFirstInstallTime();
+    method public android.graphics.drawable.Drawable getIcon(int);
+    method public java.lang.CharSequence getLabel();
+    method public android.os.UserHandle getUser();
+  }
+
+  public class LauncherApps {
+    method public synchronized void addOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
+    method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
+    method public synchronized void removeOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
+    method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
+    method public void startActivityForProfile(android.content.ComponentName, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+  }
+
+  public static abstract interface LauncherApps.OnAppsChangedListener {
+    method public abstract void onPackageAdded(android.os.UserHandle, java.lang.String);
+    method public abstract void onPackageChanged(android.os.UserHandle, java.lang.String);
+    method public abstract void onPackageRemoved(android.os.UserHandle, java.lang.String);
+    method public abstract void onPackagesAvailable(android.os.UserHandle, java.lang.String[], boolean);
+    method public abstract void onPackagesUnavailable(android.os.UserHandle, java.lang.String[], boolean);
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     ctor public PackageInfo();
     method public int describeContents();
@@ -7796,6 +7844,7 @@
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
     field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
     field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
+    field public static final java.lang.String FEATURE_MANAGEDPROFILES = "android.software.managedprofiles";
     field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
     field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
     field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
@@ -8145,6 +8194,7 @@
     field public static final int UI_MODE_TYPE_NORMAL = 1; // 0x1
     field public static final int UI_MODE_TYPE_TELEVISION = 4; // 0x4
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
@@ -10613,6 +10663,7 @@
     method public void applyTheme(android.content.res.Resources.Theme);
     method public boolean canApplyTheme();
     method public void clearColorFilter();
+    method public void clearHotspots();
     method public final void copyBounds(android.graphics.Rect);
     method public final android.graphics.Rect copyBounds();
     method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
@@ -10655,6 +10706,7 @@
     method protected void onBoundsChange(android.graphics.Rect);
     method protected boolean onLevelChange(int);
     method protected boolean onStateChange(int[]);
+    method public void removeHotspot(int);
     method public static int resolveOpacity(int, int);
     method public void scheduleSelf(java.lang.Runnable, long);
     method public abstract void setAlpha(int);
@@ -10667,9 +10719,11 @@
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
     method public void setDither(boolean);
     method public void setFilterBitmap(boolean);
+    method public void setHotspot(int, float, float);
     method public final boolean setLevel(int);
     method public boolean setState(int[]);
     method public boolean setVisible(boolean, boolean);
+    method public boolean supportsHotspots();
     method public void unscheduleSelf(java.lang.Runnable);
   }
 
@@ -10974,7 +11028,6 @@
     method public void setRepeatMode(int);
     method public void start();
     method public void stop();
-    field public static final int INFINITE = -1; // 0xffffffff
   }
 
 }
@@ -11539,6 +11592,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BASE_GAIN_FACTOR;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BLACK_LEVEL_PATTERN;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_EXPOSURE_TIME_RANGE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_MAX_FRAME_DURATION;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_PHYSICAL_SIZE;
@@ -11735,6 +11789,11 @@
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4; // 0x4
     field public static final int SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT = 1; // 0x1
     field public static final int SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT = 0; // 0x0
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
     field public static final int SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER = 10; // 0xa
     field public static final int SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14; // 0xe
     field public static final int SENSOR_REFERENCE_ILLUMINANT_D50 = 23; // 0x17
@@ -12079,11 +12138,16 @@
     field public static final int MESSAGE_VENDOR_COMMAND_WITH_ID = 160; // 0xa0
     field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_DOWN = 138; // 0x8a
     field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_UP = 139; // 0x8b
+    field public static final int POWER_STATUS_ON = 0; // 0x0
+    field public static final int POWER_STATUS_STANDBY = 1; // 0x1
+    field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff
+    field public static final int POWER_TRANSIENT_TO_ON = 2; // 0x2
+    field public static final int POWER_TRANSIENT_TO_STANDBY = 3; // 0x3
   }
 
   public final class HdmiCecClient {
+    method public boolean isTvOn();
     method public void sendActiveSource();
-    method public void sendGiveDevicePowerStatus(int);
     method public void sendImageViewOn();
     method public void sendInactiveSource();
     method public void sendTextViewOn();
@@ -12456,6 +12520,7 @@
     method public void setBackDisposition(int);
     method public void setCandidatesView(android.view.View);
     method public void setCandidatesViewShown(boolean);
+    method public void setCursorAnchorMonitorMode(int);
     method public void setExtractView(android.view.View);
     method public void setExtractViewShown(boolean);
     method public void setInputView(android.view.View);
@@ -12467,6 +12532,8 @@
     field public static final int BACK_DISPOSITION_DEFAULT = 0; // 0x0
     field public static final int BACK_DISPOSITION_WILL_DISMISS = 2; // 0x2
     field public static final int BACK_DISPOSITION_WILL_NOT_DISMISS = 1; // 0x1
+    field public static final int CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT = 1; // 0x1
+    field public static final int CURSOR_ANCHOR_MONITOR_MODE_NONE = 0; // 0x0
   }
 
   public class InputMethodService.InputMethodImpl extends android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl {
@@ -13145,7 +13212,7 @@
     method public int setPlaybackRate(int);
     method public int setPositionNotificationPeriod(int);
     method protected deprecated void setState(int);
-    method public int setStereoVolume(float, float);
+    method public deprecated int setStereoVolume(float, float);
     method public int setVolume(float);
     method public void stop() throws java.lang.IllegalStateException;
     method public int write(byte[], int, int);
@@ -16198,6 +16265,19 @@
 
 }
 
+package android.net.wifi.hotspot {
+
+  public abstract interface IWifiHotspotManager implements android.os.IInterface {
+    method public abstract void test() throws android.os.RemoteException;
+  }
+
+  public class WifiHotspotManager {
+    ctor public WifiHotspotManager(android.content.Context, android.net.wifi.hotspot.IWifiHotspotManager);
+    method public void test();
+  }
+
+}
+
 package android.net.wifi.p2p {
 
   public class WifiP2pConfig implements android.os.Parcelable {
@@ -19861,6 +19941,7 @@
     method public int getUserCount();
     method public android.os.UserHandle getUserForSerialNumber(long);
     method public java.lang.String getUserName();
+    method public java.util.List<android.os.UserHandle> getUserProfiles();
     method public android.os.Bundle getUserRestrictions();
     method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
     method public boolean isUserAGoat();
@@ -21173,6 +21254,16 @@
     field public static final deprecated android.net.Uri DELETED_CONTENT_URI;
     field public static final deprecated java.lang.String GROUP_ANDROID_STARRED = "Starred in Android";
     field public static final deprecated java.lang.String GROUP_MY_CONTACTS = "Contacts";
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT = "non_syncable";
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT_TYPE = "android.local";
+    field public static final java.lang.String _SYNC_ACCOUNT = "_sync_account";
+    field public static final java.lang.String _SYNC_ACCOUNT_TYPE = "_sync_account_type";
+    field public static final java.lang.String _SYNC_DIRTY = "_sync_dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+    field public static final java.lang.String _SYNC_LOCAL_ID = "_sync_local_id";
+    field public static final java.lang.String _SYNC_MARK = "_sync_mark";
+    field public static final java.lang.String _SYNC_TIME = "_sync_time";
+    field public static final java.lang.String _SYNC_VERSION = "_sync_version";
   }
 
   public static abstract deprecated interface Contacts.GroupsColumns {
@@ -21274,9 +21365,19 @@
     field public static final deprecated android.net.Uri CONTENT_URI;
     field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "name ASC";
     field public static final deprecated android.net.Uri DELETED_CONTENT_URI;
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT = "non_syncable";
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT_TYPE = "android.local";
     field public static final deprecated java.lang.String PRIMARY_EMAIL_ID = "primary_email";
     field public static final deprecated java.lang.String PRIMARY_ORGANIZATION_ID = "primary_organization";
     field public static final deprecated java.lang.String PRIMARY_PHONE_ID = "primary_phone";
+    field public static final java.lang.String _SYNC_ACCOUNT = "_sync_account";
+    field public static final java.lang.String _SYNC_ACCOUNT_TYPE = "_sync_account_type";
+    field public static final java.lang.String _SYNC_DIRTY = "_sync_dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+    field public static final java.lang.String _SYNC_LOCAL_ID = "_sync_local_id";
+    field public static final java.lang.String _SYNC_MARK = "_sync_mark";
+    field public static final java.lang.String _SYNC_TIME = "_sync_time";
+    field public static final java.lang.String _SYNC_VERSION = "_sync_version";
   }
 
   public static final deprecated class Contacts.People.ContactMethods implements android.provider.BaseColumns android.provider.Contacts.ContactMethodsColumns android.provider.Contacts.PeopleColumns {
@@ -21339,6 +21440,16 @@
     field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
     field public static final deprecated android.net.Uri CONTENT_URI;
     field public static final deprecated java.lang.String DEFAULT_SORT_ORDER = "person ASC";
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT = "non_syncable";
+    field public static final java.lang.String NON_SYNCABLE_ACCOUNT_TYPE = "android.local";
+    field public static final java.lang.String _SYNC_ACCOUNT = "_sync_account";
+    field public static final java.lang.String _SYNC_ACCOUNT_TYPE = "_sync_account_type";
+    field public static final java.lang.String _SYNC_DIRTY = "_sync_dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+    field public static final java.lang.String _SYNC_LOCAL_ID = "_sync_local_id";
+    field public static final java.lang.String _SYNC_MARK = "_sync_mark";
+    field public static final java.lang.String _SYNC_TIME = "_sync_time";
+    field public static final java.lang.String _SYNC_VERSION = "_sync_version";
   }
 
   public static abstract deprecated interface Contacts.PhotosColumns {
@@ -24316,9 +24427,14 @@
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
-    method public final void cancelNotification(java.lang.String, java.lang.String, int);
+    method public final deprecated void cancelNotification(java.lang.String, java.lang.String, int);
+    method public final void cancelNotification(java.lang.String);
+    method public final void cancelNotifications(java.lang.String[]);
+    method public java.lang.String[] getActiveNotificationKeys();
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+    method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
     method public android.os.IBinder onBind(android.content.Intent);
+    method public void onListenerConnected(java.lang.String[]);
     method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
@@ -24330,11 +24446,13 @@
     method public android.service.notification.StatusBarNotification clone();
     method public int describeContents();
     method public int getId();
+    method public java.lang.String getKey();
     method public android.app.Notification getNotification();
     method public java.lang.String getPackageName();
     method public long getPostTime();
     method public java.lang.String getTag();
-    method public int getUserId();
+    method public android.os.UserHandle getUser();
+    method public deprecated int getUserId();
     method public boolean isClearable();
     method public boolean isOngoing();
     method public void writeToParcel(android.os.Parcel, int);
@@ -24366,6 +24484,20 @@
 
 }
 
+package android.service.trust {
+
+  public class TrustAgentService extends android.app.Service {
+    ctor public TrustAgentService();
+    method protected final void enableTrust(java.lang.String, long, boolean);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method protected void onUnlockAttempt(boolean);
+    method protected final void revokeTrust();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.trust.TrustAgentService";
+    field public static final java.lang.String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -27352,6 +27484,16 @@
     method public void setResizeClip(boolean);
   }
 
+  public class CircularPropagation extends android.transition.VisibilityPropagation {
+    ctor public CircularPropagation();
+    method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+    method public void setPropagationSpeed(float);
+  }
+
+  public class Explode extends android.transition.Visibility {
+    ctor public Explode();
+  }
+
   public class Fade extends android.transition.Visibility {
     ctor public Fade();
     ctor public Fade(int);
@@ -27359,6 +27501,12 @@
     field public static final int OUT = 2; // 0x2
   }
 
+  public class MoveImage extends android.transition.Transition {
+    ctor public MoveImage();
+    method public void captureEndValues(android.transition.TransitionValues);
+    method public void captureStartValues(android.transition.TransitionValues);
+  }
+
   public final class Scene {
     ctor public Scene(android.view.ViewGroup);
     ctor public Scene(android.view.ViewGroup, android.view.View);
@@ -27371,6 +27519,27 @@
     method public void setExitAction(java.lang.Runnable);
   }
 
+  public class SidePropagation extends android.transition.VisibilityPropagation {
+    ctor public SidePropagation();
+    method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+    method public void setPropagationSpeed(float);
+    method public void setSide(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int TOP = 1; // 0x1
+  }
+
+  public class Slide extends android.transition.Visibility {
+    ctor public Slide();
+    ctor public Slide(int);
+    method public void setSlideEdge(int);
+    field public static final int BOTTOM = 3; // 0x3
+    field public static final int LEFT = 0; // 0x0
+    field public static final int RIGHT = 2; // 0x2
+    field public static final int TOP = 1; // 0x1
+  }
+
   public abstract class Transition implements java.lang.Cloneable {
     ctor public Transition();
     method public android.transition.Transition addListener(android.transition.Transition.TransitionListener);
@@ -27388,8 +27557,11 @@
     method public android.transition.Transition excludeTarget(android.view.View, boolean);
     method public android.transition.Transition excludeTarget(java.lang.Class, boolean);
     method public long getDuration();
+    method public android.graphics.Rect getEpicenter();
+    method public android.transition.Transition.EpicenterCallback getEpicenterCallback();
     method public android.animation.TimeInterpolator getInterpolator();
     method public java.lang.String getName();
+    method public android.transition.TransitionPropagation getPropagation();
     method public long getStartDelay();
     method public java.util.List<java.lang.Integer> getTargetIds();
     method public java.util.List<android.view.View> getTargets();
@@ -27399,10 +27571,17 @@
     method public android.transition.Transition removeTarget(int);
     method public android.transition.Transition removeTarget(android.view.View);
     method public android.transition.Transition setDuration(long);
+    method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback);
     method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator);
+    method public void setPropagation(android.transition.TransitionPropagation);
     method public android.transition.Transition setStartDelay(long);
   }
 
+  public static abstract class Transition.EpicenterCallback {
+    ctor public Transition.EpicenterCallback();
+    method public abstract android.graphics.Rect getEpicenter(android.transition.Transition);
+  }
+
   public static abstract interface Transition.TransitionListener {
     method public abstract void onTransitionCancel(android.transition.Transition);
     method public abstract void onTransitionEnd(android.transition.Transition);
@@ -27429,6 +27608,13 @@
     method public void transitionTo(android.transition.Scene);
   }
 
+  public abstract class TransitionPropagation {
+    ctor public TransitionPropagation();
+    method public abstract void captureValues(android.transition.TransitionValues);
+    method public abstract java.lang.String[] getPropagationProperties();
+    method public abstract long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
+  }
+
   public class TransitionSet extends android.transition.Transition {
     ctor public TransitionSet();
     method public android.transition.TransitionSet addTransition(android.transition.Transition);
@@ -27453,7 +27639,80 @@
     method public void captureStartValues(android.transition.TransitionValues);
     method public boolean isVisible(android.transition.TransitionValues);
     method public android.animation.Animator onAppear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int);
+    method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
     method public android.animation.Animator onDisappear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int);
+    method public android.animation.Animator onDisappear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
+  }
+
+  public abstract class VisibilityPropagation extends android.transition.TransitionPropagation {
+    ctor public VisibilityPropagation();
+    method public void captureValues(android.transition.TransitionValues);
+    method public java.lang.String[] getPropagationProperties();
+    method public int getViewVisibility(android.transition.TransitionValues);
+    method public int getViewX(android.transition.TransitionValues);
+    method public int getViewY(android.transition.TransitionValues);
+  }
+
+}
+
+package android.tv {
+
+  public final class TvInputInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getServiceName();
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public final class TvInputManager {
+    method public void createSession(android.content.ComponentName, android.tv.TvInputManager.SessionCreateCallback, android.os.Handler);
+    method public boolean getAvailability(android.content.ComponentName);
+    method public java.util.List<android.tv.TvInputInfo> getTvInputList();
+    method public void registerListener(android.content.ComponentName, android.tv.TvInputManager.TvInputListener, android.os.Handler);
+    method public void unregisterListener(android.content.ComponentName, android.tv.TvInputManager.TvInputListener);
+  }
+
+  public static final class TvInputManager.Session {
+    method public void release();
+    method public void setSurface(android.view.Surface);
+    method public void setVolume(float);
+    method public void tune(android.net.Uri);
+  }
+
+  public static abstract interface TvInputManager.SessionCreateCallback {
+    method public abstract void onSessionCreated(android.tv.TvInputManager.Session);
+  }
+
+  public static abstract class TvInputManager.TvInputListener {
+    ctor public TvInputManager.TvInputListener();
+    method public void onAvailabilityChanged(android.content.ComponentName, boolean);
+  }
+
+  public abstract class TvInputService extends android.app.Service {
+    ctor public TvInputService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.tv.TvInputService.TvInputSessionImpl onCreateSession();
+    method public final void setAvailable(boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.tv.TvInputService";
+  }
+
+  public static abstract class TvInputService.TvInputSessionImpl {
+    ctor public TvInputService.TvInputSessionImpl();
+    method public abstract void onRelease();
+    method public abstract boolean onSetSurface(android.view.Surface);
+    method public abstract void onSetVolume(float);
+    method public abstract boolean onTune(android.net.Uri);
+  }
+
+  public abstract class TvInputSession {
+    ctor public TvInputSession();
+    method public void release();
+    method public void setSurface(android.view.Surface);
+    method public void setVolume(float);
+    method public void tune(android.net.Uri);
   }
 
 }
@@ -27818,9 +28077,9 @@
     field public static final java.lang.String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
     field public static final java.util.regex.Pattern IP_ADDRESS;
     field public static final java.util.regex.Pattern PHONE;
-    field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN;
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
-    field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
+    field public static final deprecated java.util.regex.Pattern TOP_LEVEL_DOMAIN;
+    field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
+    field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
     field public static final java.util.regex.Pattern WEB_URL;
   }
 
@@ -28293,6 +28552,7 @@
     method public android.os.Vibrator getVibrator();
     method public boolean[] hasKeys(int...);
     method public boolean isVirtual();
+    method public boolean supportsSource(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int KEYBOARD_TYPE_ALPHABETIC = 2; // 0x2
@@ -29313,6 +29573,7 @@
     method protected int computeVerticalScrollRange();
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
     method public void createContextMenu(android.view.ContextMenu);
+    method public final android.animation.ValueAnimator createRevealAnimator(int, int, float, float);
     method public void destroyDrawingCache();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
@@ -30404,6 +30665,8 @@
     method public boolean requestFeature(int);
     method public abstract void restoreHierarchyState(android.os.Bundle);
     method public abstract android.os.Bundle saveHierarchyState();
+    method public void setAllowOverlappingEnterTransition(boolean);
+    method public void setAllowOverlappingExitTransition(boolean);
     method public void setAttributes(android.view.WindowManager.LayoutParams);
     method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setBackgroundDrawableResource(int);
@@ -30432,7 +30695,6 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract deprecated void setTitleColor(int);
     method public void setTransitionManager(android.transition.TransitionManager);
-    method public void setTriggerEarlyEnterTransition(boolean);
     method public void setType(int);
     method public void setUiOptions(int);
     method public void setUiOptions(int, int);
@@ -31792,6 +32054,9 @@
     method public static synchronized android.webkit.CookieSyncManager createInstance(android.content.Context);
     method public static synchronized android.webkit.CookieSyncManager getInstance();
     method protected void syncFromRamToFlash();
+    field protected static final java.lang.String LOGTAG = "websync";
+    field protected android.webkit.WebViewDatabase mDataBase;
+    field protected android.os.Handler mHandler;
   }
 
   public class DateSorter {
@@ -32466,6 +32731,7 @@
     method public android.view.Menu getMenu();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onDetachedFromWindow();
+    method public void setOnMenuItemClickListener(android.widget.ActionMenuView.OnMenuItemClickListener);
   }
 
   public static class ActionMenuView.LayoutParams extends android.widget.LinearLayout.LayoutParams {
@@ -32475,6 +32741,10 @@
     ctor public ActionMenuView.LayoutParams(int, int);
   }
 
+  public static abstract interface ActionMenuView.OnMenuItemClickListener {
+    method public abstract boolean onMenuItemClick(android.view.MenuItem);
+  }
+
   public abstract interface Adapter {
     method public abstract int getCount();
     method public abstract java.lang.Object getItem(int);
@@ -34628,6 +34898,50 @@
     method public void setTextOn(java.lang.CharSequence);
   }
 
+  public class Toolbar extends android.view.ViewGroup {
+    ctor public Toolbar(android.content.Context);
+    ctor public Toolbar(android.content.Context, android.util.AttributeSet);
+    ctor public Toolbar(android.content.Context, android.util.AttributeSet, int);
+    ctor public Toolbar(android.content.Context, android.util.AttributeSet, int, int);
+    method public android.graphics.drawable.Drawable getLogo();
+    method public java.lang.CharSequence getLogoDescription();
+    method public android.view.Menu getMenu();
+    method public android.graphics.drawable.Drawable getNavigationIcon();
+    method public java.lang.CharSequence getSubtitle();
+    method public java.lang.CharSequence getTitle();
+    method public void inflateMenu(int);
+    method protected void onLayout(boolean, int, int, int, int);
+    method public void setLogo(int);
+    method public void setLogo(android.graphics.drawable.Drawable);
+    method public void setLogoDescription(int);
+    method public void setLogoDescription(java.lang.CharSequence);
+    method public void setNavigationDescription(int);
+    method public void setNavigationDescription(java.lang.CharSequence);
+    method public void setNavigationIcon(int);
+    method public void setNavigationIcon(android.graphics.drawable.Drawable);
+    method public void setNavigationOnClickListener(android.view.View.OnClickListener);
+    method public void setOnMenuItemClickListener(android.widget.Toolbar.OnMenuItemClickListener);
+    method public void setSubtitle(int);
+    method public void setSubtitle(java.lang.CharSequence);
+    method public void setTitle(int);
+    method public void setTitle(java.lang.CharSequence);
+  }
+
+  public static class Toolbar.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
+    ctor public Toolbar.LayoutParams(android.content.Context, android.util.AttributeSet);
+    ctor public Toolbar.LayoutParams(int, int);
+    ctor public Toolbar.LayoutParams(int, int, int);
+    ctor public Toolbar.LayoutParams(int);
+    ctor public Toolbar.LayoutParams(android.widget.Toolbar.LayoutParams);
+    ctor public Toolbar.LayoutParams(android.view.ViewGroup.MarginLayoutParams);
+    ctor public Toolbar.LayoutParams(android.view.ViewGroup.LayoutParams);
+    field public int gravity;
+  }
+
+  public static abstract interface Toolbar.OnMenuItemClickListener {
+    method public abstract boolean onMenuItemClick(android.view.MenuItem);
+  }
+
   public deprecated class TwoLineListItem extends android.widget.RelativeLayout {
     ctor public TwoLineListItem(android.content.Context);
     ctor public TwoLineListItem(android.content.Context, android.util.AttributeSet);
@@ -46760,7 +47074,47 @@
     method public void setMethod(int);
     method public void setSize(long);
     method public void setTime(long);
+    field public static final int CENATT = 36; // 0x24
+    field public static final int CENATX = 38; // 0x26
+    field public static final int CENCOM = 32; // 0x20
+    field public static final int CENCRC = 16; // 0x10
+    field public static final int CENDSK = 34; // 0x22
+    field public static final int CENEXT = 30; // 0x1e
+    field public static final int CENFLG = 8; // 0x8
+    field public static final int CENHDR = 46; // 0x2e
+    field public static final int CENHOW = 10; // 0xa
+    field public static final int CENLEN = 24; // 0x18
+    field public static final int CENNAM = 28; // 0x1c
+    field public static final int CENOFF = 42; // 0x2a
+    field public static final long CENSIG = 33639248L; // 0x2014b50L
+    field public static final int CENSIZ = 20; // 0x14
+    field public static final int CENTIM = 12; // 0xc
+    field public static final int CENVEM = 4; // 0x4
+    field public static final int CENVER = 6; // 0x6
     field public static final int DEFLATED = 8; // 0x8
+    field public static final int ENDCOM = 20; // 0x14
+    field public static final int ENDHDR = 22; // 0x16
+    field public static final int ENDOFF = 16; // 0x10
+    field public static final long ENDSIG = 101010256L; // 0x6054b50L
+    field public static final int ENDSIZ = 12; // 0xc
+    field public static final int ENDSUB = 8; // 0x8
+    field public static final int ENDTOT = 10; // 0xa
+    field public static final int EXTCRC = 4; // 0x4
+    field public static final int EXTHDR = 16; // 0x10
+    field public static final int EXTLEN = 12; // 0xc
+    field public static final long EXTSIG = 134695760L; // 0x8074b50L
+    field public static final int EXTSIZ = 8; // 0x8
+    field public static final int LOCCRC = 14; // 0xe
+    field public static final int LOCEXT = 28; // 0x1c
+    field public static final int LOCFLG = 6; // 0x6
+    field public static final int LOCHDR = 30; // 0x1e
+    field public static final int LOCHOW = 8; // 0x8
+    field public static final int LOCLEN = 22; // 0x16
+    field public static final int LOCNAM = 26; // 0x1a
+    field public static final long LOCSIG = 67324752L; // 0x4034b50L
+    field public static final int LOCSIZ = 18; // 0x12
+    field public static final int LOCTIM = 10; // 0xa
+    field public static final int LOCVER = 4; // 0x4
     field public static final int STORED = 0; // 0x0
   }
 
@@ -46784,6 +47138,46 @@
     method public java.io.InputStream getInputStream(java.util.zip.ZipEntry) throws java.io.IOException;
     method public java.lang.String getName();
     method public int size();
+    field public static final int CENATT = 36; // 0x24
+    field public static final int CENATX = 38; // 0x26
+    field public static final int CENCOM = 32; // 0x20
+    field public static final int CENCRC = 16; // 0x10
+    field public static final int CENDSK = 34; // 0x22
+    field public static final int CENEXT = 30; // 0x1e
+    field public static final int CENFLG = 8; // 0x8
+    field public static final int CENHDR = 46; // 0x2e
+    field public static final int CENHOW = 10; // 0xa
+    field public static final int CENLEN = 24; // 0x18
+    field public static final int CENNAM = 28; // 0x1c
+    field public static final int CENOFF = 42; // 0x2a
+    field public static final long CENSIG = 33639248L; // 0x2014b50L
+    field public static final int CENSIZ = 20; // 0x14
+    field public static final int CENTIM = 12; // 0xc
+    field public static final int CENVEM = 4; // 0x4
+    field public static final int CENVER = 6; // 0x6
+    field public static final int ENDCOM = 20; // 0x14
+    field public static final int ENDHDR = 22; // 0x16
+    field public static final int ENDOFF = 16; // 0x10
+    field public static final long ENDSIG = 101010256L; // 0x6054b50L
+    field public static final int ENDSIZ = 12; // 0xc
+    field public static final int ENDSUB = 8; // 0x8
+    field public static final int ENDTOT = 10; // 0xa
+    field public static final int EXTCRC = 4; // 0x4
+    field public static final int EXTHDR = 16; // 0x10
+    field public static final int EXTLEN = 12; // 0xc
+    field public static final long EXTSIG = 134695760L; // 0x8074b50L
+    field public static final int EXTSIZ = 8; // 0x8
+    field public static final int LOCCRC = 14; // 0xe
+    field public static final int LOCEXT = 28; // 0x1c
+    field public static final int LOCFLG = 6; // 0x6
+    field public static final int LOCHDR = 30; // 0x1e
+    field public static final int LOCHOW = 8; // 0x8
+    field public static final int LOCLEN = 22; // 0x16
+    field public static final int LOCNAM = 26; // 0x1a
+    field public static final long LOCSIG = 67324752L; // 0x4034b50L
+    field public static final int LOCSIZ = 18; // 0x12
+    field public static final int LOCTIM = 10; // 0xa
+    field public static final int LOCVER = 4; // 0x4
     field public static final int OPEN_DELETE = 4; // 0x4
     field public static final int OPEN_READ = 1; // 0x1
   }
@@ -46793,6 +47187,46 @@
     method public void closeEntry() throws java.io.IOException;
     method protected java.util.zip.ZipEntry createZipEntry(java.lang.String);
     method public java.util.zip.ZipEntry getNextEntry() throws java.io.IOException;
+    field public static final int CENATT = 36; // 0x24
+    field public static final int CENATX = 38; // 0x26
+    field public static final int CENCOM = 32; // 0x20
+    field public static final int CENCRC = 16; // 0x10
+    field public static final int CENDSK = 34; // 0x22
+    field public static final int CENEXT = 30; // 0x1e
+    field public static final int CENFLG = 8; // 0x8
+    field public static final int CENHDR = 46; // 0x2e
+    field public static final int CENHOW = 10; // 0xa
+    field public static final int CENLEN = 24; // 0x18
+    field public static final int CENNAM = 28; // 0x1c
+    field public static final int CENOFF = 42; // 0x2a
+    field public static final long CENSIG = 33639248L; // 0x2014b50L
+    field public static final int CENSIZ = 20; // 0x14
+    field public static final int CENTIM = 12; // 0xc
+    field public static final int CENVEM = 4; // 0x4
+    field public static final int CENVER = 6; // 0x6
+    field public static final int ENDCOM = 20; // 0x14
+    field public static final int ENDHDR = 22; // 0x16
+    field public static final int ENDOFF = 16; // 0x10
+    field public static final long ENDSIG = 101010256L; // 0x6054b50L
+    field public static final int ENDSIZ = 12; // 0xc
+    field public static final int ENDSUB = 8; // 0x8
+    field public static final int ENDTOT = 10; // 0xa
+    field public static final int EXTCRC = 4; // 0x4
+    field public static final int EXTHDR = 16; // 0x10
+    field public static final int EXTLEN = 12; // 0xc
+    field public static final long EXTSIG = 134695760L; // 0x8074b50L
+    field public static final int EXTSIZ = 8; // 0x8
+    field public static final int LOCCRC = 14; // 0xe
+    field public static final int LOCEXT = 28; // 0x1c
+    field public static final int LOCFLG = 6; // 0x6
+    field public static final int LOCHDR = 30; // 0x1e
+    field public static final int LOCHOW = 8; // 0x8
+    field public static final int LOCLEN = 22; // 0x16
+    field public static final int LOCNAM = 26; // 0x1a
+    field public static final long LOCSIG = 67324752L; // 0x4034b50L
+    field public static final int LOCSIZ = 18; // 0x12
+    field public static final int LOCTIM = 10; // 0xa
+    field public static final int LOCVER = 4; // 0x4
   }
 
   public class ZipOutputStream extends java.util.zip.DeflaterOutputStream {
@@ -46802,7 +47236,47 @@
     method public void setComment(java.lang.String);
     method public void setLevel(int);
     method public void setMethod(int);
+    field public static final int CENATT = 36; // 0x24
+    field public static final int CENATX = 38; // 0x26
+    field public static final int CENCOM = 32; // 0x20
+    field public static final int CENCRC = 16; // 0x10
+    field public static final int CENDSK = 34; // 0x22
+    field public static final int CENEXT = 30; // 0x1e
+    field public static final int CENFLG = 8; // 0x8
+    field public static final int CENHDR = 46; // 0x2e
+    field public static final int CENHOW = 10; // 0xa
+    field public static final int CENLEN = 24; // 0x18
+    field public static final int CENNAM = 28; // 0x1c
+    field public static final int CENOFF = 42; // 0x2a
+    field public static final long CENSIG = 33639248L; // 0x2014b50L
+    field public static final int CENSIZ = 20; // 0x14
+    field public static final int CENTIM = 12; // 0xc
+    field public static final int CENVEM = 4; // 0x4
+    field public static final int CENVER = 6; // 0x6
     field public static final int DEFLATED = 8; // 0x8
+    field public static final int ENDCOM = 20; // 0x14
+    field public static final int ENDHDR = 22; // 0x16
+    field public static final int ENDOFF = 16; // 0x10
+    field public static final long ENDSIG = 101010256L; // 0x6054b50L
+    field public static final int ENDSIZ = 12; // 0xc
+    field public static final int ENDSUB = 8; // 0x8
+    field public static final int ENDTOT = 10; // 0xa
+    field public static final int EXTCRC = 4; // 0x4
+    field public static final int EXTHDR = 16; // 0x10
+    field public static final int EXTLEN = 12; // 0xc
+    field public static final long EXTSIG = 134695760L; // 0x8074b50L
+    field public static final int EXTSIZ = 8; // 0x8
+    field public static final int LOCCRC = 14; // 0xe
+    field public static final int LOCEXT = 28; // 0x1c
+    field public static final int LOCFLG = 6; // 0x6
+    field public static final int LOCHDR = 30; // 0x1e
+    field public static final int LOCHOW = 8; // 0x8
+    field public static final int LOCLEN = 22; // 0x16
+    field public static final int LOCNAM = 26; // 0x1a
+    field public static final long LOCSIG = 67324752L; // 0x4034b50L
+    field public static final int LOCSIZ = 18; // 0x12
+    field public static final int LOCTIM = 10; // 0xa
+    field public static final int LOCVER = 4; // 0x4
     field public static final int STORED = 0; // 0x0
   }
 
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8d2b739..bdbb08c 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -30,8 +30,9 @@
 class AppRuntime : public AndroidRuntime
 {
 public:
-    AppRuntime()
-        : mParentDir(NULL)
+    AppRuntime(char* argBlockStart, const size_t argBlockLength)
+        : AndroidRuntime(argBlockStart, argBlockLength)
+        , mParentDir(NULL)
         , mClassName(NULL)
         , mClass(NULL)
         , mArgC(0)
@@ -125,29 +126,30 @@
 
 using namespace android;
 
-/*
- * sets argv0 to as much of newArgv0 as will fit
- */
-static void setArgv0(const char *argv0, const char *newArgv0)
-{
-    strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+static size_t computeArgBlockSize(int argc, char* const argv[]) {
+    // TODO: This assumes that all arguments are allocated in
+    // contiguous memory. There isn't any documented guarantee
+    // that this is the case, but this is how the kernel does it
+    // (see fs/exec.c).
+    //
+    // Also note that this is a constant for "normal" android apps.
+    // Since they're forked from zygote, the size of their command line
+    // is the size of the zygote command line.
+    //
+    // We change the process name of the process by over-writing
+    // the start of the argument block (argv[0]) with the new name of
+    // the process, so we'd mysteriously start getting truncated process
+    // names if the zygote command line decreases in size.
+    uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
+    uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]);
+    end += strlen(argv[argc - 1]);
+
+    return (end - start);
 }
 
 int main(int argc, char* const argv[])
 {
-    // These are global variables in ProcessState.cpp
-    mArgC = argc;
-    mArgV = argv;
-
-    mArgLen = 0;
-    for (int i=0; i<argc; i++) {
-        mArgLen += strlen(argv[i]) + 1;
-    }
-    mArgLen--;
-
-    AppRuntime runtime;
-    const char* argv0 = argv[0];
-
+    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
     // Process command line arguments
     // ignore argv[0]
     argc--;
@@ -184,7 +186,7 @@
     }
 
     if (niceName && *niceName) {
-        setArgv0(argv0, niceName);
+        runtime.setArgv0(niceName);
         set_process_name(niceName);
     }
 
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index f415c85..5454b46 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1033,18 +1033,18 @@
 
     public void runCreateUser() {
         String name;
-        int relatedUserId = -1;
+        int userId = -1;
         int flags = 0;
         String opt;
         while ((opt = nextOption()) != null) {
-            if ("--relatedTo".equals(opt)) {
+            if ("--profileOf".equals(opt)) {
                 String optionData = nextOptionData();
                 if (optionData == null || !isNumber(optionData)) {
                     System.err.println("Error: no USER_ID specified");
                     showUsage();
                     return;
                 } else {
-                    relatedUserId = Integer.parseInt(optionData);
+                    userId = Integer.parseInt(optionData);
                 }
             } else if ("--managed".equals(opt)) {
                 flags |= UserInfo.FLAG_MANAGED_PROFILE;
@@ -1062,14 +1062,14 @@
         name = arg;
         try {
             UserInfo info = null;
-            if (relatedUserId < 0) {
+            if (userId < 0) {
                 info = mUm.createUser(name, flags);
             } else {
                 if (Process.myUid() != 0) {
                     System.err.println("Error: not running as root.");
                     return;
                 }
-                info = mUm.createRelatedUser(name, flags, relatedUserId);
+                info = mUm.createProfileForUser(name, flags, userId);
             }
             if (info != null) {
                 System.out.println("Success: created user id " + info.id);
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java
new file mode 100644
index 0000000..77a536a
--- /dev/null
+++ b/core/java/android/animation/RevealAnimator.java
@@ -0,0 +1,141 @@
+/*
+ * 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.animation;
+
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Reveals a View with an animated clipping circle.
+ * The clipping is implemented efficiently by talking to a private reveal API on View.
+ * This hidden class currently only accessed by the {@link android.view.View}.
+ *
+ * @hide
+ */
+public class RevealAnimator extends ValueAnimator {
+    private final static String LOGTAG = "RevealAnimator";
+    private ValueAnimator.AnimatorListener mListener;
+    private ValueAnimator.AnimatorUpdateListener mUpdateListener;
+    private RevealCircle mReuseRevealCircle = new RevealCircle(0);
+    private RevealAnimator(final View clipView, final int x, final int y,
+            float startRadius, float endRadius, final boolean inverseClip) {
+
+        setObjectValues(new RevealCircle(startRadius), new RevealCircle(endRadius));
+        setEvaluator(new RevealCircleEvaluator(mReuseRevealCircle));
+
+        mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                RevealCircle circle = (RevealCircle) animation.getAnimatedValue();
+                float radius = circle.getRadius();
+                clipView.setRevealClip(true, inverseClip, x, y, radius);
+            }
+        };
+        mListener = new AnimatorListenerAdapter() {
+                @Override
+            public void onAnimationCancel(Animator animation) {
+                clipView.setRevealClip(false, false, 0, 0, 0);
+            }
+
+                @Override
+            public void onAnimationEnd(Animator animation) {
+                clipView.setRevealClip(false, false, 0, 0, 0);
+            }
+        };
+        addUpdateListener(mUpdateListener);
+        addListener(mListener);
+    }
+
+    public static RevealAnimator ofRevealCircle(View clipView, int x, int y,
+            float startRadius, float endRadius, boolean inverseClip) {
+        RevealAnimator anim = new RevealAnimator(clipView, x, y,
+                startRadius, endRadius, inverseClip);
+        return anim;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void removeAllUpdateListeners() {
+        super.removeAllUpdateListeners();
+        addUpdateListener(mUpdateListener);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void removeAllListeners() {
+        super.removeAllListeners();
+        addListener(mListener);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ArrayList<AnimatorListener> getListeners() {
+        ArrayList<AnimatorListener> allListeners =
+                (ArrayList<AnimatorListener>) super.getListeners().clone();
+        allListeners.remove(mListener);
+        return allListeners;
+    }
+
+    private class RevealCircle {
+        float mRadius;
+
+        public RevealCircle(float radius) {
+            mRadius = radius;
+        }
+
+        public void setRadius(float radius) {
+            mRadius = radius;
+        }
+
+        public float getRadius() {
+            return mRadius;
+        }
+    }
+
+    private class RevealCircleEvaluator implements TypeEvaluator<RevealCircle> {
+
+        private RevealCircle mRevealCircle;
+
+        public RevealCircleEvaluator() {
+        }
+
+        public RevealCircleEvaluator(RevealCircle reuseCircle) {
+            mRevealCircle = reuseCircle;
+        }
+
+        @Override
+        public RevealCircle evaluate(float fraction, RevealCircle startValue,
+                RevealCircle endValue) {
+            float currentRadius = startValue.mRadius
+                    + ((endValue.mRadius - startValue.mRadius) * fraction);
+            if (mRevealCircle == null) {
+                return new RevealCircle(currentRadius);
+            } else {
+                mRevealCircle.setRadius(currentRadius);
+                return mRevealCircle;
+            }
+        }
+    }
+}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index fbe8987..34b0f3a 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -20,9 +20,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewDebug;
@@ -30,31 +32,57 @@
 import android.view.ViewGroup.MarginLayoutParams;
 import android.view.Window;
 import android.widget.SpinnerAdapter;
+import android.widget.Toolbar;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
 
 /**
- * A window feature at the top of the activity that may display the activity title, navigation
- * modes, and other interactive items.
+ * A primary toolbar within the activity that may display the activity title, application-level
+ * navigation affordances, and other interactive items.
+ *
  * <p>Beginning with Android 3.0 (API level 11), the action bar appears at the top of an
  * activity's window when the activity uses the system's {@link
  * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default.
  * You may otherwise add the action bar by calling {@link
  * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a
  * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property.
- * <p>By default, the action bar shows the application icon on
+ * </p>
+ *
+ * <p>Beginning with Android L (API level 21), the action bar may be represented by any
+ * Toolbar widget within the application layout. The application may signal to the Activity
+ * which Toolbar should be treated as the Activity's action bar. Activities that use this
+ * feature should use one of the supplied <code>.NoActionBar</code> themes, set the
+ * {@link android.R.styleable#Theme_windowActionBar windowActionBar} attribute to <code>false</code>
+ * or otherwise not request the window feature.</p>
+ *
+ * <p>By adjusting the window features requested by the theme and the layouts used for
+ * an Activity's content view, an app can use the standard system action bar on older platform
+ * releases and the newer inline toolbars on newer platform releases. The <code>ActionBar</code>
+ * object obtained from the Activity can be used to control either configuration transparently.</p>
+ *
+ * <p>When using the Holo themes the action bar shows the application icon on
  * the left, followed by the activity title. If your activity has an options menu, you can make
  * select items accessible directly from the action bar as "action items". You can also
  * modify various characteristics of the action bar or remove it completely.</p>
+ *
+ * <p>When using the Quantum themes (default in API 21 or newer) the navigation button
+ * (formerly "Home") takes over the space previously occupied by the application icon.
+ * Apps wishing to express a stronger branding should use their brand colors heavily
+ * in the action bar and other application chrome or use a {@link #setLogo(int) logo}
+ * in place of their standard title text.</p>
+ *
  * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
  * android.app.Activity#getActionBar getActionBar()}.</p>
+ *
  * <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions,
  * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in
  * your activity, you can enable an action mode that offers actions specific to the selected
  * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the
  * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for
- * {@link ActionBar}.
+ * {@link ActionBar}.</p>
+ *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For information about how to use the action bar, including how to add action items, navigation
@@ -73,6 +101,11 @@
      * and title text with an optional subtitle. Clicking any of these elements
      * will dispatch onOptionsItemSelected to the host Activity with
      * a MenuItem with item ID android.R.id.home.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public static final int NAVIGATION_MODE_STANDARD = 0;
     
@@ -80,12 +113,22 @@
      * List navigation mode. Instead of static title text this mode
      * presents a list menu for navigation within the activity.
      * e.g. this might be presented to the user as a dropdown list.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public static final int NAVIGATION_MODE_LIST = 1;
     
     /**
      * Tab navigation mode. Instead of static title text this mode
      * presents a series of tabs for navigation within the activity.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public static final int NAVIGATION_MODE_TABS = 2;
 
@@ -288,6 +331,11 @@
      *                within the dropdown navigation menu.
      * @param callback An OnNavigationListener that will receive events when the user
      *                 selects a navigation item.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void setListNavigationCallbacks(SpinnerAdapter adapter,
             OnNavigationListener callback);
@@ -296,6 +344,11 @@
      * Set the selected navigation item in list or tabbed navigation modes.
      *
      * @param position Position of the item to select.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void setSelectedNavigationItem(int position);
 
@@ -303,6 +356,11 @@
      * Get the position of the selected navigation item in list or tabbed navigation modes.
      *
      * @return Position of the selected item.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract int getSelectedNavigationIndex();
 
@@ -310,6 +368,11 @@
      * Get the number of navigation items present in the current navigation mode.
      *
      * @return Number of navigation items.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract int getNavigationItemCount();
 
@@ -507,6 +570,11 @@
      * </ul>
      *
      * @return The current navigation mode.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     @NavigationMode
     public abstract int getNavigationMode();
@@ -518,6 +586,11 @@
      * @see #NAVIGATION_MODE_STANDARD
      * @see #NAVIGATION_MODE_LIST
      * @see #NAVIGATION_MODE_TABS
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void setNavigationMode(@NavigationMode int mode);
 
@@ -539,6 +612,11 @@
      * @return A new Tab
      *
      * @see #addTab(Tab)
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract Tab newTab();
 
@@ -547,6 +625,11 @@
      * If this is the first tab to be added it will become the selected tab.
      *
      * @param tab Tab to add
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void addTab(Tab tab);
 
@@ -555,6 +638,11 @@
      *
      * @param tab Tab to add
      * @param setSelected True if the added tab should become the selected tab.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void addTab(Tab tab, boolean setSelected);
 
@@ -565,6 +653,11 @@
      *
      * @param tab The tab to add
      * @param position The new position of the tab
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void addTab(Tab tab, int position);
 
@@ -575,6 +668,11 @@
      * @param tab The tab to add
      * @param position The new position of the tab
      * @param setSelected True if the added tab should become the selected tab.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void addTab(Tab tab, int position, boolean setSelected);
 
@@ -583,6 +681,11 @@
      * and another tab will be selected if present.
      *
      * @param tab The tab to remove
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void removeTab(Tab tab);
 
@@ -591,11 +694,21 @@
      * and another tab will be selected if present.
      *
      * @param position Position of the tab to remove
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void removeTabAt(int position);
 
     /**
      * Remove all tabs from the action bar and deselect the current tab.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void removeAllTabs();
 
@@ -605,6 +718,11 @@
      * <p>Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.</p>
      *
      * @param tab Tab to select
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract void selectTab(Tab tab);
 
@@ -613,6 +731,11 @@
      * one tab present.
      *
      * @return The currently selected tab or null
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract Tab getSelectedTab();
 
@@ -621,12 +744,22 @@
      *
      * @param index Index value in the range 0-get
      * @return
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract Tab getTabAt(int index);
 
     /**
      * Returns the number of tabs currently registered with the action bar.
      * @return Tab count
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public abstract int getTabCount();
 
@@ -799,8 +932,38 @@
      */
     public void setHomeActionContentDescription(int resId) { }
 
+    /** @hide */
+    public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) {
+    }
+
+    /** @hide */
+    public void setShowHideAnimationEnabled(boolean enabled) {
+    }
+
+    /** @hide */
+    public void onConfigurationChanged(Configuration config) {
+    }
+
+    /** @hide */
+    public void dispatchMenuVisibilityChanged(boolean visible) {
+    }
+
+    /** @hide */
+    public void captureSharedElements(Map<String, View> sharedElements) {
+    }
+
+    /** @hide */
+    public ActionMode startActionMode(ActionMode.Callback callback) {
+        return null;
+    }
+
     /**
      * Listener interface for ActionBar navigation events.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public interface OnNavigationListener {
         /**
@@ -833,6 +996,11 @@
      * A tab in the action bar.
      *
      * <p>Tabs manage the hiding and showing of {@link Fragment}s.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public static abstract class Tab {
         /**
@@ -984,6 +1152,11 @@
 
     /**
      * Callback interface invoked when a tab is focused, unfocused, added, or removed.
+     *
+     * @deprecated Action bar navigation modes are deprecated and not supported by inline
+     * toolbar action bars. Consider using other
+     * <a href="http://developer.android.com/design/patterns/navigation.html">common
+     * navigation patterns</a> instead.
      */
     public interface TabListener {
         /**
@@ -1025,27 +1198,27 @@
      *
      * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity
      */
-    public static class LayoutParams extends MarginLayoutParams {
+    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
         /**
          * Gravity for the view associated with these LayoutParams.
          *
          * @see android.view.Gravity
          */
         @ViewDebug.ExportedProperty(category = "layout", mapping = {
-            @ViewDebug.IntToString(from =  -1,                       to = "NONE"),
-            @ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
-            @ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
-            @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
-            @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
-            @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
-            @ViewDebug.IntToString(from = Gravity.START,             to = "START"),
-            @ViewDebug.IntToString(from = Gravity.END,               to = "END"),
-            @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
-            @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
-            @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
-            @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
-            @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
-            @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
+                @ViewDebug.IntToString(from =  -1,                       to = "NONE"),
+                @ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
+                @ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
+                @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
+                @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
+                @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
+                @ViewDebug.IntToString(from = Gravity.START,             to = "START"),
+                @ViewDebug.IntToString(from = Gravity.END,               to = "END"),
+                @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
+                @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
+                @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
+                @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
+                @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
+                @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
         })
         public int gravity = Gravity.NO_GRAVITY;
 
@@ -1062,12 +1235,10 @@
 
         public LayoutParams(int width, int height) {
             super(width, height);
-            this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
         }
 
         public LayoutParams(int width, int height, int gravity) {
             super(width, height);
-            this.gravity = gravity;
         }
 
         public LayoutParams(int gravity) {
@@ -1076,12 +1247,14 @@
 
         public LayoutParams(LayoutParams source) {
             super(source);
-
-            this.gravity = source.gravity;
         }
 
         public LayoutParams(ViewGroup.LayoutParams source) {
             super(source);
         }
+
+        public LayoutParams(MarginLayoutParams source) {
+            super(source);
+        }
     }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e38bbb3..b18eb98 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -21,9 +21,10 @@
 import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
-import android.util.Pair;
 import android.util.SuperNotCalledException;
-import com.android.internal.app.ActionBarImpl;
+import android.widget.Toolbar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.policy.PolicyManager;
 
 import android.annotation.IntDef;
@@ -723,7 +724,7 @@
     /*package*/ boolean mWindowAdded = false;
     /*package*/ boolean mVisibleFromServer = false;
     /*package*/ boolean mVisibleFromClient = true;
-    /*package*/ ActionBarImpl mActionBar = null;
+    /*package*/ ActionBar mActionBar = null;
     private boolean mEnableDefaultActionBarUp;
 
     private CharSequence mTitle;
@@ -772,7 +773,6 @@
 
     private Thread mUiThread;
     final Handler mHandler = new Handler();
-    private ActivityOptions mTransitionActivityOptions;
 
     /** Return the intent that started this activity. */
     public Intent getIntent() {
@@ -1398,6 +1398,9 @@
     protected void onStop() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
         if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
+        if (mWindow != null) {
+            mWindow.restoreViewVisibilityAfterTransitionToCallee();
+        }
         getApplication().dispatchActivityStopped(this);
         mTranslucentCallback = null;
         mCalled = true;
@@ -1906,15 +1909,39 @@
      */
     @Nullable
     public ActionBar getActionBar() {
-        initActionBar();
+        initWindowDecorActionBar();
         return mActionBar;
     }
+
+    /**
+     * Set a {@link android.widget.Toolbar Toolbar} to act as the {@link ActionBar} for this
+     * Activity window.
+     *
+     * <p>When set to a non-null value the {@link #getActionBar()} method will return
+     * an {@link ActionBar} object that can be used to control the given toolbar as if it were
+     * a traditional window decor action bar. The toolbar's menu will be populated with the
+     * Activity's options menu and the navigation button will be wired through the standard
+     * {@link android.R.id#home home} menu select action.</p>
+     *
+     * <p>In order to use a Toolbar within the Activity's window content the application
+     * must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
+     *
+     * @param actionBar Toolbar to set as the Activity's action bar
+     */
+    public void setActionBar(@Nullable Toolbar actionBar) {
+        if (getActionBar() instanceof WindowDecorActionBar) {
+            throw new IllegalStateException("This Activity already has an action bar supplied " +
+                    "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " +
+                    "android:windowActionBar to false in your theme to use a Toolbar instead.");
+        }
+        mActionBar = new ToolbarActionBar(actionBar);
+    }
     
     /**
      * Creates a new ActionBar, locates the inflated ActionBarView,
      * initializes the ActionBar with the view, and sets mActionBar.
      */
-    private void initActionBar() {
+    private void initWindowDecorActionBar() {
         Window window = getWindow();
 
         // Initializing the window decor can change window feature flags.
@@ -1925,7 +1952,7 @@
             return;
         }
 
-        mActionBar = new ActionBarImpl(this);
+        mActionBar = new WindowDecorActionBar(this);
         mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
 
         mWindow.setDefaultIcon(mActivityInfo.getIconResource());
@@ -1943,7 +1970,7 @@
      */
     public void setContentView(int layoutResID) {
         getWindow().setContentView(layoutResID);
-        initActionBar();
+        initWindowDecorActionBar();
     }
 
     /**
@@ -1963,7 +1990,7 @@
      */
     public void setContentView(View view) {
         getWindow().setContentView(view);
-        initActionBar();
+        initWindowDecorActionBar();
     }
 
     /**
@@ -1979,7 +2006,7 @@
      */
     public void setContentView(View view, ViewGroup.LayoutParams params) {
         getWindow().setContentView(view, params);
-        initActionBar();
+        initWindowDecorActionBar();
     }
 
     /**
@@ -1991,7 +2018,7 @@
      */
     public void addContentView(View view, ViewGroup.LayoutParams params) {
         getWindow().addContentView(view, params);
-        initActionBar();
+        initWindowDecorActionBar();
     }
 
     /**
@@ -2274,7 +2301,7 @@
      */
     public void onBackPressed() {
         if (!mFragments.popBackStackImmediate()) {
-            finish();
+            finishWithTransition();
         }
     }
 
@@ -2636,7 +2663,7 @@
      */
     public boolean onMenuOpened(int featureId, Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
-            initActionBar();
+            initWindowDecorActionBar();
             if (mActionBar != null) {
                 mActionBar.dispatchMenuVisibilityChanged(true);
             } else {
@@ -2717,7 +2744,7 @@
                 break;
 
             case Window.FEATURE_ACTION_BAR:
-                initActionBar();
+                initWindowDecorActionBar();
                 mActionBar.dispatchMenuVisibilityChanged(false);
                 break;
         }
@@ -3417,7 +3444,7 @@
     public MenuInflater getMenuInflater() {
         // Make sure that action views can get an appropriate theme.
         if (mMenuInflater == null) {
-            initActionBar();
+            initWindowDecorActionBar();
             if (mActionBar != null) {
                 mMenuInflater = new MenuInflater(mActionBar.getThemedContext(), this);
             } else {
@@ -3457,8 +3484,7 @@
     public void startActivityForResult(Intent intent, int requestCode) {
         Bundle options = null;
         if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
-            final Pair<View, String>[] noSharedElements = null;
-            options = ActivityOptions.makeSceneTransitionAnimation(noSharedElements).toBundle();
+            options = ActivityOptions.makeSceneTransitionAnimation().toBundle();
         }
         startActivityForResult(intent, requestCode, options);
     }
@@ -3506,7 +3532,7 @@
                     mActionBar.captureSharedElements(sharedElementMap);
                     activityOptions.addSharedElements(sharedElementMap);
                 }
-                options = mWindow.startExitTransition(activityOptions);
+                options = mWindow.startExitTransitionToCallee(options);
             }
         }
         if (mParent == null) {
@@ -4361,6 +4387,23 @@
     }
 
     /**
+     * Reverses the Activity Scene entry Transition and triggers the calling Activity
+     * to reverse its exit Transition. When the exit Transition completes,
+     * {@link #finish()} is called. If no entry Transition was used, finish() is called
+     * immediately and the Activity exit Transition is run.
+     * @see android.view.Window#setTriggerEarlySceneTransition(boolean, boolean)
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)
+     */
+    public void finishWithTransition() {
+        mWindow.startExitTransitionToCaller(new Runnable() {
+            @Override
+            public void run() {
+                finish();
+            }
+        });
+    }
+
+    /**
      * Force finish another activity that you had previously started with
      * {@link #startActivityForResult}.
      * 
@@ -4701,42 +4744,31 @@
     }
 
     /**
-     * Set a label to be used in the Recents task display. The activities of a task are traversed
-     * in order from the topmost activity to the bottommost. As soon as one activity returns a
-     * non-null Recents label the traversal is ended and that value will be used in
-     * {@link ActivityManager.RecentTaskInfo#activityLabel}
+     * Set a label and icon to be used in the Recents task display. When {@link
+     * ActivityManager#getRecentTasks} is called, the activities of each task are
+     * traversed in order from the topmost activity to the bottommost. As soon as one activity is
+     * found with either a non-null label or a non-null icon set by this call the traversal is
+     * ended. For each task those values will be returned in {@link
+     * ActivityManager.RecentTaskInfo#activityLabel} and {@link
+     * ActivityManager.RecentTaskInfo#activityIcon}.
      *
      * @see ActivityManager#getRecentTasks
+     * @see ActivityManager.RecentTaskInfo
      *
-     * @param recentsLabel The label to use in the RecentTaskInfo.
+     * @param activityLabel The label to use in the RecentTaskInfo.
+     * @param activityIcon The Bitmap to use in the RecentTaskInfo.
      */
-    public void setRecentsLabel(CharSequence recentsLabel) {
-        try {
-            ActivityManagerNative.getDefault().setRecentsLabel(mToken, recentsLabel);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * Set an icon to be used in the Recents task display. The activities of a task are traversed
-     * in order from the topmost activity to the bottommost. As soon as one activity returns a
-     * non-null Recents icon the traversal is ended and that value will be used in
-     * {@link ActivityManager.RecentTaskInfo#activityIcon}.
-     *
-     * @see ActivityManager#getRecentTasks
-     *
-     * @param recentsIcon The Bitmap to use in the RecentTaskInfo.
-     */
-    public void setRecentsIcon(Bitmap recentsIcon) {
+    public void setActivityLabelAndIcon(CharSequence activityLabel, Bitmap activityIcon) {
         final Bitmap scaledIcon;
-        if (recentsIcon != null) {
+        if (activityIcon != null) {
             final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
-            scaledIcon = Bitmap.createScaledBitmap(recentsIcon, size, size, true);
+            scaledIcon = Bitmap.createScaledBitmap(activityIcon, size, size, true);
         } else {
             scaledIcon = null;
         }
         try {
-            ActivityManagerNative.getDefault().setRecentsIcon(mToken, scaledIcon);
+            ActivityManagerNative.getDefault().setActivityLabelAndIcon(mToken, activityLabel,
+                    scaledIcon);
         } catch (RemoteException e) {
         }
     }
@@ -5150,7 +5182,7 @@
     @Nullable
     @Override
     public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
-        initActionBar();
+        initWindowDecorActionBar();
         if (mActionBar != null) {
             return mActionBar.startActionMode(callback);
         }
@@ -5381,43 +5413,34 @@
         }
         mWindowManager = mWindow.getWindowManager();
         mCurrentConfig = config;
-        mTransitionActivityOptions = null;
-        Window.SceneTransitionListener sceneTransitionListener = null;
-        if (options != null) {
-            ActivityOptions activityOptions = new ActivityOptions(options);
-            if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
-                mTransitionActivityOptions = activityOptions;
-                sceneTransitionListener = new Window.SceneTransitionListener() {
-                    @Override
-                    public void nullPendingTransition() {
-                        overridePendingTransition(0, 0);
-                    }
-
-                    @Override
-                    public void convertFromTranslucent() {
-                        Activity.this.convertFromTranslucent();
-                    }
-
-                    @Override
-                    public void convertToTranslucent() {
-                        Activity.this.convertToTranslucent(null);
-                    }
-
-                    @Override
-                    public void sharedElementStart(Transition transition) {
-                        Activity.this.onCaptureSharedElementStart(transition);
-                    }
-
-                    @Override
-                    public void sharedElementEnd() {
-                        Activity.this.onCaptureSharedElementEnd();
-                    }
-                };
-
+        Window.SceneTransitionListener sceneTransitionListener
+                = new Window.SceneTransitionListener() {
+            @Override
+            public void nullPendingTransition() {
+                overridePendingTransition(0, 0);
             }
-        }
 
-        mWindow.setTransitionOptions(mTransitionActivityOptions, sceneTransitionListener);
+            @Override
+            public void convertFromTranslucent() {
+                Activity.this.convertFromTranslucent();
+            }
+
+            @Override
+            public void convertToTranslucent() {
+                Activity.this.convertToTranslucent(null);
+            }
+
+            @Override
+            public void sharedElementStart(Transition transition) {
+                Activity.this.onCaptureSharedElementStart(transition);
+            }
+
+            @Override
+            public void sharedElementEnd() {
+                Activity.this.onCaptureSharedElementEnd();
+            }
+        };
+        mWindow.setTransitionOptions(options, sceneTransitionListener);
     }
 
     /** @hide */
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d386eff..c027e99 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -516,14 +516,14 @@
         public int userId;
 
         /**
-         * The label of the highest activity in the task stack to have set a label
-         * {@link Activity#setRecentsLabel}.
+         * The label of the highest activity in the task stack to have set a label using
+         * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
          */
         public CharSequence activityLabel;
 
         /**
          * The Bitmap icon of the highest activity in the task stack to set a Bitmap using
-         * {@link Activity#setRecentsIcon}.
+         * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
          */
         public Bitmap activityIcon;
 
@@ -563,11 +563,7 @@
         public void readFromParcel(Parcel source) {
             id = source.readInt();
             persistentId = source.readInt();
-            if (source.readInt() != 0) {
-                baseIntent = Intent.CREATOR.createFromParcel(source);
-            } else {
-                baseIntent = null;
-            }
+            baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null;
             origActivity = ComponentName.readFromParcel(source);
             description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
             activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
@@ -605,11 +601,11 @@
     public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;
 
     /**
-     * Provides a list that also contains recent tasks for user
-     * and related users.
+     * Provides a list that contains recent tasks for all
+     * profiles of a user.
      * @hide
      */
-    public static final int RECENT_INCLUDE_RELATED = 0x0004;
+    public static final int RECENT_INCLUDE_PROFILES = 0x0004;
 
     /**
      * Return a list of the tasks that the user has recently launched, with
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 707a038..a37a35a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2129,21 +2129,13 @@
             return true;
         }
 
-        case SET_RECENTS_LABEL_TRANSACTION: {
+        case SET_ACTIVITY_LABEL_ICON_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            CharSequence recentsLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            setRecentsLabel(token, recentsLabel);
-            reply.writeNoException();
-            return true;
-        }
-
-        case SET_RECENTS_ICON_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);
-            IBinder token = data.readStrongBinder();
-            Bitmap recentsIcon = data.readInt() != 0
+            CharSequence activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
+            Bitmap activityIcon = data.readInt() > 0
                     ? Bitmap.CREATOR.createFromParcel(data) : null;
-            setRecentsIcon(token, recentsIcon);
+            setActivityLabelAndIcon(token, activityLabel, activityIcon);
             reply.writeNoException();
             return true;
         }
@@ -4918,32 +4910,22 @@
         return isInLockTaskMode;
     }
 
-    public void setRecentsLabel(IBinder token, CharSequence recentsLabel) throws RemoteException
+    @Override
+    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
+            Bitmap activityIcon) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        TextUtils.writeToParcel(recentsLabel, data, 0);
-        mRemote.transact(SET_RECENTS_LABEL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    public void setRecentsIcon(IBinder token, Bitmap recentsBitmap) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
-        if (recentsBitmap != null) {
+        TextUtils.writeToParcel(activityLabel, data, 0);
+        if (activityIcon != null) {
             data.writeInt(1);
-            recentsBitmap.writeToParcel(data, 0);
+            activityIcon.writeToParcel(data, 0);
         } else {
             data.writeInt(0);
         }
-        mRemote.transact(SET_RECENTS_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(SET_ACTIVITY_LABEL_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 07247ff..4384580 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -20,8 +20,10 @@
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.transition.Transition;
 import android.util.Log;
 import android.util.Pair;
@@ -136,6 +138,11 @@
     /** @hide */
     public static final int ANIM_SCENE_TRANSITION = 5;
 
+    private static final int MSG_SET_LISTENER = 100;
+    private static final int MSG_HIDE_SHARED_ELEMENTS = 101;
+    private static final int MSG_PREPARE_RESTORE = 102;
+    private static final int MSG_RESTORE = 103;
+
     private String mPackageName;
     private int mAnimationType = ANIM_NONE;
     private int mCustomEnterResId;
@@ -146,7 +153,7 @@
     private int mStartWidth;
     private int mStartHeight;
     private IRemoteCallback mAnimationStartedListener;
-    private IRemoteCallback mTransitionCompleteListener;
+    private ResultReceiver mTransitionCompleteListener;
     private ArrayList<String> mSharedElementNames;
     private ArrayList<String> mLocalElementNames;
 
@@ -428,8 +435,7 @@
                 break;
 
             case ANIM_SCENE_TRANSITION:
-                mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
-                        opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
+                mTransitionCompleteListener = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
                 mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
                 mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
                 break;
@@ -495,7 +501,6 @@
     /** @hide */
     public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
             ArrayList<String> sharedElementNames) {
-        boolean listenerSent = false;
         if (mTransitionCompleteListener != null) {
             IRemoteCallback callback = new IRemoteCallback.Stub() {
                 @Override
@@ -510,27 +515,28 @@
             Bundle bundle = new Bundle();
             bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
             bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
-            try {
-                mTransitionCompleteListener.sendResult(bundle);
-                listenerSent = true;
-            } catch (RemoteException e) {
-                Log.w(TAG, "Couldn't retrieve transition notifications", e);
-            }
-        }
-        if (!listenerSent) {
-            target.sharedElementTransitionComplete(null);
-            target.exitTransitionComplete();
+            mTransitionCompleteListener.send(MSG_SET_LISTENER, bundle);
         }
     }
 
     /** @hide */
     public void dispatchSharedElementsReady() {
         if (mTransitionCompleteListener != null) {
-            try {
-                mTransitionCompleteListener.sendResult(null);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Couldn't synchronize shared elements", e);
-            }
+            mTransitionCompleteListener.send(MSG_HIDE_SHARED_ELEMENTS, null);
+        }
+    }
+
+    /** @hide */
+    public void dispatchPrepareRestore() {
+        if (mTransitionCompleteListener != null) {
+            mTransitionCompleteListener.send(MSG_PREPARE_RESTORE, null);
+        }
+    }
+
+    /** @hide */
+    public void dispatchRestore(Bundle sharedElementsArgs) {
+        if (mTransitionCompleteListener != null) {
+            mTransitionCompleteListener.send(MSG_RESTORE, sharedElementsArgs);
         }
     }
 
@@ -658,8 +664,7 @@
             case ANIM_SCENE_TRANSITION:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
                 if (mTransitionCompleteListener != null) {
-                    b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
-                            mTransitionCompleteListener.asBinder());
+                    b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionCompleteListener);
                 }
                 b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
                 b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
@@ -710,13 +715,13 @@
         Bundle getSharedElementExitState();
         void acceptedSharedElements(ArrayList<String> sharedElementNames);
         void hideSharedElements();
+        void restore(Bundle sharedElementState);
+        void prepareForRestore();
     }
 
-    private static class ExitTransitionListener extends IRemoteCallback.Stub
+    private static class ExitTransitionListener extends ResultReceiver
             implements Transition.TransitionListener {
         private boolean mSharedElementNotified;
-        private Transition mExitTransition;
-        private Transition mSharedElementTransition;
         private IRemoteCallback mTransitionCompleteCallback;
         private boolean mExitComplete;
         private boolean mSharedElementComplete;
@@ -724,25 +729,40 @@
 
         public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
                 SharedElementSource sharedElementSource) {
+            super(null);
             mSharedElementSource = sharedElementSource;
-            mExitTransition = exitTransition;
-            mExitTransition.addListener(this);
-            mSharedElementTransition = sharedElementTransition;
-            mSharedElementTransition.addListener(this);
+            exitTransition.addListener(this);
+            sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    mSharedElementComplete = true;
+                    notifySharedElement();
+                    transition.removeListener(this);
+                }
+            });
         }
 
         @Override
-        public void sendResult(Bundle data) throws RemoteException {
-            if (data != null) {
-                mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
-                        data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
-                ArrayList<String> sharedElementNames
-                        = data.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
-                mSharedElementSource.acceptedSharedElements(sharedElementNames);
-                notifySharedElement();
-                notifyExit();
-            } else {
-                mSharedElementSource.hideSharedElements();
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            switch (resultCode) {
+                case MSG_SET_LISTENER:
+                    IBinder listener = resultData.getBinder(KEY_TRANSITION_TARGET_LISTENER);
+                    mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(listener);
+                    ArrayList<String> sharedElementNames
+                            = resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+                    mSharedElementSource.acceptedSharedElements(sharedElementNames);
+                    notifySharedElement();
+                    notifyExit();
+                    break;
+                case MSG_HIDE_SHARED_ELEMENTS:
+                    mSharedElementSource.hideSharedElements();
+                    break;
+                case MSG_PREPARE_RESTORE:
+                    mSharedElementSource.prepareForRestore();
+                    break;
+                case MSG_RESTORE:
+                    mSharedElementSource.restore(resultData);
+                    break;
             }
         }
 
@@ -752,15 +772,9 @@
 
         @Override
         public void onTransitionEnd(Transition transition) {
-            if (transition == mExitTransition) {
-                mExitComplete = true;
-                notifyExit();
-                mExitTransition.removeListener(this);
-            } else {
-                mSharedElementComplete = true;
-                notifySharedElement();
-                mSharedElementTransition.removeListener(this);
-            }
+            mExitComplete = true;
+            notifyExit();
+            transition.removeListener(this);
         }
 
         @Override
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 589c82f..1c02102 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -36,7 +36,9 @@
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ILauncherApps;
 import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetManager;
@@ -75,6 +77,8 @@
 import android.net.nsd.NsdManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot.IWifiHotspotManager;
+import android.net.wifi.hotspot.WifiHotspotManager;
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
@@ -101,6 +105,8 @@
 import android.print.IPrintManager;
 import android.print.PrintManager;
 import android.telephony.TelephonyManager;
+import android.tv.ITvInputManager;
+import android.tv.TvInputManager;
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -117,6 +123,7 @@
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsService;
@@ -465,7 +472,8 @@
                                         outerContext.getApplicationInfo().targetSdkVersion,
                                         com.android.internal.R.style.Theme_Dialog,
                                         com.android.internal.R.style.Theme_Holo_Dialog,
-                                        com.android.internal.R.style.Theme_DeviceDefault_Dialog)),
+                                        com.android.internal.R.style.Theme_DeviceDefault_Dialog,
+                                        com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog)),
                         ctx.mMainThread.getHandler());
                 }});
 
@@ -552,6 +560,13 @@
                     return new WifiManager(ctx.getOuterContext(), service);
                 }});
 
+        registerService(WIFI_HOTSPOT_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    IBinder b = ServiceManager.getService(WIFI_HOTSPOT_SERVICE);
+                    IWifiHotspotManager service = IWifiHotspotManager.Stub.asInterface(b);
+                    return new WifiHotspotManager(ctx.getOuterContext(), service);
+                }});
+
         registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
@@ -594,6 +609,14 @@
             }
         });
 
+        registerService(LAUNCHER_APPS_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(LAUNCHER_APPS_SERVICE);
+                ILauncherApps service = ILauncherApps.Stub.asInterface(b);
+                return new LauncherApps(ctx, service);
+            }
+        });
+
         registerService(PRINT_SERVICE, new ServiceFetcher() {
             public Object createService(ContextImpl ctx) {
                 IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE);
@@ -612,6 +635,19 @@
                 return new MediaSessionManager(ctx);
             }
         });
+        registerService(TRUST_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(TRUST_SERVICE);
+                return new TrustManager(b);
+            }
+        });
+
+        registerService(TV_INPUT_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                IBinder iBinder = ServiceManager.getService(TV_INPUT_SERVICE);
+                ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
+                return new TvInputManager(service, UserHandle.myUserId());
+            }});
     }
 
     static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index fb96d8d..07583fd 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -17,7 +17,7 @@
 package android.app;
 
 import android.content.pm.ApplicationInfo;
-import com.android.internal.app.ActionBarImpl;
+import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.policy.PolicyManager;
 
 import android.content.ComponentName;
@@ -87,7 +87,7 @@
     final WindowManager mWindowManager;
     Window mWindow;
     View mDecor;
-    private ActionBarImpl mActionBar;
+    private ActionBar mActionBar;
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
@@ -280,7 +280,7 @@
             final ApplicationInfo info = mContext.getApplicationInfo();
             mWindow.setDefaultIcon(info.icon);
             mWindow.setDefaultLogo(info.logo);
-            mActionBar = new ActionBarImpl(this);
+            mActionBar = new WindowDecorActionBar(this);
         }
 
         WindowManager.LayoutParams l = mWindow.getAttributes();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3b56839..f7416d6 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -437,10 +437,8 @@
     public boolean isInLockTaskMode() throws RemoteException;
 
     /** @hide */
-    public void setRecentsLabel(IBinder token, CharSequence recentsLabel) throws RemoteException;
-
-    /** @hide */
-    public void setRecentsIcon(IBinder token, Bitmap recentsBitmap) throws RemoteException;
+    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
+            Bitmap activityBitmap) throws RemoteException;
 
     /*
      * Private non-Binder interfaces
@@ -741,6 +739,5 @@
     int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214;
     int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
     int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
-    int SET_RECENTS_LABEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
-    int SET_RECENTS_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
+    int SET_ACTIVITY_LABEL_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
 }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 4ca06ed..7036aea 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -124,4 +124,12 @@
             int type, String domain, String path, long mode, long mtime,
             int token, IBackupManager callbackBinder);
 
+    /**
+     * Out of band: instruct the agent to crash within the client process.  This is used
+     * when the backup infrastructure detects a semantic error post-hoc and needs to
+     * pass the problem back to the app.
+     *
+     * @param message The message to be passed to the agent's application in an exception.
+     */
+    void fail(String message);
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9f933ca..9911467 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -45,7 +45,8 @@
     void unregisterListener(in INotificationListener listener, int userid);
 
     void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
-    void cancelAllNotificationsFromListener(in INotificationListener token);
+    void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
 
-    StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token);
+    StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
+    String[] getActiveNotificationKeysFromListener(in INotificationListener token);
 }
\ No newline at end of file
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 8efc14f..cf14202 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -121,8 +121,8 @@
      */
     public static final int FLAG_ONE_SHOT = 1<<30;
     /**
-     * Flag indicating that if the described PendingIntent already
-     * exists, then simply return null instead of creating it.
+     * Flag indicating that if the described PendingIntent does not
+     * already exist, then simply return null instead of creating it.
      * For use with {@link #getActivity}, {@link #getBroadcast}, and
      * {@link #getService}.
      */
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0c22740..c6731c9 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -166,9 +166,11 @@
     /**
      * Return the current running mode type.  May be one of
      * {@link Configuration#UI_MODE_TYPE_NORMAL Configuration.UI_MODE_TYPE_NORMAL},
-     * {@link Configuration#UI_MODE_TYPE_DESK Configuration.UI_MODE_TYPE_DESK}, or
-     * {@link Configuration#UI_MODE_TYPE_CAR Configuration.UI_MODE_TYPE_CAR}, or
-     * {@link Configuration#UI_MODE_TYPE_TELEVISION Configuration.UI_MODE_TYPE_APPLIANCE}.
+     * {@link Configuration#UI_MODE_TYPE_DESK Configuration.UI_MODE_TYPE_DESK},
+     * {@link Configuration#UI_MODE_TYPE_CAR Configuration.UI_MODE_TYPE_CAR},
+     * {@link Configuration#UI_MODE_TYPE_TELEVISION Configuration.UI_MODE_TYPE_TELEVISION},
+     * {@link Configuration#UI_MODE_TYPE_APPLIANCE Configuration.UI_MODE_TYPE_APPLIANCE}, or
+     * {@link Configuration#UI_MODE_TYPE_WATCH Configuration.UI_MODE_TYPE_WATCH}.
      */
     public int getCurrentModeType() {
         if (mService != null) {
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 66fc816..3074b49 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -52,6 +52,22 @@
     static final String TAG = "DeviceAdminInfo";
 
     /**
+     * A type of policy that this device admin can use: device owner meta-policy
+     * for an admin that is designated as owner of the device.
+     *
+     * @hide
+     */
+    public static final int USES_POLICY_DEVICE_OWNER = -2;
+
+    /**
+     * A type of policy that this device admin can use: profile owner meta-policy
+     * for admins that have been installed as owner of some user profile.
+     *
+     * @hide
+     */
+    public static final int USES_POLICY_PROFILE_OWNER = -1;
+
+    /**
      * A type of policy that this device admin can use: limit the passwords
      * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
      * and {@link DevicePolicyManager#setPasswordMinimumLength}.
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 67c772b..3c31f8d 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -128,6 +128,13 @@
 
     Handler mHandler = null;
 
+    Handler getHandler() {
+        if (mHandler == null) {
+            mHandler = new Handler(Looper.getMainLooper());
+        }
+        return mHandler;
+    }
+
     class SharedPrefsSynchronizer implements Runnable {
         public final CountDownLatch mLatch = new CountDownLatch(1);
 
@@ -140,12 +147,9 @@
 
     // Syncing shared preferences deferred writes needs to happen on the main looper thread
     private void waitForSharedPrefs() {
-        if (mHandler == null) {
-            mHandler = new Handler(Looper.getMainLooper());
-        }
-
+        Handler h = getHandler();
         final SharedPrefsSynchronizer s = new SharedPrefsSynchronizer();
-        mHandler.postAtFrontOfQueue(s);
+        h.postAtFrontOfQueue(s);
         try {
             s.mLatch.await();
         } catch (InterruptedException e) { /* ignored */ }
@@ -680,5 +684,23 @@
                 }
             }
         }
+
+        @Override
+        public void fail(String message) {
+            getHandler().post(new FailRunnable(message));
+        }
+    }
+
+    static class FailRunnable implements Runnable {
+        private String mMessage;
+
+        FailRunnable(String message) {
+            mMessage = message;
+        }
+
+        @Override
+        public void run() {
+            throw new IllegalStateException(mMessage);
+        }
     }
 }
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 845784f..fc5fb3d 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -85,11 +85,6 @@
      * @throws IOException if the write failed
      */
     public int writeEntityHeader(String key, int dataSize) throws IOException {
-        if (key != null && key.charAt(0) >= 0xff00) {
-            if (Process.myUid() != Process.SYSTEM_UID) {
-                throw new IllegalArgumentException("Invalid key " + key);
-            }
-        }
         int result = writeEntityHeader_native(mBackupWriter, key, dataSize);
         if (result >= 0) {
             return result;
diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl
new file mode 100644
index 0000000..4680043
--- /dev/null
+++ b/core/java/android/app/trust/ITrustListener.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.app.trust;
+
+/**
+ * Private API to be notified about trust changes.
+ *
+ * {@hide}
+ */
+oneway interface ITrustListener {
+    void onTrustChanged(boolean enabled, int userId);
+}
\ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
new file mode 100644
index 0000000..ad4ccbb
--- /dev/null
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -0,0 +1,31 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.app.trust;
+
+import android.app.trust.ITrustListener;
+
+/**
+ * System private API to comunicate with trust service.
+ *
+ * {@hide}
+ */
+interface ITrustManager {
+    void reportUnlockAttempt(boolean successful, int userId);
+    void reportEnabledTrustAgentsChanged(int userId);
+    void registerTrustListener(in ITrustListener trustListener);
+    void unregisterTrustListener(in ITrustListener trustListener);
+}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
new file mode 100644
index 0000000..e31c624
--- /dev/null
+++ b/core/java/android/app/trust/TrustManager.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.trust;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+/**
+ * See {@link com.android.server.trust.TrustManagerService}
+ * @hide
+ */
+public class TrustManager {
+
+    private static final int MSG_TRUST_CHANGED = 1;
+
+    private static final String TAG = "TrustManager";
+
+    private final ITrustManager mService;
+    private final ArrayMap<TrustListener, ITrustListener> mTrustListeners;
+
+    public TrustManager(IBinder b) {
+        mService = ITrustManager.Stub.asInterface(b);
+        mTrustListeners = new ArrayMap<TrustListener, ITrustListener>();
+    }
+
+    /**
+     * Reports that user {@param userId} has tried to unlock the device.
+     *
+     * @param successful if true, the unlock attempt was successful.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     */
+    public void reportUnlockAttempt(boolean successful, int userId) {
+        try {
+            mService.reportUnlockAttempt(successful, userId);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
+     * Reports that the list of enabled trust agents changed for user {@param userId}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     */
+    public void reportEnabledTrustAgentsChanged(int userId) {
+        try {
+            mService.reportEnabledTrustAgentsChanged(userId);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
+     * Registers a listener for trust events.
+     *
+     * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+     */
+    public void registerTrustListener(final TrustListener trustListener) {
+        try {
+            ITrustListener.Stub iTrustListener = new ITrustListener.Stub() {
+                @Override
+                public void onTrustChanged(boolean enabled, int userId) throws RemoteException {
+                    mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId,
+                            trustListener).sendToTarget();
+                }
+            };
+            mService.registerTrustListener(iTrustListener);
+            mTrustListeners.put(trustListener, iTrustListener);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
+     * Unregisters a listener for trust events.
+     *
+     * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+     */
+    public void unregisterTrustListener(final TrustListener trustListener) {
+        ITrustListener iTrustListener = mTrustListeners.remove(trustListener);
+        if (iTrustListener != null) {
+            try {
+                mService.unregisterTrustListener(iTrustListener);
+            } catch (RemoteException e) {
+                onError(e);
+            }
+        }
+    }
+
+    private void onError(Exception e) {
+        Log.e(TAG, "Error while calling TrustManagerService", e);
+    }
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_TRUST_CHANGED:
+                    ((TrustListener)msg.obj).onTrustChanged(msg.arg1 != 0, msg.arg2);
+                    break;
+            }
+        }
+    };
+
+    public interface TrustListener {
+
+        /**
+         * Reports that the trust state has changed.
+         * @param enabled if true, the system believes the environment to be trusted.
+         * @param userId the user, for which the trust changed.
+         */
+        void onTrustChanged(boolean enabled, int userId);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a4374b8..e79deec 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -567,7 +567,7 @@
     }
 
     /**
-     * Stop BLE advertising.
+     * Stop BLE advertising. The callback has to be the same one used for start advertising.
      *
      * @param callback - {@link AdvertiseCallback}
      * @return true if BLE advertising stops, false otherwise.
@@ -1986,7 +1986,13 @@
         public void onAdvertiseStateChange(int advertiseState, int status) {
             Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status);
             if (advertiseState == STATE_ADVERTISE_STARTED) {
-                mAdvertiseCallback.onAdvertiseStart(status);
+                if (status == ADVERTISE_CALLBACK_SUCCESS) {
+                    mAdvertiseCallback.onAdvertiseStart(status);
+                } else {
+                    // If status is unsuccessful and advertise state is started, it means stop
+                    // advertising fails.
+                    mAdvertiseCallback.onAdvertiseStop(status);
+                }
             } else {
                 synchronized (this) {
                     if (status == ADVERTISE_CALLBACK_SUCCESS) {
@@ -2008,8 +2014,22 @@
                         }
                     }
                 }
-                mAdvertiseCallback.onAdvertiseStop(status);
+                if (status == ADVERTISE_CALLBACK_SUCCESS) {
+                    mAdvertiseCallback.onAdvertiseStop(status);
+                } else{
+                    // If status is unsuccesful and advertise state is stopped, it means start
+                    // advertising fails.
+                    mAdvertiseCallback.onAdvertiseStart(status);
+                }
             }
         }
+
+        /**
+         * Callback reporting LE ATT MTU.
+         * @hide
+         */
+        public void onConfigureMTU(String address, int mtu, int status) {
+            // no op
+        }
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 39305b0..101b721 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -550,6 +550,23 @@
             public void onAdvertiseStateChange(int state, int status) {
                 if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
                         + state + " status=" + status);
+	    }
+
+            /**
+             * Callback invoked when the MTU for a given connection changes
+             * @hide
+             */
+            public void onConfigureMTU(String address, int mtu, int status) {
+                if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
+                            " mtu=" + mtu + " status=" + status);
+                if (!address.equals(mDevice.getAddress())) {
+                    return;
+                }
+                try {
+                    mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception in callback", ex);
+                }
             }
         };
 
@@ -1137,6 +1154,36 @@
     }
 
     /**
+     * Configure the MTU used for a given connection.
+     *
+     * <p>When performing a write request operation (write without response),
+     * the data sent is truncated to the MTU size. This function may be used
+     * to request a larget MTU size to be able to send more data at once.
+     *
+     * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
+     * whether this operation was successful.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return true, if the new MTU value has been requested successfully
+     * @hide
+     */
+    public boolean configureMTU(int mtu) {
+        if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
+                            + " mtu: " + mtu);
+        if (mService == null || mClientIf == 0) return false;
+
+        try {
+            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
      * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
      * with {@link BluetoothProfile#GATT} as argument
      *
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 80ea4a6..5180259 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -138,4 +138,19 @@
      */
     public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
     }
+
+    /**
+     * Callback indicating the MTU for a given device connection has changed.
+     *
+     * This callback is triggered in response to the
+     * {@link BluetoothGatt#configureMTU} function, or in response to a connection
+     * event.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#configureMTU}
+     * @param mtu The new MTU size
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
+     * @hide
+     */
+    public void onConfigureMTU(BluetoothGatt gatt, int mtu, int status) {
+    }
 }
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 784cdcc..c6b5c3d 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -73,6 +73,7 @@
     void beginReliableWrite(in int clientIf, in String address);
     void endReliableWrite(in int clientIf, in String address, in boolean execute);
     void readRemoteRssi(in int clientIf, in String address);
+    void configureMTU(in int clientIf, in String address, in int mtu);
 
     void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
     void unregisterServer(in int serverIf);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 7c69a06..a78c29b 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -64,4 +64,5 @@
                              in byte[] value);
     void onReadRemoteRssi(in String address, in int rssi, in int status);
     oneway void onAdvertiseStateChange(in int advertiseState, in int status);
+    void onConfigureMTU(in String address, in int mtu, in int status);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9f0c384..ed0cc23 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -573,6 +573,9 @@
      * Open a private file associated with this Context's application package
      * for writing.  Creates the file if it doesn't already exist.
      *
+     * <p>No permissions are required to invoke this method, since it uses internal
+     * storage.
+     *
      * @param name The name of the file to open; can not contain path
      *             separators.
      * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
@@ -630,6 +633,9 @@
      * Returns the absolute path to the directory on the filesystem where
      * files created with {@link #openFileOutput} are stored.
      *
+     * <p>No permissions are required to read or write to the returned path, since this
+     * path is internal storage.
+     *
      * @return The path of the directory holding application files.
      *
      * @see #openFileOutput
@@ -1974,6 +1980,7 @@
             //@hide: NETWORK_STATS_SERVICE,
             //@hide: NETWORK_POLICY_SERVICE,
             WIFI_SERVICE,
+            WIFI_HOTSPOT_SERVICE,
             WIFI_P2P_SERVICE,
             NSD_SERVICE,
             AUDIO_SERVICE,
@@ -1992,6 +1999,7 @@
             BLUETOOTH_SERVICE,
             //@hide: SIP_SERVICE,
             USB_SERVICE,
+            LAUNCHER_APPS_SERVICE,
             //@hide: SERIAL_SERVICE,
             INPUT_SERVICE,
             DISPLAY_SERVICE,
@@ -2324,6 +2332,16 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
+     * android.net.wifi.hotspot.WifiHotspotManager} for handling management of
+     * Wi-Fi hotspot access.
+     *
+     * @see #getSystemService
+     * @see android.net.wifi.hotspot.WifiHotspotManager
+     */
+    public static final String WIFI_HOTSPOT_SERVICE = "wifihotspot";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a {@link
      * android.net.wifi.p2p.WifiP2pManager} for handling management of
      * Wi-Fi peer-to-peer connections.
      *
@@ -2546,6 +2564,16 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.content.pm.LauncherApps} for querying and monitoring launchable apps across
+     * profiles of a user.
+     *
+     * @see #getSystemService
+     * @see android.content.pm.LauncherApps
+     */
+    public static final String LAUNCHER_APPS_SERVICE = "launcherapps";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.app.AppOpsManager} for tracking application operations
      * on the device.
      *
@@ -2584,6 +2612,24 @@
     public static final String CONSUMER_IR_SERVICE = "consumer_ir";
 
     /**
+     * {@link android.app.trust.TrustManager} for managing trust agents.
+     * @see #getSystemService
+     * @see android.app.trust.TrustManager
+     * @hide
+     */
+    public static final String TRUST_SERVICE = "trust";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.tv.TvInputManager} for interacting with TV inputs on the
+     * device.
+     *
+     * @see #getSystemService
+     * @see android.tv.TvInputManager
+     */
+    public static final String TV_INPUT_SERVICE = "tv_input";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 102433b..9881428 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2608,6 +2608,23 @@
             "android.intent.action.USER_INFO_CHANGED";
 
     /**
+     * Broadcast sent to the primary user when an associated managed profile is added (the profile
+     * was created and is ready to be used). Carries an extra {@link #EXTRA_USER} that specifies
+     * the UserHandle of the profile that was added. This is only sent to registered receivers,
+     * not manifest receivers.
+     */
+    public static final String ACTION_MANAGED_PROFILE_ADDED =
+            "android.intent.action.MANAGED_PROFILE_ADDED";
+
+    /**
+     * Broadcast sent to the primary user when an associated managed profile is removed. Carries an
+     * extra {@link #EXTRA_USER} that specifies the UserHandle of the profile that was removed. This
+     * is only sent to registered receivers, not manifest receivers.
+     */
+    public static final String ACTION_MANAGED_PROFILE_REMOVED =
+            "android.intent.action.MANAGED_PROFILE_REMOVED";
+
+    /**
      * Sent when the user taps on the clock widget in the system's "quick settings" area.
      */
     public static final String ACTION_QUICK_CLOCK =
@@ -2884,6 +2901,14 @@
     @SdkConstant(SdkConstantType.INTENT_CATEGORY)
     public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
 
+    /**
+     * An activity that provides a user interface for adjusting notification preferences for its
+     * containing application. Optional but recommended for apps that post
+     * {@link android.app.Notification Notifications}.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Application launch intent categories (see addCategory()).
@@ -3293,15 +3318,23 @@
             "android.intent.extra.ALLOW_MULTIPLE";
 
     /**
-     * The userHandle carried with broadcast intents related to addition, removal and switching of
-     * users
-     * - {@link #ACTION_USER_ADDED}, {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
+     * The integer userHandle carried with broadcast intents related to addition, removal and
+     * switching of users and managed profiles - {@link #ACTION_USER_ADDED},
+     * {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
+     *
      * @hide
      */
     public static final String EXTRA_USER_HANDLE =
             "android.intent.extra.user_handle";
 
     /**
+     * The UserHandle carried with broadcasts intents related to addition and removal of managed
+     * profiles - {@link #ACTION_MANAGED_PROFILE_ADDED} and {@link #ACTION_MANAGED_PROFILE_REMOVED}.
+     */
+    public static final String EXTRA_USER =
+            "android.intent.extra.user";
+
+    /**
      * Extra used in the response from a BroadcastReceiver that handles
      * {@link #ACTION_GET_RESTRICTION_ENTRIES}. The type of the extra is
      * <code>ArrayList&lt;RestrictionEntry&gt;</code>.
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 40275d8..9916476 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -189,6 +189,13 @@
      */
     public static final int FLAG_IMMERSIVE = 0x0800;
     /**
+     * Bit in {@link #flags} indicating that this activity is to be persisted across
+     * reboots for display in the Recents list.
+     * {@link android.R.attr#persistable}
+     * @hide
+     */
+    public static final int FLAG_PERSISTABLE = 0x1000;
+    /**
      * @hide Bit in {@link #flags}: If set, this component will only be seen
      * by the primary user.  Only works with broadcast receivers.  Set from the
      * {@link android.R.attr#primaryUserOnly} attribute.
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
new file mode 100644
index 0000000..796b113
--- /dev/null
+++ b/core/java/android/content/pm/ILauncherApps.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.content.pm;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.ResolveInfo;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.UserHandle;
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+interface ILauncherApps {
+    void addOnAppsChangedListener(in IOnAppsChangedListener listener);
+    void removeOnAppsChangedListener(in IOnAppsChangedListener listener);
+    List<ResolveInfo> getLauncherActivities(String packageName, in UserHandle user);
+    ResolveInfo resolveActivity(in Intent intent, in UserHandle user);
+    void startActivityAsUser(in ComponentName component, in Rect sourceBounds,
+            in Bundle opts, in UserHandle user);
+}
diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl
new file mode 100644
index 0000000..796b58d
--- /dev/null
+++ b/core/java/android/content/pm/IOnAppsChangedListener.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.content.pm;
+
+import android.os.UserHandle;
+
+/**
+ * {@hide}
+ */
+oneway interface IOnAppsChangedListener {
+    void onPackageRemoved(in UserHandle user, String packageName);
+    void onPackageAdded(in UserHandle user, String packageName);
+    void onPackageChanged(in UserHandle user, String packageName);
+    void onPackagesAvailable(in UserHandle user, in String[] packageNames, boolean replacing);
+    void onPackagesUnavailable(in UserHandle user, in String[] packageNames, boolean replacing);
+}
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
new file mode 100644
index 0000000..92b9146
--- /dev/null
+++ b/core/java/android/content/pm/LauncherActivityInfo.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 android.content.pm;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Bitmap.Config;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+/**
+ * A representation of an activity that can belong to this user or a managed
+ * profile associated with this user. It can be used to query the label, icon
+ * and badged icon for the activity.
+ */
+public class LauncherActivityInfo {
+    private static final boolean DEBUG = false;
+    private final PackageManager mPm;
+    private final UserManager mUm;
+
+    private ActivityInfo mActivityInfo;
+    private ComponentName mComponentName;
+    private UserHandle mUser;
+    // TODO: Fetch this value from PM
+    private long mFirstInstallTime;
+
+    /**
+     * Create a launchable activity object for a given ResolveInfo and user.
+     * 
+     * @param context The context for fetching resources.
+     * @param info ResolveInfo from which to create the LauncherActivityInfo.
+     * @param user The UserHandle of the profile to which this activity belongs.
+     */
+    LauncherActivityInfo(Context context, ResolveInfo info, UserHandle user) {
+        this(context);
+        this.mActivityInfo = info.activityInfo;
+        this.mComponentName = LauncherApps.getComponentName(info);
+        this.mUser = user;
+    }
+
+    LauncherActivityInfo(Context context) {
+        mPm = context.getPackageManager();
+        mUm = UserManager.get(context);
+    }
+
+    /**
+     * Returns the component name of this activity.
+     *
+     * @return ComponentName of the activity
+     */
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    /**
+     * Returns the user handle of the user profile that this activity belongs to.
+     *
+     * @return The UserHandle of the profile.
+     */
+    public UserHandle getUser() {
+        return mUser;
+    }
+
+    /**
+     * Retrieves the label for the activity.
+     * 
+     * @return The label for the activity.
+     */
+    public CharSequence getLabel() {
+        return mActivityInfo.loadLabel(mPm);
+    }
+
+    /**
+     * Returns the icon for this activity, without any badging for the profile.
+     * @param density The preferred density of the icon, zero for default density.
+     * @see #getBadgedIcon(int)
+     * @return The drawable associated with the activity
+     */
+    public Drawable getIcon(int density) {
+        // TODO: Use density
+        return mActivityInfo.loadIcon(mPm);
+    }
+
+    /**
+     * Returns the application flags from the ApplicationInfo of the activity.
+     * 
+     * @return Application flags
+     */
+    public int getApplicationFlags() {
+        return mActivityInfo.applicationInfo.flags;
+    }
+
+    /**
+     * Returns the time at which the package was first installed.
+     * @return The time of installation of the package, in milliseconds.
+     */
+    public long getFirstInstallTime() {
+        return mFirstInstallTime;
+    }
+
+    /**
+     * Returns the activity icon with badging appropriate for the profile.
+     * @param density Optional density for the icon, or 0 to use the default density.
+     * @return A badged icon for the activity.
+     */
+    public Drawable getBadgedIcon(int density) {
+        // TODO: Handle density
+        if (mUser.equals(android.os.Process.myUserHandle())) {
+            return mActivityInfo.loadIcon(mPm);
+        }
+        Drawable originalIcon = mActivityInfo.loadIcon(mPm);
+        if (originalIcon == null) {
+            if (DEBUG) {
+                Log.w("LauncherActivityInfo", "Couldn't find icon for activity");
+            }
+            originalIcon = mPm.getDefaultActivityIcon();
+        }
+        if (originalIcon instanceof BitmapDrawable) {
+            return mUm.getBadgedDrawableForUser(
+                    originalIcon, mUser);
+        }
+        return originalIcon;
+    }
+}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
new file mode 100644
index 0000000..5187181
--- /dev/null
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ILauncherApps;
+import android.content.pm.IOnAppsChangedListener;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Class for retrieving a list of launchable activities for the current user and any associated
+ * managed profiles. This is mainly for use by launchers. Apps can be queried for each user profile.
+ * Since the PackageManager will not deliver package broadcasts for other profiles, you can register
+ * for package changes here.
+ */
+public class LauncherApps {
+
+    static final String TAG = "LauncherApps";
+    static final boolean DEBUG = false;
+
+    private Context mContext;
+    private ILauncherApps mService;
+
+    private List<OnAppsChangedListener> mListeners
+            = new ArrayList<OnAppsChangedListener>();
+
+    /**
+     * Callbacks for changes to this and related managed profiles.
+     */
+    public interface OnAppsChangedListener {
+        /**
+         * Indicates that a package was removed from the specified profile.
+         *
+         * @param user The UserHandle of the profile that generated the change.
+         * @param packageName The name of the package that was removed.
+         */
+        void onPackageRemoved(UserHandle user, String packageName);
+
+        /**
+         * Indicates that a package was added to the specified profile.
+         *
+         * @param user The UserHandle of the profile that generated the change.
+         * @param packageName The name of the package that was added.
+         */
+        void onPackageAdded(UserHandle user, String packageName);
+
+        /**
+         * Indicates that a package was modified in the specified profile.
+         *
+         * @param user The UserHandle of the profile that generated the change.
+         * @param packageName The name of the package that has changed.
+         */
+        void onPackageChanged(UserHandle user, String packageName);
+
+        /**
+         * Indicates that one or more packages have become available. For
+         * example, this can happen when a removable storage card has
+         * reappeared.
+         *
+         * @param user The UserHandle of the profile that generated the change.
+         * @param packageNames The names of the packages that have become
+         *            available.
+         * @param replacing Indicates whether these packages are replacing
+         *            existing ones.
+         */
+        void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing);
+
+        /**
+         * Indicates that one or more packages have become unavailable. For
+         * example, this can happen when a removable storage card has been
+         * removed.
+         *
+         * @param user The UserHandle of the profile that generated the change.
+         * @param packageNames The names of the packages that have become
+         *            unavailable.
+         * @param replacing Indicates whether the packages are about to be
+         *            replaced with new versions.
+         */
+        void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing);
+    }
+
+    /** @hide */
+    public LauncherApps(Context context, ILauncherApps service) {
+        mContext = context;
+        mService = service;
+    }
+
+    /**
+     * Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
+     * {@link Intent#CATEGORY_LAUNCHER}, for a specified user.
+     *
+     * @param packageName The specific package to query. If null, it checks all installed packages
+     *            in the profile.
+     * @param user The UserHandle of the profile.
+     * @return List of launchable activities. Can be an empty list but will not be null.
+     */
+    public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
+        List<ResolveInfo> activities = null;
+        try {
+            activities = mService.getLauncherActivities(packageName, user);
+        } catch (RemoteException re) {
+        }
+        if (activities == null) {
+            return Collections.EMPTY_LIST;
+        }
+        ArrayList<LauncherActivityInfo> lais = new ArrayList<LauncherActivityInfo>();
+        final int count = activities.size();
+        for (int i = 0; i < count; i++) {
+            ResolveInfo ri = activities.get(i);
+            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri, user);
+            if (DEBUG) {
+                Log.v(TAG, "Returning activity for profile " + user + " : "
+                        + lai.getComponentName());
+            }
+            lais.add(lai);
+        }
+        return lais;
+    }
+
+    static ComponentName getComponentName(ResolveInfo ri) {
+        return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+    }
+
+    /**
+     * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
+     * returns null.
+     *
+     * @param intent The intent to find a match for.
+     * @param user The profile to look in for a match.
+     * @return An activity info object if there is a match.
+     */
+    public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
+        try {
+            ResolveInfo ri = mService.resolveActivity(intent, user);
+            if (ri != null) {
+                LauncherActivityInfo info = new LauncherActivityInfo(mContext, ri, user);
+                return info;
+            }
+        } catch (RemoteException re) {
+            return null;
+        }
+        return null;
+    }
+
+    /**
+     * Starts an activity in the specified profile.
+     *
+     * @param component The ComponentName of the activity to launch
+     * @param sourceBounds The Rect containing the source bounds of the clicked icon
+     * @param opts Options to pass to startActivity
+     * @param user The UserHandle of the profile
+     */
+    public void startActivityForProfile(ComponentName component, Rect sourceBounds,
+            Bundle opts, UserHandle user) {
+        if (DEBUG) {
+            Log.i(TAG, "StartActivityForProfile " + component + " " + user.getIdentifier());
+        }
+        try {
+            mService.startActivityAsUser(component, sourceBounds, opts, user);
+        } catch (RemoteException re) {
+            // Oops!
+        }
+    }
+
+    /**
+     * Adds a listener for changes to packages in current and managed profiles.
+     *
+     * @param listener The listener to add.
+     */
+    public synchronized void addOnAppsChangedListener(OnAppsChangedListener listener) {
+        if (listener != null && !mListeners.contains(listener)) {
+            mListeners.add(listener);
+            if (mListeners.size() == 1) {
+                try {
+                    mService.addOnAppsChangedListener(mAppsChangedListener);
+                } catch (RemoteException re) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a listener that was previously added.
+     *
+     * @param listener The listener to remove.
+     * @see #addOnAppsChangedListener(OnAppsChangedListener)
+     */
+    public synchronized void removeOnAppsChangedListener(OnAppsChangedListener listener) {
+        mListeners.remove(listener);
+        if (mListeners.size() == 0) {
+            try {
+                mService.removeOnAppsChangedListener(mAppsChangedListener);
+            } catch (RemoteException re) {
+            }
+        }
+    }
+
+    private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
+
+        @Override
+        public void onPackageRemoved(UserHandle user, String packageName) throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
+            }
+            synchronized (LauncherApps.this) {
+                for (OnAppsChangedListener listener : mListeners) {
+                    listener.onPackageRemoved(user, packageName);
+                }
+            }
+        }
+
+        @Override
+        public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
+            }
+            synchronized (LauncherApps.this) {
+                for (OnAppsChangedListener listener : mListeners) {
+                    listener.onPackageChanged(user, packageName);
+                }
+            }
+        }
+
+        @Override
+        public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
+            }
+            synchronized (LauncherApps.this) {
+                for (OnAppsChangedListener listener : mListeners) {
+                    listener.onPackageAdded(user, packageName);
+                }
+            }
+        }
+
+        @Override
+        public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
+                throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
+            }
+            synchronized (LauncherApps.this) {
+                for (OnAppsChangedListener listener : mListeners) {
+                    listener.onPackagesAvailable(user, packageNames, replacing);
+                }
+            }
+        }
+
+        @Override
+        public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
+                throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
+            }
+            synchronized (LauncherApps.this) {
+                for (OnAppsChangedListener listener : mListeners) {
+                    listener.onPackagesUnavailable(user, packageNames, replacing);
+                }
+            }
+        }
+    };
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ceb7764..3300e9d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1316,6 +1316,13 @@
     public static final String FEATURE_BACKUP = "android.software.backup";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device supports managed profiles for enterprise users.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_MANAGEDPROFILES = "android.software.managedprofiles";
+
+    /**
      * Action to external storage service to clean out removed apps.
      * @hide
      */
@@ -2490,7 +2497,7 @@
     /**
      * Return the generic icon for an activity that is used when no specific
      * icon is defined.
-     * 
+     *
      * @return Drawable Image of the icon.
      */
     public abstract Drawable getDefaultActivityIcon();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8898beb..4b5616f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -57,7 +57,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.jar.JarEntry;
 import java.util.jar.StrictJarFile;
 import java.util.zip.ZipEntry;
 
@@ -1010,13 +1009,14 @@
             pkg.mSharedUserLabel = sa.getResourceId(
                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
         }
-        sa.recycle();
 
         pkg.installLocation = sa.getInteger(
                 com.android.internal.R.styleable.AndroidManifest_installLocation,
                 PARSE_DEFAULT_INSTALL_LOCATION);
         pkg.applicationInfo.installLocation = pkg.installLocation;
 
+        sa.recycle();
+
         /* Set the global "forward lock" flag */
         if ((flags & PARSE_FORWARD_LOCK) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
@@ -2447,6 +2447,11 @@
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestActivity_persistable, false)) {
+            a.info.flags |= ActivityInfo.FLAG_PERSISTABLE;
+        }
+
         if (!receiver) {
             if (sa.getBoolean(
                     com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 6f1d4f8..f53aa4c 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -71,7 +71,7 @@
     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
 
 
-    public static final int NO_RELATED_GROUP_ID = -1;
+    public static final int NO_PROFILE_GROUP_ID = -1;
 
     public int id;
     public int serialNumber;
@@ -80,7 +80,7 @@
     public int flags;
     public long creationTime;
     public long lastLoggedInTime;
-    public int relatedGroupId;
+    public int profileGroupId;
 
     /** User is only partially created. */
     public boolean partial;
@@ -94,7 +94,7 @@
         this.name = name;
         this.flags = flags;
         this.iconPath = iconPath;
-        this.relatedGroupId = NO_RELATED_GROUP_ID;
+        this.profileGroupId = NO_PROFILE_GROUP_ID;
     }
 
     public boolean isPrimary() {
@@ -137,7 +137,7 @@
         creationTime = orig.creationTime;
         lastLoggedInTime = orig.lastLoggedInTime;
         partial = orig.partial;
-        relatedGroupId = orig.relatedGroupId;
+        profileGroupId = orig.profileGroupId;
     }
 
     public UserHandle getUserHandle() {
@@ -162,7 +162,7 @@
         dest.writeLong(creationTime);
         dest.writeLong(lastLoggedInTime);
         dest.writeInt(partial ? 1 : 0);
-        dest.writeInt(relatedGroupId);
+        dest.writeInt(profileGroupId);
     }
 
     public static final Parcelable.Creator<UserInfo> CREATOR
@@ -184,6 +184,6 @@
         creationTime = source.readLong();
         lastLoggedInTime = source.readLong();
         partial = source.readInt() != 0;
-        relatedGroupId = source.readInt();
+        profileGroupId = source.readInt();
     }
 }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 48b6fca..a07fc97 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -440,6 +440,11 @@
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a>
      * resource qualifier. */
     public static final int UI_MODE_TYPE_APPLIANCE = 0x05;
+    /** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
+     * value that corresponds to the
+     * <a href="{@docRoot}guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a>
+     * resource qualifier. */
+    public static final int UI_MODE_TYPE_WATCH = 0x06;
 
     /** Constant for {@link #uiMode}: bits that encode the night mode. */
     public static final int UI_MODE_NIGHT_MASK = 0x30;
@@ -462,8 +467,8 @@
      * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
      * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
      * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
-     * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, or
-     * {@link #UI_MODE_TYPE_APPLIANCE}.
+     * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
+     * {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_MODE_TYPE_WATCH}.
      *
      * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
      * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
@@ -700,6 +705,7 @@
             case UI_MODE_TYPE_CAR: sb.append(" car"); break;
             case UI_MODE_TYPE_TELEVISION: sb.append(" television"); break;
             case UI_MODE_TYPE_APPLIANCE: sb.append(" appliance"); break;
+            case UI_MODE_TYPE_WATCH: sb.append(" watch"); break;
             default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
         }
         switch ((uiMode&UI_MODE_NIGHT_MASK)) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index affc784..4879c23 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -114,7 +114,6 @@
     private boolean mPreloading;
 
     private TypedArray mCachedStyledAttributes = null;
-    private RuntimeException mLastRetrievedAttrs = null;
 
     private int mLastCachedXmlBlockIndex = -1;
     private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
@@ -136,17 +135,31 @@
         sPreloadedDrawables[1] = new LongSparseArray<ConstantState>();
     }
 
-    /** @hide */
+    /**
+     * Returns the most appropriate default theme for the specified target SDK version.
+     * <ul>
+     * <li>Below API 11: Gingerbread
+     * <li>APIs 11 thru 14: Holo
+     * <li>APIs 14 thru XX: Device default dark
+     * <li>API XX and above: Device default light with dark action bar
+     * </ul>
+     *
+     * @param curTheme The current theme, or 0 if not specified.
+     * @param targetSdkVersion The target SDK version.
+     * @return A theme resource identifier
+     * @hide
+     */
     public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
         return selectSystemTheme(curTheme, targetSdkVersion,
                 com.android.internal.R.style.Theme,
                 com.android.internal.R.style.Theme_Holo,
-                com.android.internal.R.style.Theme_DeviceDefault);
+                com.android.internal.R.style.Theme_DeviceDefault,
+                com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
     }
-    
+
     /** @hide */
-    public static int selectSystemTheme(int curTheme, int targetSdkVersion,
-            int orig, int holo, int deviceDefault) {
+    public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
+            int dark, int deviceDefault) {
         if (curTheme != 0) {
             return curTheme;
         }
@@ -156,9 +169,12 @@
         if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
             return holo;
         }
+        if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
+            return dark;
+        }
         return deviceDefault;
     }
-    
+
     /**
      * This exception is thrown by the resource APIs when a requested resource
      * can not be found.
@@ -1253,12 +1269,9 @@
         public void applyStyle(int resid, boolean force) {
             AssetManager.applyThemeStyle(mTheme, resid, force);
 
-            if (!mHasStyle) {
-                mHasStyle = true;
-                mThemeResId = resid;
-            } else if (resid != mThemeResId) {
-                mThemeResId = 0;
-            }
+            // TODO: In very rare cases, we may end up with a hybrid theme
+            // that can't map to a single theme ID.
+            mThemeResId = resid;
         }
 
         /**
@@ -1273,7 +1286,6 @@
         public void setTo(Theme other) {
             AssetManager.copyTheme(mTheme, other.mTheme);
 
-            mHasStyle = other.mHasStyle;
             mThemeResId = other.mThemeResId;
         }
 
@@ -1562,10 +1574,6 @@
             mAssets.releaseTheme(mTheme);
         }
 
-        /*package*/ boolean canCacheDrawables() {
-            return mHasStyle && mThemeResId != 0;
-        }
-
         /*package*/ Theme() {
             mAssets = Resources.this.mAssets;
             mTheme = mAssets.createTheme();
@@ -1575,12 +1583,17 @@
         private final AssetManager mAssets;
         private final long mTheme;
 
-        /**
-         * Resource identifier for the theme. If multiple styles have been
-         * applied to this theme, this value will be 0 (invalid).
-         */
+        /** Resource identifier for the theme. */
         private int mThemeResId = 0;
-        private boolean mHasStyle = false;
+
+        // Needed by layoutlib.
+        /*package*/ long getNativeTheme() {
+            return mTheme;
+        }
+
+        /*package*/ int getAppliedStyleResId() {
+            return mThemeResId;
+        }
     }
 
     /**
@@ -2260,11 +2273,6 @@
             return;
         }
 
-        // Abort if the drawable is themed, but the theme cannot be cached.
-        if (dr.canApplyTheme() && theme != null && !theme.canCacheDrawables()) {
-            return;
-        }
-
         if (mPreloading) {
             // Preloaded drawables never have a theme, but may be themeable.
             final int changingConfigs = cs.getChangingConfigurations();
@@ -2289,11 +2297,7 @@
         } else {
             synchronized (mAccessLock) {
                 final LongSparseArray<WeakReference<ConstantState>> themedCache;
-                if (!dr.canApplyTheme()) {
-                    themedCache = caches.getUnthemed(true);
-                } else {
-                    themedCache = caches.getOrCreate(theme == null ? 0 : theme.mThemeResId);
-                }
+                themedCache = caches.getOrCreate(theme == null ? 0 : theme.mThemeResId);
                 themedCache.put(key, new WeakReference<ConstantState>(cs));
             }
         }
@@ -2354,21 +2358,6 @@
 
     private Drawable getCachedDrawable(ThemedCaches<ConstantState> caches, long key, Theme theme) {
         synchronized (mAccessLock) {
-            // First, check for a matching unthemed drawable.
-            final LongSparseArray<WeakReference<ConstantState>> unthemed = caches.getUnthemed(false);
-            if (unthemed != null) {
-                final Drawable unthemedDrawable = getCachedDrawableLocked(unthemed, key);
-                if (unthemedDrawable != null) {
-                    return unthemedDrawable;
-                }
-            }
-
-            final boolean themeCannotCache = theme != null && !theme.canCacheDrawables();
-            if (themeCannotCache) {
-                return null;
-            }
-
-            // Next, check for a matching themed drawable.
             final int themeKey = theme != null ? theme.mThemeResId : 0;
             final LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
             if (themedCache != null) {
@@ -2606,18 +2595,6 @@
     }
 
     static class ThemedCaches<T> extends SparseArray<LongSparseArray<WeakReference<T>>> {
-        private LongSparseArray<WeakReference<T>> mUnthemed = null;
-
-        /**
-         * Returns the cache of drawables with no themeable attributes.
-         */
-        public LongSparseArray<WeakReference<T>> getUnthemed(boolean autoCreate) {
-            if (mUnthemed == null && autoCreate) {
-                mUnthemed = new LongSparseArray<WeakReference<T>>(1);
-            }
-            return mUnthemed;
-        }
-
         /**
          * Returns the cache of drawables styled for the specified theme.
          * <p>
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 9fb2846..15337ce 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -32,7 +32,7 @@
  * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
  * or {@link Resources#obtainAttributes}.  Be
  * sure to call {@link #recycle} when done with them.
- * 
+ *
  * The indices used to retrieve values from this structure correspond to
  * the positions of the attributes given to obtainStyledAttributes.
  */
@@ -46,6 +46,7 @@
             attrs.mResources = res;
             attrs.mMetrics = res.getDisplayMetrics();
             attrs.mAssets = res.getAssets();
+            attrs.mRecycled = false;
 
             final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
             if (attrs.mData.length >= fullLen) {
@@ -65,6 +66,8 @@
     private Resources mResources;
     private DisplayMetrics mMetrics;
     private AssetManager mAssets;
+    private boolean mRecycled;
+
     /*package*/ XmlBlock.Parser mXml;
     /*package*/ Resources.Theme mTheme;
     /*package*/ int[] mData;
@@ -76,45 +79,65 @@
      * Return the number of values in this array.
      */
     public int length() {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         return mLength;
     }
-    
+
     /**
      * Return the number of indices in the array that actually have data.
      */
     public int getIndexCount() {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         return mIndices[0];
     }
-    
+
     /**
      * Return an index in the array that has data.
-     * 
+     *
      * @param at The index you would like to returned, ranging from 0 to
      * {@link #getIndexCount()}.
-     * 
+     *
      * @return The index at the given offset, which can be used with
      * {@link #getValue} and related APIs.
      */
     public int getIndex(int at) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         return mIndices[1+at];
     }
-    
+
     /**
      * Return the Resources object this array was loaded from.
      */
     public Resources getResources() {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         return mResources;
     }
-    
+
     /**
      * Retrieve the styled string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return CharSequence holding string data.  May be styled.  Returns 
+     *
+     * @return CharSequence holding string data.  May be styled.  Returns
      *         null if the attribute is not defined.
      */
     public CharSequence getText(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -136,13 +159,17 @@
 
     /**
      * Retrieve the string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return String holding string data.  Any styling information is
      * removed.  Returns null if the attribute is not defined.
      */
     public String getString(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -170,14 +197,18 @@
      * attributes, or conversions from other types.  As such, this method
      * will only return strings for TypedArray objects that come from
      * attributes in an XML file.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return String holding string data.  Any styling information is
      * removed.  Returns null if the attribute is not defined or is not
      * an immediate string value.
      */
     public String getNonResourceString(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -190,12 +221,12 @@
         }
         return null;
     }
-    
+
     /**
      * @hide
      * Retrieve the string value for the attribute at <var>index</var> that is
      * not allowed to change with the given configurations.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param allowedChangingConfigs Bit mask of configurations from
      * {@link Configuration}.NATIVE_CONFIG_* that are allowed to change.
@@ -204,6 +235,10 @@
      * removed.  Returns null if the attribute is not defined.
      */
     public String getNonConfigurationString(int index, int allowedChangingConfigs) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -229,13 +264,17 @@
 
     /**
      * Retrieve the boolean value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute boolean value, or defValue if not defined.
      */
     public boolean getBoolean(int index, boolean defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -259,13 +298,17 @@
 
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute int value, or defValue if not defined.
      */
     public int getInt(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -289,12 +332,16 @@
 
     /**
      * Retrieve the float value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Attribute float value, or defValue if not defined..
      */
     public float getFloat(int index, float defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -319,20 +366,24 @@
               + Integer.toHexString(type));
         return defValue;
     }
-    
+
     /**
      * Retrieve the color value for the attribute at <var>index</var>.  If
      * the attribute references a color resource holding a complex
      * {@link android.content.res.ColorStateList}, then the default color from
      * the set is returned.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute color value, or defValue if not defined.
      */
     public int getColor(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -359,12 +410,16 @@
      * Retrieve the ColorStateList for the attribute at <var>index</var>.
      * The value may be either a single solid color or a reference to
      * a color or complex {@link android.content.res.ColorStateList} description.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return ColorStateList for the attribute, or null if not defined.
      */
     public ColorStateList getColorStateList(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         final TypedValue value = mValue;
         if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             return mResources.loadColorStateList(value, value.resourceId);
@@ -374,14 +429,18 @@
 
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute integer value, or defValue if not defined.
      */
     public int getInteger(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -397,22 +456,26 @@
     }
 
     /**
-     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit 
-     * conversions are based on the current {@link DisplayMetrics} 
-     * associated with the resources this {@link TypedArray} object 
-     * came from. 
-     * 
+     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit
+     * conversions are based on the current {@link DisplayMetrics}
+     * associated with the resources this {@link TypedArray} object
+     * came from.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric, or defValue if not defined.
-     * 
+     *
      * @see #getDimensionPixelOffset
      * @see #getDimensionPixelSize
      */
     public float getDimension(int index, float defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -433,18 +496,22 @@
      * {@link #getDimension}, except the returned value is converted to
      * integer pixels for you.  An offset conversion involves simply
      * truncating the base value to an integer.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     * 
+     *
      * @see #getDimension
      * @see #getDimensionPixelSize
      */
     public int getDimensionPixelOffset(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -466,18 +533,22 @@
      * integer pixels for use as a size.  A size conversion involves
      * rounding the base value, and ensuring that a non-zero base value
      * is at least one pixel in size.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     *  
+     *
      * @see #getDimension
      * @see #getDimensionPixelOffset
      */
     public int getDimensionPixelSize(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -497,14 +568,18 @@
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param name Textual name of attribute for error reporting.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels.
      */
     public int getLayoutDimension(int index, String name) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -519,21 +594,25 @@
         throw new RuntimeException(getPositionDescription()
                 + ": You must supply a " + name + " attribute.");
     }
-    
+
     /**
      * Special version of {@link #getDimensionPixelSize} for retrieving
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param defValue The default value to return if this attribute is not
      * default or contains the wrong type of data.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels.
      */
     public int getLayoutDimension(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -550,20 +629,24 @@
 
     /**
      * Retrieve a fractional unit attribute at <var>index</var>.
-     * 
-     * @param index Index of attribute to retrieve. 
-     * @param base The base value of this fraction.  In other words, a 
+     *
+     * @param index Index of attribute to retrieve.
+     * @param base The base value of this fraction.  In other words, a
      *             standard fraction is multiplied by this value.
-     * @param pbase The parent base value of this fraction.  In other 
+     * @param pbase The parent base value of this fraction.  In other
      *             words, a parent fraction (nn%p) is multiplied by this
      *             value.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute fractional value multiplied by the appropriate 
-     * base value, or defValue if not defined. 
+     *
+     * @return Attribute fractional value multiplied by the appropriate
+     * base value, or defValue if not defined.
      */
     public float getFraction(int index, int base, int pbase, float defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
@@ -580,19 +663,23 @@
 
     /**
      * Retrieve the resource identifier for the attribute at
-     * <var>index</var>.  Note that attribute resource as resolved when 
-     * the overall {@link TypedArray} object is retrieved.  As a 
-     * result, this function will return the resource identifier of the 
-     * final resource value that was found, <em>not</em> necessarily the 
-     * original resource that was specified by the attribute. 
-     * 
+     * <var>index</var>.  Note that attribute resource as resolved when
+     * the overall {@link TypedArray} object is retrieved.  As a
+     * result, this function will return the resource identifier of the
+     * final resource value that was found, <em>not</em> necessarily the
+     * original resource that was specified by the attribute.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute resource identifier, or defValue if not defined.
      */
     public int getResourceId(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
@@ -615,6 +702,10 @@
      * @hide
      */
     public int getThemeAttributeId(int index, int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
@@ -628,12 +719,16 @@
      * gets the resource ID of the selected attribute, and uses
      * {@link Resources#getDrawable Resources.getDrawable} of the owning
      * Resources object to retrieve its Drawable.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Drawable for the attribute, or null if not defined.
      */
     public Drawable getDrawable(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         final TypedValue value = mValue;
         if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (false) {
@@ -655,12 +750,16 @@
      * This gets the resource ID of the selected attribute, and uses
      * {@link Resources#getTextArray Resources.getTextArray} of the owning
      * Resources object to retrieve its String[].
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return CharSequence[] for the attribute, or null if not defined.
      */
     public CharSequence[] getTextArray(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         final TypedValue value = mValue;
         if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             if (false) {
@@ -679,36 +778,19 @@
 
     /**
      * Retrieve the raw TypedValue for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param outValue TypedValue object in which to place the attribute's
      *                 data.
-     * 
-     * @return Returns true if the value was retrieved, else false. 
+     *
+     * @return Returns true if the value was retrieved, else false.
      */
     public boolean getValue(int index, TypedValue outValue) {
-        return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
-    }
-
-    /**
-     * Determines whether this TypedArray contains an attribute of the specified
-     * type.
-     *
-     * @param type Type of data, e.g. {@link TypedValue#TYPE_ATTRIBUTE}
-     * @return True if the TypedArray contains an attribute of the specified
-     *         type.
-     * @hide
-     */
-    public boolean hasType(int type) {
-        final int[] data = mData;
-        final int N = getIndexCount();
-        for (int i = 0; i < N; i++) {
-            final int index = getIndex(i) * AssetManager.STYLE_NUM_ENTRIES;
-            if (data[index + AssetManager.STYLE_TYPE] == type) {
-                return true;
-            }
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
-        return false;
+
+        return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
     }
 
     /**
@@ -718,36 +800,48 @@
      * @return Attribute type.
      */
     public int getType(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         return mData[index + AssetManager.STYLE_TYPE];
     }
 
     /**
      * Determines whether there is an attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return True if the attribute has a value, false otherwise.
      */
     public boolean hasValue(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
         return type != TypedValue.TYPE_NULL;
     }
-    
+
     /**
-     * Retrieve the raw TypedValue for the attribute at <var>index</var> 
-     * and return a temporary object holding its data.  This object is only 
-     * valid until the next call on to {@link TypedArray}. 
-     * 
+     * Retrieve the raw TypedValue for the attribute at <var>index</var>
+     * and return a temporary object holding its data.  This object is only
+     * valid until the next call on to {@link TypedArray}.
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return Returns a TypedValue object if the attribute is defined, 
+     *
+     * @return Returns a TypedValue object if the attribute is defined,
      *         containing its data; otherwise returns null.  (You will not
      *         receive a TypedValue whose type is TYPE_NULL.)
      */
     public TypedValue peekValue(int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         final TypedValue value = mValue;
         if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
             return value;
@@ -759,13 +853,23 @@
      * Returns a message about the parser state suitable for printing error messages.
      */
     public String getPositionDescription() {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         return mXml != null ? mXml.getPositionDescription() : "<internal>";
     }
 
     /**
-     * Give back a previously retrieved array, for later re-use.
+     * Recycle the TypedArray, to be re-used by a later caller. After calling
+     * this function you must not ever touch the typed array again.
      */
     public void recycle() {
+        if (mRecycled) {
+            throw new RuntimeException(toString() + " recycled twice!");
+        }
+
+        mRecycled = true;
         mResources = null;
         mMetrics = null;
         mAssets = null;
@@ -791,6 +895,10 @@
      * @hide
      */
     public int[] extractThemeAttrs() {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
         int[] attrs = null;
 
         final int N = length();
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 37bead8..9852776 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -950,6 +950,19 @@
             new Key<int[]>("android.sensor.info.sensitivityRange", int[].class);
 
     /**
+     * <p>Arrangement of color filters on sensor;
+     * represents the colors in the top-left 2x2 section of
+     * the sensor, in reading order</p>
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB
+     */
+    public static final Key<Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT =
+            new Key<Integer>("android.sensor.info.colorFilterArrangement", int.class);
+
+    /**
      * <p>Range of valid exposure
      * times used by {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}.</p>
      *
@@ -1093,8 +1106,8 @@
      *
      * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
      */
-    public static final Key<Byte> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
-            new Key<Byte>("android.sensor.availableTestPatternModes", byte.class);
+    public static final Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
+            new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
 
     /**
      * <p>Which face detection modes are available,
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 42c8e3da..1e34498 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -425,6 +425,38 @@
     public static final int SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT = 1;
 
     //
+    // Enumeration values for CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+    //
+
+    /**
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3;
+
+    /**
+     * <p>Sensor is not Bayer; output has 3 16-bit
+     * values for each pixel, instead of just 1 16-bit value
+     * per pixel.</p>
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
+
+    //
     // Enumeration values for CameraCharacteristics#LED_AVAILABLE_LEDS
     //
 
@@ -1002,8 +1034,11 @@
      * controls; the camera device will ignore those settings while
      * USE_SCENE_MODE is active (except for FACE_PRIORITY
      * scene mode). Other control entries are still active.
-     * This setting can only be used if availableSceneModes !=
-     * UNSUPPORTED</p>
+     * This setting can only be used if scene mode is supported
+     * (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes} contain some modes
+     * other than DISABLED).</p>
+     *
+     * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
      * @see CaptureRequest#CONTROL_MODE
      */
     public static final int CONTROL_MODE_USE_SCENE_MODE = 2;
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 2c8a5c2..ecc461e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -335,7 +335,9 @@
                 mRepeatingRequestId = REQUEST_ID_NONE;
 
                 // Queue for deletion after in-flight requests finish
-                mRepeatingRequestIdDeletedList.add(requestId);
+                if (mCaptureListenerMap.get(requestId) != null) {
+                    mRepeatingRequestIdDeletedList.add(requestId);
+                }
 
                 try {
                     mRemoteDevice.cancelRequest(requestId);
@@ -367,8 +369,6 @@
             }
 
             mRepeatingRequestId = REQUEST_ID_NONE;
-            mRepeatingRequestIdDeletedList.clear();
-            mCaptureListenerMap.clear();
         }
     }
 
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index 38d9de4..8578a32 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -160,6 +160,12 @@
     public static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2;
     public static final int MESSAGE_ABORT = 0xFF;
 
+    public static final int POWER_STATUS_UNKNOWN = -1;
+    public static final int POWER_STATUS_ON = 0;
+    public static final int POWER_STATUS_STANDBY = 1;
+    public static final int POWER_TRANSIENT_TO_ON = 2;
+    public static final int POWER_TRANSIENT_TO_STANDBY = 3;
+
     private static final int[] ADDRESS_TO_TYPE = {
         DEVICE_TV,  // ADDR_TV
         DEVICE_RECORDER,  // ADDR_RECORDER_1
diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java
index d7f4a72..1f382e6 100644
--- a/core/java/android/hardware/hdmi/HdmiCecClient.java
+++ b/core/java/android/hardware/hdmi/HdmiCecClient.java
@@ -110,16 +110,20 @@
     }
 
     /**
-     * Send &lt;GiveDevicePowerStatus&gt; message.
+     * Returns true if the TV or attached display is powered on.
+     * <p>
+     * The result of this method is only meaningful on playback devices (where the device
+     * type is {@link HdmiCec#DEVICE_PLAYBACK}).
+     * </p>
      *
-     * @param address logical address of the device to send the message to, such as
-     *        {@link HdmiCec#ADDR_TV}.
+     * @return true if TV is on; otherwise false.
      */
-    public void sendGiveDevicePowerStatus(int address) {
+    public boolean isTvOn() {
         try {
-            mService.sendGiveDevicePowerStatus(mBinder, address);
+            return mService.isTvOn(mBinder);
         } catch (RemoteException e) {
-            Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e);
+            Log.e(TAG, "isTvOn threw exception ", e);
         }
+        return false;
     }
 }
diff --git a/core/java/android/hardware/hdmi/HdmiCecManager.java b/core/java/android/hardware/hdmi/HdmiCecManager.java
index 575785d..10b058c 100644
--- a/core/java/android/hardware/hdmi/HdmiCecManager.java
+++ b/core/java/android/hardware/hdmi/HdmiCecManager.java
@@ -45,6 +45,9 @@
      * @return {@link HdmiCecClient} instance. {@code null} on failure.
      */
     public HdmiCecClient getClient(int type, HdmiCecClient.Listener listener) {
+        if (mService == null) {
+            return null;
+        }
         try {
             IBinder b = mService.allocateLogicalDevice(type, getListenerWrapper(listener));
             return HdmiCecClient.create(mService, b);
diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
index 6fefcf8..b5df131 100644
--- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
@@ -29,12 +29,11 @@
 interface IHdmiCecService {
     IBinder allocateLogicalDevice(int type, IHdmiCecListener listener);
     void removeServiceListener(IBinder b, IHdmiCecListener listener);
-    void setOsdName(IBinder b, String name);
     void sendActiveSource(IBinder b);
     void sendInactiveSource(IBinder b);
     void sendImageViewOn(IBinder b);
     void sendTextViewOn(IBinder b);
-    void sendGiveDevicePowerStatus(IBinder b, int address);
+    boolean isTvOn(IBinder b);
     void sendMessage(IBinder b, in HdmiCecMessage message);
 }
 
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 81ad28b..c51d1a7 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -249,6 +249,16 @@
      */
     public static final int IME_VISIBLE = 0x2;
 
+    /**
+     * The IME does not require cursor/anchor position.
+     */
+    public static final int CURSOR_ANCHOR_MONITOR_MODE_NONE = 0x0;
+
+    /**
+     * The IME expects that {@link #onUpdateCursor(Rect)} is called back.
+     */
+    public static final int CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT = 0x1;
+
     InputMethodManager mImm;
     
     int mTheme = 0;
@@ -647,6 +657,7 @@
                 getApplicationInfo().targetSdkVersion,
                 android.R.style.Theme_InputMethod,
                 android.R.style.Theme_Holo_InputMethod,
+                android.R.style.Theme_DeviceDefault_InputMethod,
                 android.R.style.Theme_DeviceDefault_InputMethod);
         super.setTheme(mTheme);
         super.onCreate();
@@ -1701,6 +1712,13 @@
     }
 
     /**
+     * Update the cursor/anthor monitor mode.
+     */
+    public void setCursorAnchorMonitorMode(int monitorMode) {
+        mImm.setCursorAnchorMonitorMode(mToken, monitorMode);
+    }
+
+    /**
      * Close this input method's soft input area, removing it from the display.
      * The input method will continue running, but the user can no longer use
      * it to generate input by touching the screen.
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index a500bcf..830ddce 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -56,7 +56,8 @@
         if (tm instanceof TrustManagerImpl) {
             mDelegate = (TrustManagerImpl) tm;
         } else {
-            throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+            throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() +
+                    " which is not a supported type of X509TrustManager");
         }
     }
 
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index d8e8e2c..377ed88 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -211,6 +211,7 @@
     private Context mContext;
 
     private static final int INVALID_LISTENER_KEY = 0;
+    private static final int BUSY_LISTENER_KEY = -1;
     private int mListenerKey = 1;
     private final SparseArray mListenerMap = new SparseArray();
     private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<NsdServiceInfo>();
@@ -317,71 +318,74 @@
                 Log.d(TAG, "Stale key " + message.arg2);
                 return;
             }
-            boolean listenerRemove = true;
             NsdServiceInfo ns = getNsdService(message.arg2);
             switch (message.what) {
                 case DISCOVER_SERVICES_STARTED:
                     String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
                     ((DiscoveryListener) listener).onDiscoveryStarted(s);
-                    // Keep listener until stop discovery
-                    listenerRemove = false;
                     break;
                 case DISCOVER_SERVICES_FAILED:
+                    removeListener(message.arg2);
                     ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
                             message.arg1);
                     break;
                 case SERVICE_FOUND:
                     ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj);
-                    // Keep listener until stop discovery
-                    listenerRemove = false;
                     break;
                 case SERVICE_LOST:
                     ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj);
-                    // Keep listener until stop discovery
-                    listenerRemove = false;
                     break;
                 case STOP_DISCOVERY_FAILED:
+                    removeListener(message.arg2);
                     ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
                             message.arg1);
                     break;
                 case STOP_DISCOVERY_SUCCEEDED:
+                    removeListener(message.arg2);
                     ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
                     break;
                 case REGISTER_SERVICE_FAILED:
+                    removeListener(message.arg2);
                     ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
                     break;
                 case REGISTER_SERVICE_SUCCEEDED:
                     ((RegistrationListener) listener).onServiceRegistered(
                             (NsdServiceInfo) message.obj);
-                    // Keep listener until unregister
-                    listenerRemove = false;
                     break;
                 case UNREGISTER_SERVICE_FAILED:
+                    removeListener(message.arg2);
                     ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
                     break;
                 case UNREGISTER_SERVICE_SUCCEEDED:
+                    removeListener(message.arg2);
                     ((RegistrationListener) listener).onServiceUnregistered(ns);
                     break;
                 case RESOLVE_SERVICE_FAILED:
+                    removeListener(message.arg2);
                     ((ResolveListener) listener).onResolveFailed(ns, message.arg1);
                     break;
                 case RESOLVE_SERVICE_SUCCEEDED:
+                    removeListener(message.arg2);
                     ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
                     break;
                 default:
                     Log.d(TAG, "Ignored " + message);
                     break;
             }
-            if (listenerRemove) {
-                removeListener(message.arg2);
-            }
         }
     }
 
+    // if the listener is already in the map, reject it.  Otherwise, add it and
+    // return its key.
+
     private int putListener(Object listener, NsdServiceInfo s) {
         if (listener == null) return INVALID_LISTENER_KEY;
         int key;
         synchronized (mMapLock) {
+            int valueIndex = mListenerMap.indexOfValue(listener);
+            if (valueIndex != -1) {
+                return BUSY_LISTENER_KEY;
+            }
             do {
                 key = mListenerKey++;
             } while (key == INVALID_LISTENER_KEY);
@@ -422,7 +426,6 @@
         return INVALID_LISTENER_KEY;
     }
 
-
     private String getNsdServiceInfoType(NsdServiceInfo s) {
         if (s == null) return "?";
         return s.getServiceType();
@@ -449,14 +452,18 @@
      * Register a service to be discovered by other services.
      *
      * <p> The function call immediately returns after sending a request to register service
-     * to the framework. The application is notified of a success to initiate
-     * discovery through the callback {@link RegistrationListener#onServiceRegistered} or a failure
+     * to the framework. The application is notified of a successful registration
+     * through the callback {@link RegistrationListener#onServiceRegistered} or a failure
      * through {@link RegistrationListener#onRegistrationFailed}.
      *
+     * <p> The application should call {@link #unregisterService} when the service
+     * registration is no longer required, and/or whenever the application is stopped.
+     *
      * @param serviceInfo The service being registered
      * @param protocolType The service discovery protocol
      * @param listener The listener notifies of a successful registration and is used to
      * unregister this service through a call on {@link #unregisterService}. Cannot be null.
+     * Cannot be in use for an active service registration.
      */
     public void registerService(NsdServiceInfo serviceInfo, int protocolType,
             RegistrationListener listener) {
@@ -473,8 +480,11 @@
         if (protocolType != PROTOCOL_DNS_SD) {
             throw new IllegalArgumentException("Unsupported protocol");
         }
-        mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, putListener(listener, serviceInfo),
-                serviceInfo);
+        int key = putListener(listener, serviceInfo);
+        if (key == BUSY_LISTENER_KEY) {
+            throw new IllegalArgumentException("listener already in use");
+        }
+        mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo);
     }
 
     /**
@@ -484,7 +494,11 @@
      *
      * @param listener This should be the listener object that was passed to
      * {@link #registerService}. It identifies the service that should be unregistered
-     * and notifies of a successful unregistration.
+     * and notifies of a successful or unsuccessful unregistration via the listener
+     * callbacks.  In API versions 20 and above, the listener object may be used for
+     * another service registration once the callback has been called.  In API versions <= 19,
+     * there is no entirely reliable way to know when a listener may be re-used, and a new
+     * listener should be created for each service registration request.
      */
     public void unregisterService(RegistrationListener listener) {
         int id = getListenerKey(listener);
@@ -514,12 +528,16 @@
      * <p> Upon failure to start, service discovery is not active and application does
      * not need to invoke {@link #stopServiceDiscovery}
      *
+     * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
+     * service type is no longer required, and/or whenever the application is paused or
+     * stopped.
+     *
      * @param serviceType The service type being discovered. Examples include "_http._tcp" for
      * http services or "_ipp._tcp" for printers
      * @param protocolType The service discovery protocol
      * @param listener  The listener notifies of a successful discovery and is used
      * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
-     * Cannot be null.
+     * Cannot be null. Cannot be in use for an active service discovery.
      */
     public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
         if (listener == null) {
@@ -535,11 +553,17 @@
 
         NsdServiceInfo s = new NsdServiceInfo();
         s.setServiceType(serviceType);
-        mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, putListener(listener, s), s);
+
+        int key = putListener(listener, s);
+        if (key == BUSY_LISTENER_KEY) {
+            throw new IllegalArgumentException("listener already in use");
+        }
+
+        mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s);
     }
 
     /**
-     * Stop service discovery initiated with {@link #discoverServices}. An active service
+     * Stop service discovery initiated with {@link #discoverServices}.  An active service
      * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
      * and it stays active until the application invokes a stop service discovery. A successful
      * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}.
@@ -548,7 +572,11 @@
      * {@link DiscoveryListener#onStopDiscoveryFailed}.
      *
      * @param listener This should be the listener object that was passed to {@link #discoverServices}.
-     * It identifies the discovery that should be stopped and notifies of a successful stop.
+     * It identifies the discovery that should be stopped and notifies of a successful or
+     * unsuccessful stop.  In API versions 20 and above, the listener object may be used for
+     * another service discovery once the callback has been called.  In API versions <= 19,
+     * there is no entirely reliable way to know when a listener may be re-used, and a new
+     * listener should be created for each service discovery request.
      */
     public void stopServiceDiscovery(DiscoveryListener listener) {
         int id = getListenerKey(listener);
@@ -568,6 +596,7 @@
      *
      * @param serviceInfo service to be resolved
      * @param listener to receive callback upon success or failure. Cannot be null.
+     * Cannot be in use for an active service resolution.
      */
     public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
         if (TextUtils.isEmpty(serviceInfo.getServiceName()) ||
@@ -577,8 +606,13 @@
         if (listener == null) {
             throw new IllegalArgumentException("listener cannot be null");
         }
-        mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, putListener(listener, serviceInfo),
-                serviceInfo);
+
+        int key = putListener(listener, serviceInfo);
+
+        if (key == BUSY_LISTENER_KEY) {
+            throw new IllegalArgumentException("listener already in use");
+        }
+        mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo);
     }
 
     /** Internal use only @hide */
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index d03b0c5..be3c0cc 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,7 +23,7 @@
 
 interface IPowerManager
 {
-    // WARNING: The first four methods must remain the first three methods because their
+    // WARNING: The first five methods must remain the first five methods because their
     // transaction numbers must not change unless IPowerManager.cpp is also updated.
     void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
             String historyTag);
@@ -31,6 +31,7 @@
             int uidtoblame);
     void releaseWakeLock(IBinder lock, int flags);
     void updateWakeLockUids(IBinder lock, in int[] uids);
+    oneway void powerHint(int hintId, int data);
 
     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
     boolean isWakeLockLevelSupported(int level);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 6e6c06d..1192a45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -28,13 +28,13 @@
  */
 interface IUserManager {
     UserInfo createUser(in String name, int flags);
-    UserInfo createRelatedUser(in String name, int flags, int relatedUserId);
+    UserInfo createProfileForUser(in String name, int flags, int userHandle);
     boolean removeUser(int userHandle);
     void setUserName(int userHandle, String name);
     void setUserIcon(int userHandle, in Bitmap icon);
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
-    List<UserInfo> getRelatedUsers(int userHandle);
+    List<UserInfo> getProfiles(int userHandle);
     UserInfo getUserInfo(int userHandle);
     boolean isRestricted();
     void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 057f516..3241693 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,10 +16,11 @@
 
 package android.os;
 
-import android.net.LocalSocketAddress;
 import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.util.Log;
-import dalvik.system.Zygote;
+
+import com.android.internal.os.Zygote;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1ec5cd5..031cba7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -20,10 +20,16 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Bitmap.Config;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.util.Log;
 
 import com.android.internal.R;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -410,20 +416,29 @@
     }
 
     /**
-     * Creates a user with the specified name and options.
+     * Renamed, just present to avoid multi project commit.
+     * TODO delete.
+     * @hide
+     */
+    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+        return createProfileForUser(name, flags, relatedUserId);
+    }
+
+    /**
+     * Creates a user with the specified name and options as a profile of another user.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param name the user's name
      * @param flags flags that identify the type of user and other properties.
      * @see UserInfo
-     * @param relatedUserId new user will be related to this user id.
+     * @param userHandle new user will be a profile of this use.
      *
      * @return the UserInfo object for the created user, or null if the user could not be created.
      * @hide
      */
-    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+    public UserInfo createProfileForUser(String name, int flags, int userHandle) {
         try {
-            return mService.createRelatedUser(name, flags, relatedUserId);
+            return mService.createProfileForUser(name, flags, userHandle);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not create a user", re);
             return null;
@@ -454,15 +469,26 @@
     }
 
     /**
-     * Returns information for all users related to userId
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
-     * @param userHandle users related to this user id will be returned.
-     * @return the list of related users.
+     * Renaming, left to avoid multi project commit.
+     * TODO Delete.
      * @hide
      */
     public List<UserInfo> getRelatedUsers(int userHandle) {
+        return getProfiles(userHandle);
+    }
+
+    /**
+     * Returns list of the profiles of userHandle including
+     * userHandle itself.
+     *
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @param userHandle profiles of this user will be returned.
+     * @return the list of profiles.
+     * @hide
+     */
+    public List<UserInfo> getProfiles(int userHandle) {
         try {
-            return mService.getRelatedUsers(userHandle);
+            return mService.getProfiles(userHandle);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not get user list", re);
             return null;
@@ -470,9 +496,66 @@
     }
 
     /**
-     * Returns information for all users on this device.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
-     * @param excludeDying specify if the list should exclude users being removed.
+     * Returns a list of UserHandles for profiles associated with this user, including this user.
+     *
+     * @return A non-empty list of UserHandles associated with the calling user.
+     */
+    public List<UserHandle> getUserProfiles() {
+        ArrayList<UserHandle> profiles = new ArrayList<UserHandle>();
+        List<UserInfo> users = getProfiles(UserHandle.myUserId());
+        for (UserInfo info : users) {
+            UserHandle userHandle = new UserHandle(info.id);
+            profiles.add(userHandle);
+        }
+        return profiles;
+    }
+
+    /** @hide */
+    public Drawable getBadgedDrawableForUser(Drawable icon, UserHandle user) {
+        int badgeResId = getBadgeResIdForUser(user.getIdentifier());
+        if (badgeResId == 0) {
+            return icon;
+        } else {
+            Drawable badgeIcon = mContext.getPackageManager()
+                    .getDrawable("system", badgeResId, null);
+            return getMergedDrawable(icon, badgeIcon);
+        }
+    }
+
+    private int getBadgeResIdForUser(int userHandle) {
+        // Return the framework-provided badge.
+        List<UserInfo> userProfiles = getProfiles(UserHandle.myUserId());
+        for (UserInfo user : userProfiles) {
+            if (user.id == userHandle
+                    && user.isManagedProfile()) {
+                return com.android.internal.R.drawable.ic_corp_badge;
+            }
+        }
+        return 0;
+    }
+
+    private Drawable getMergedDrawable(Drawable icon, Drawable badge) {
+        final int width = icon.getIntrinsicWidth();
+        final int height = icon.getIntrinsicHeight();
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        icon.setBounds(0, 0, width, height);
+        icon.draw(canvas);
+        badge.setBounds(0, 0, width, height);
+        badge.draw(canvas);
+        BitmapDrawable merged = new BitmapDrawable(bitmap);
+        if (icon instanceof BitmapDrawable) {
+            merged.setTargetDensity(((BitmapDrawable) icon).getBitmap().getDensity());
+        }
+        return merged;
+    }
+
+    /**
+     * Returns information for all users on this device. Requires
+     * {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * 
+     * @param excludeDying specify if the list should exclude users being
+     *            removed.
      * @return the list of users that were created.
      * @hide
      */
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index b97734e..2ef5b66 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -694,6 +694,67 @@
                 return _result;
             }
 
+            public String getPassword() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_getPassword, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
+            public void clearPassword() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, IBinder.FLAG_ONEWAY);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            public void setField(String field, String data) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(field);
+                    _data.writeString(data);
+                    mRemote.transact(Stub.TRANSACTION_setField, _data, _reply, IBinder.FLAG_ONEWAY);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            public String getField(String field) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(field);
+                    mRemote.transact(Stub.TRANSACTION_getField, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
             public StorageVolume[] getVolumeList() throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
@@ -846,7 +907,15 @@
 
         static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
 
-        static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 36;
+        static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 35;
+
+        static final int TRANSACTION_getPassword = IBinder.FIRST_CALL_TRANSACTION + 36;
+
+        static final int TRANSACTION_clearPassword = IBinder.FIRST_CALL_TRANSACTION + 37;
+
+        static final int TRANSACTION_setField = IBinder.FIRST_CALL_TRANSACTION + 38;
+
+        static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39;
 
         /**
          * Cast an IBinder object into an IMountService interface, generating a
@@ -1208,6 +1277,35 @@
                     reply.writeInt(result);
                     return true;
                 }
+                case TRANSACTION_getPassword: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String result = getPassword();
+                    reply.writeNoException();
+                    reply.writeString(result);
+                    return true;
+                }
+                case TRANSACTION_clearPassword: {
+                    data.enforceInterface(DESCRIPTOR);
+                    clearPassword();
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_setField: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String field = data.readString();
+                    String contents = data.readString();
+                    setField(field, contents);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_getField: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String field = data.readString();
+                    String contents = getField(field);
+                    reply.writeNoException();
+                    reply.writeString(contents);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1446,4 +1544,29 @@
      * @return PasswordType
      */
     public int getPasswordType() throws RemoteException;
+
+    /**
+     * Get password from vold
+     * @return password or empty string
+     */
+    public String getPassword() throws RemoteException;
+
+    /**
+     * Securely clear password from vold
+     */
+    public void clearPassword() throws RemoteException;
+
+    /**
+     * Set a field in the crypto header.
+     * @param field field to set
+     * @param contents contents to set in field
+     */
+    public void setField(String field, String contents) throws RemoteException;
+
+    /**
+     * Gets a field from the crypto header.
+     * @param field field to get
+     * @return contents of field
+     */
+    public String getField(String field) throws RemoteException;
 }
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index 23d0a19..c2e1f51 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -45,8 +45,11 @@
  * adapter, use {@link PreferenceCategoryAdapter} instead.
  * 
  * @see PreferenceCategoryAdapter
+ *
+ * @hide
  */
-class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeInternalListener {
+public class PreferenceGroupAdapter extends BaseAdapter
+        implements OnPreferenceChangeInternalListener {
     
     private static final String TAG = "PreferenceGroupAdapter";
 
@@ -88,6 +91,8 @@
         }
     };
 
+    private int mActivatedPosition = -1;
+
     private static class PreferenceLayout implements Comparable<PreferenceLayout> {
         private int resId;
         private int widgetResId;
@@ -207,6 +212,10 @@
         return this.getItem(position).getId();
     }
 
+    public void setActivated(int position) {
+        mActivatedPosition = position;
+    }
+
     public View getView(int position, View convertView, ViewGroup parent) {
         final Preference preference = this.getItem(position);
         // Build a PreferenceLayout to compare with known ones that are cacheable.
@@ -217,8 +226,9 @@
         if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0) {
             convertView = null;
         }
-
-        return preference.getView(convertView, parent);
+        View result = preference.getView(convertView, parent);
+        result.setActivated(position == mActivatedPosition);
+        return result;
     }
 
     @Override
diff --git a/core/java/android/provider/SearchIndexableData.java b/core/java/android/provider/SearchIndexableData.java
index 719dcea..05285a3 100644
--- a/core/java/android/provider/SearchIndexableData.java
+++ b/core/java/android/provider/SearchIndexableData.java
@@ -52,6 +52,12 @@
     public int rank;
 
     /**
+     * The key for the data. This is application specific. Should be unique per data as the data
+     * should be able to be retrieved by the key.
+     */
+    public String key;
+
+    /**
      * The class name associated with the data. Generally this is a Fragment class name for
      * referring where the data is coming from and for launching the associated Fragment for
      * displaying the data. This is used only when the data is provided "locally".
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index b8635b8..05f3a1c 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -73,7 +73,8 @@
     public static final String[] INDEXABLES_RAW_COLUMNS = new String[] {
             RawData.COLUMN_RANK,
             RawData.COLUMN_TITLE,
-            RawData.COLUMN_SUMMARY,
+            RawData.COLUMN_SUMMARY_ON,
+            RawData.COLUMN_SUMMARY_OFF,
             RawData.COLUMN_KEYWORDS,
             RawData.COLUMN_SCREEN_TITLE,
             RawData.COLUMN_CLASS_NAME,
@@ -123,9 +124,14 @@
         public static final String COLUMN_TITLE = "title";
 
         /**
-         * Summary's raw data.
+         * Summary's raw data when the data is "ON".
          */
-        public static final String COLUMN_SUMMARY = "summary";
+        public static final String COLUMN_SUMMARY_ON = "summaryOn";
+
+        /**
+         * Summary's raw data when the data is "OFF".
+         */
+        public static final String COLUMN_SUMMARY_OFF = "summaryOff";
 
         /**
          * Keywords' raw data.
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 7647c22..de9eeff 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -153,11 +153,11 @@
     private final Handler mHandler = new Handler();
     private IBinder mWindowToken;
     private Window mWindow;
-    private WindowManager mWindowManager;
-    private boolean mInteractive = false;
+    private boolean mInteractive;
     private boolean mLowProfile = true;
-    private boolean mFullscreen = false;
+    private boolean mFullscreen;
     private boolean mScreenBright = true;
+    private boolean mStarted;
     private boolean mFinished;
     private boolean mCanDoze;
     private boolean mDozing;
@@ -340,7 +340,7 @@
      * @return The current window manager, or null if the dream is not started.
      */
     public WindowManager getWindowManager() {
-        return mWindowManager;
+        return mWindow != null ? mWindow.getWindowManager() : null;
     }
 
     /**
@@ -623,7 +623,7 @@
      * @hide experimental
      */
     public DozeHardware getDozeHardware() {
-        if (mCanDoze && mDozeHardware == null) {
+        if (mCanDoze && mDozeHardware == null && mWindowToken != null) {
             try {
                 IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken);
                 if (hardware != null) {
@@ -701,24 +701,25 @@
      * Must run on mHandler.
      */
     private final void detach() {
-        if (mWindow == null) {
-            // already detached!
-            return;
+        if (mStarted) {
+            if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
+            mStarted = false;
+            onDreamingStopped();
         }
 
-        if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
-        onDreamingStopped();
+        if (mWindow != null) {
+            // force our window to be removed synchronously
+            if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
+            mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView());
+            mWindow = null;
+        }
 
-        if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
-
-        // force our window to be removed synchronously
-        mWindowManager.removeViewImmediate(mWindow.getDecorView());
-        // the following will print a log message if it finds any other leaked windows
-        WindowManagerGlobal.getInstance().closeAll(mWindowToken,
-                this.getClass().getName(), "Dream");
-
-        mWindow = null;
-        mWindowToken = null;
+        if (mWindowToken != null) {
+            // the following will print a log message if it finds any other leaked windows
+            WindowManagerGlobal.getInstance().closeAll(mWindowToken,
+                    this.getClass().getName(), "Dream");
+            mWindowToken = null;
+        }
     }
 
     /**
@@ -746,12 +747,13 @@
         if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
 
         mWindowToken = windowToken;
+        mCanDoze = canDoze;
+
         mWindow = PolicyManager.makeNewWindow(this);
         mWindow.setCallback(this);
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
         mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
         mWindow.setFormat(PixelFormat.OPAQUE);
-        mCanDoze = canDoze;
 
         if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
                 windowToken, WindowManager.LayoutParams.TYPE_DREAM));
@@ -769,26 +771,28 @@
                     | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
                     );
         mWindow.setAttributes(lp);
-
-        if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow);
-
         mWindow.setWindowManager(null, windowToken, "dream", true);
-        mWindowManager = mWindow.getWindowManager();
 
-        if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
         applySystemUiVisibilityFlags(
                 (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
                 View.SYSTEM_UI_FLAG_LOW_PROFILE);
-        getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+
+        try {
+            getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+        } catch (WindowManager.BadTokenException ex) {
+            // This can happen because the dream manager service will remove the token
+            // immediately without necessarily waiting for the dream to start.
+            // We should receive a finish message soon.
+            Slog.i(TAG, "attach() called after window token already removed, dream will "
+                    + "finish soon");
+            mWindow = null;
+            return;
+        }
 
         // start it up
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
-                onDreamingStarted();
-            }
-        });
+        if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
+        mStarted = true;
+        onDreamingStarted();
     }
 
     private void safelyFinish() {
@@ -831,7 +835,7 @@
             WindowManager.LayoutParams lp = mWindow.getAttributes();
             lp.flags = applyFlags(lp.flags, flags, mask);
             mWindow.setAttributes(lp);
-            mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
+            mWindow.getWindowManager().updateViewLayout(mWindow.getDecorView(), lp);
         }
     }
 
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 425fdc1..d4b29d8 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -21,6 +21,7 @@
 /** @hide */
 oneway interface INotificationListener
 {
+    void onListenerConnected(in String[] notificationKeys);
     void onNotificationPosted(in StatusBarNotification notification);
     void onNotificationRemoved(in StatusBarNotification notification);
 }
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index cf862b8..3673f03 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 
 /**
@@ -83,6 +84,17 @@
      */
     public abstract void onNotificationRemoved(StatusBarNotification sbn);
 
+    /**
+     * Implement this method to learn about when the listener is enabled and connected to
+     * the notification manager.  You are safe to call {@link #getActiveNotifications(String[])
+     * at this time.
+     *
+     * @param notificationKeys The notification keys for all currently posted notifications.
+     */
+    public void onListenerConnected(String[] notificationKeys) {
+        // optional
+    }
+
     private final INotificationManager getNotificationInterface() {
         if (mNoMan == null) {
             mNoMan = INotificationManager.Stub.asInterface(
@@ -110,11 +122,43 @@
      *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
      * @param id  ID of the notification as specified by the notifying app in
      *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
+     * <p>
+     * @deprecated Use {@link #cancelNotification(String key)}
+     * instead. Beginning with {@link android.os.Build.VERSION_CODES#L} this method will no longer
+     * cancel the notification. It will continue to cancel the notification for applications
+     * whose {@code targetSdkVersion} is earlier than {@link android.os.Build.VERSION_CODES#L}.
      */
     public final void cancelNotification(String pkg, String tag, int id) {
         if (!isBound()) return;
         try {
-            getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id);
+            getNotificationInterface().cancelNotificationFromListener(
+                    mWrapper, pkg, tag, id);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
+     * Inform the notification manager about dismissal of a single notification.
+     * <p>
+     * Use this if your listener has a user interface that allows the user to dismiss individual
+     * notifications, similar to the behavior of Android's status bar and notification panel.
+     * It should be called after the user dismisses a single notification using your UI;
+     * upon being informed, the notification manager will actually remove the notification
+     * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
+     * <P>
+     * <b>Note:</b> If your listener allows the user to fire a notification's
+     * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
+     * this method at that time <i>if</i> the Notification in question has the
+     * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
+     * <p>
+     * @param key Notification to dismiss from {@link StatusBarNotification#getKey()}.
+     */
+    public final void cancelNotification(String key) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().cancelNotificationsFromListener(mWrapper,
+                    new String[] {key});
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
         }
@@ -132,9 +176,23 @@
      * {@see #cancelNotification(String, String, int)}
      */
     public final void cancelAllNotifications() {
+        cancelNotifications(null /*all*/);
+    }
+
+    /**
+     * Inform the notification manager about dismissal of specific notifications.
+     * <p>
+     * Use this if your listener has a user interface that allows the user to dismiss
+     * multiple notifications at once.
+     *
+     * @param keys Notifications to dismiss, or {@code null} to dismiss all.
+     *
+     * {@see #cancelNotification(String, String, int)}
+     */
+    public final void cancelNotifications(String[] keys) {
         if (!isBound()) return;
         try {
-            getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
+            getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys);
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
         }
@@ -142,14 +200,43 @@
 
     /**
      * Request the list of outstanding notifications (that is, those that are visible to the
-     * current user). Useful when starting up and you don't know what's already been posted.
+     * current user). Useful when you don't know what's already been posted.
      *
      * @return An array of active notifications.
      */
     public StatusBarNotification[] getActiveNotifications() {
+        return getActiveNotifications(null /*all*/);
+    }
+
+    /**
+     * Request the list of outstanding notifications (that is, those that are visible to the
+     * current user). Useful when you don't know what's already been posted.
+     *
+     * @param keys A specific list of notification keys, or {@code null} for all.
+     * @return An array of active notifications.
+     */
+    public StatusBarNotification[] getActiveNotifications(String[] keys) {
         if (!isBound()) return null;
         try {
-            return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+            return getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+        return null;
+    }
+
+    /**
+     * Request the list of outstanding notification keys(that is, those that are visible to the
+     * current user).  You can use the notification keys for subsequent retrieval via
+     * {@link #getActiveNotifications(String[]) or dismissal via
+     * {@link #cancelNotifications(String[]).
+     *
+     * @return An array of active notification keys.
+     */
+    public String[] getActiveNotificationKeys() {
+        if (!isBound()) return null;
+        try {
+            return getNotificationInterface().getActiveNotificationKeysFromListener(mWrapper);
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
         }
@@ -189,5 +276,13 @@
                 Log.w(TAG, "Error running onNotificationRemoved", t);
             }
         }
+        @Override
+        public void onListenerConnected(String[] notificationKeys) {
+            try {
+                NotificationListenerService.this.onListenerConnected(notificationKeys);
+            } catch (Throwable t) {
+                Log.w(TAG, "Error running onListenerConnected", t);
+            }
+        }
     }
 }
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index b5b9e14..0f74169 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -29,6 +29,7 @@
     private final String pkg;
     private final int id;
     private final String tag;
+    private final String key;
 
     private final int uid;
     private final String basePkg;
@@ -68,8 +69,8 @@
         this.notification = notification;
         this.user = user;
         this.notification.setUser(user);
-
         this.postTime = postTime;
+        this.key = key();
     }
 
     public StatusBarNotification(Parcel in) {
@@ -88,6 +89,11 @@
         this.user = UserHandle.readFromParcel(in);
         this.notification.setUser(this.user);
         this.postTime = in.readLong();
+        this.key = key();
+    }
+
+    private String key() {
+        return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -148,9 +154,9 @@
     @Override
     public String toString() {
         return String.format(
-                "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+                "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
                 this.pkg, this.user, this.id, this.tag,
-                this.score, this.notification);
+                this.score, this.key, this.notification);
     }
 
     /** Convenience method to check the notification's flags for
@@ -169,7 +175,11 @@
                 && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
     }
 
-    /** Returns a userHandle for the instance of the app that posted this notification. */
+    /**
+     * Returns a userHandle for the instance of the app that posted this notification.
+     *
+     * @deprecated Use {@link #getUser()} instead.
+     */
     public int getUserId() {
         return this.user.getIdentifier();
     }
@@ -213,7 +223,6 @@
 
     /**
      * The {@link android.os.UserHandle} for whom this notification is intended.
-     * @hide
      */
     public UserHandle getUser() {
         return user;
@@ -230,4 +239,11 @@
     public int getScore() {
         return score;
     }
+
+    /**
+     * A unique instance key for this notification record.
+     */
+    public String getKey() {
+        return key;
+    }
 }
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/service/trust/ITrustAgentService.aidl
similarity index 64%
copy from core/java/android/view/DisplayList.java
copy to core/java/android/service/trust/ITrustAgentService.aidl
index ed52803..863a249 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -13,13 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.service.trust;
 
-package android.view;
+import android.os.Bundle;
+import android.service.trust.ITrustAgentServiceCallback;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
+/**
+ * Communication channel from TrustManagerService to the TrustAgent.
+ * @hide
  */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
+oneway interface ITrustAgentService {
+    void onUnlockAttempt(boolean successful);
+    void setCallback(ITrustAgentServiceCallback callback);
 }
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
similarity index 64%
copy from core/java/android/view/DisplayList.java
copy to core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index ed52803..c346771 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -13,13 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.service.trust;
 
-package android.view;
+import android.os.Bundle;
+import android.os.UserHandle;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
+/**
+ * Communication channel from the TrustAgentService back to TrustManagerService.
+ * @hide
  */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
+oneway interface ITrustAgentServiceCallback {
+    void enableTrust(String message, long durationMs, boolean initiatedByUser);
+    void revokeTrust();
 }
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
new file mode 100644
index 0000000..d5ce429
--- /dev/null
+++ b/core/java/android/service/trust/TrustAgentService.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.service.trust;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * A service that notifies the system about whether it believes the environment of the device
+ * to be trusted.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_TRUST_AGENT_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * &lt;service android:name=".TrustAgent"
+ *          android:label="&#64;string/service_name"
+ *          android:permission="android.permission.BIND_TRUST_AGENT_SERVICE">
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.service.trust.TrustAgentService" />
+ *     &lt;/intent-filter>
+ *     &lt;meta-data android:name="android.service.trust.trustagent"
+ *          android:value="&#64;xml/trust_agent" />
+ * &lt;/service></pre>
+ *
+ * <p>The associated meta-data file can specify an activity that is accessible through Settings
+ * and should allow configuring the trust agent, as defined in
+ * {@link android.R.styleable#TrustAgent}. For example:</p>
+ *
+ * <pre>
+ * &lt;trust_agent xmlns:android="http://schemas.android.com/apk/res/android"
+ *          android:settingsActivity=".TrustAgentSettings" /></pre>
+ */
+public class TrustAgentService extends Service {
+    private final String TAG = TrustAgentService.class.getSimpleName() +
+            "[" + getClass().getSimpleName() + "]";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.trust.TrustAgentService";
+
+    /**
+     * The name of the {@code meta-data} tag pointing to additional configuration of the trust
+     * agent.
+     */
+    public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+
+    private static final int MSG_UNLOCK_ATTEMPT = 1;
+
+    private static final boolean DEBUG = false;
+
+    private ITrustAgentServiceCallback mCallback;
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(android.os.Message msg) {
+            switch (msg.what) {
+                case MSG_UNLOCK_ATTEMPT:
+                    onUnlockAttempt(msg.arg1 != 0);
+                    break;
+            }
+        };
+    };
+
+    /**
+     * Called when the user attempted to authenticate on the device.
+     *
+     * @param successful true if the attempt succeeded
+     */
+    protected void onUnlockAttempt(boolean successful) {
+    }
+
+    private void onError(String msg) {
+        Slog.v(TAG, "Remote exception while " + msg);
+    }
+
+    /**
+     * Call to enable trust on the device.
+     *
+     * @param message describes why the device is trusted, e.g. "Trusted by location".
+     * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust
+     *                   for this agent will automatically be revoked when the timeout expires.
+     * @param initiatedByUser indicates that the user has explicitly initiated an action that proves
+     *                        the user is about to use the device.
+     */
+    protected final void enableTrust(String message, long durationMs, boolean initiatedByUser) {
+        if (mCallback != null) {
+            try {
+                mCallback.enableTrust(message, durationMs, initiatedByUser);
+            } catch (RemoteException e) {
+                onError("calling enableTrust()");
+            }
+        }
+    }
+
+    /**
+     * Call to revoke trust on the device.
+     */
+    protected final void revokeTrust() {
+        if (mCallback != null) {
+            try {
+                mCallback.revokeTrust();
+            } catch (RemoteException e) {
+                onError("calling revokeTrust()");
+            }
+        }
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+        return new TrustAgentServiceWrapper();
+    }
+
+    private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
+        @Override
+        public void onUnlockAttempt(boolean successful) {
+            mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0)
+                    .sendToTarget();
+        }
+
+        public void setCallback(ITrustAgentServiceCallback callback) {
+            mCallback = callback;
+        }
+    }
+
+}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 535eee1..638ef22 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -433,7 +433,7 @@
                         }
 
                         if (mLineCount >= mMaximumVisibleLineCount) {
-                            break;
+                            return;
                         }
                     }
                 }
diff --git a/core/java/android/transition/CircularPropagation.java b/core/java/android/transition/CircularPropagation.java
new file mode 100644
index 0000000..18a3d22
--- /dev/null
+++ b/core/java/android/transition/CircularPropagation.java
@@ -0,0 +1,103 @@
+/*
+ * 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.transition;
+
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A propagation that varies with the distance to the epicenter of the Transition
+ * or center of the scene if no epicenter exists. When a View is visible in the
+ * start of the transition, Views farther from the epicenter will transition
+ * sooner than Views closer to the epicenter. When a View is not in the start
+ * of the transition or is not visible at the start of the transition, it will
+ * transition sooner when closer to the epicenter and later when farther from
+ * the epicenter. This is the default TransitionPropagation used with
+ * {@link android.transition.Explode}.
+ */
+public class CircularPropagation extends VisibilityPropagation {
+    private static final String TAG = "CircularPropagation";
+
+    private float mPropagationSpeed = 4.0f;
+
+    /**
+     * Sets the speed at which transition propagation happens, relative to the duration of the
+     * Transition. A <code>propagationSpeed</code> of 1 means that a View centered farthest from
+     * the epicenter and View centered at the epicenter will have a difference
+     * in start delay of approximately the duration of the Transition. A speed of 2 means the
+     * start delay difference will be approximately half of the duration of the transition. A
+     * value of 0 is illegal, but negative values will invert the propagation.
+     *
+     * @param propagationSpeed The speed at which propagation occurs, relative to the duration
+     *                         of the transition. A speed of 4 means it works 4 times as fast
+     *                         as the duration of the transition. May not be 0.
+     */
+    public void setPropagationSpeed(float propagationSpeed) {
+        if (propagationSpeed == 0) {
+            throw new IllegalArgumentException("propagationSpeed may not be 0");
+        }
+        mPropagationSpeed = propagationSpeed;
+    }
+
+    @Override
+    public long getStartDelay(ViewGroup sceneRoot, Transition transition,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (startValues == null && endValues == null) {
+            return 0;
+        }
+        int directionMultiplier = 1;
+        TransitionValues positionValues;
+        if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) {
+            positionValues = startValues;
+            directionMultiplier = -1;
+        } else {
+            positionValues = endValues;
+        }
+
+        int viewCenterX = getViewX(positionValues);
+        int viewCenterY = getViewY(positionValues);
+
+        Rect epicenter = transition.getEpicenter();
+        int epicenterX;
+        int epicenterY;
+        if (epicenter != null) {
+            epicenterX = epicenter.centerX();
+            epicenterY = epicenter.centerY();
+        } else {
+            int[] loc = new int[2];
+            sceneRoot.getLocationOnScreen(loc);
+            epicenterX = Math.round(loc[0] + (sceneRoot.getWidth() / 2)
+                    + sceneRoot.getTranslationX());
+            epicenterY = Math.round(loc[1] + (sceneRoot.getHeight() / 2)
+                    + sceneRoot.getTranslationY());
+        }
+        float distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY);
+        float maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
+        float distanceFraction = distance/maxDistance;
+
+        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
+                * distanceFraction);
+    }
+
+    private static float distance(float x1, float y1, float x2, float y2) {
+        float x = x2 - x1;
+        float y = y2 - y1;
+        return FloatMath.sqrt((x * x) + (y * y));
+    }
+}
diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java
new file mode 100644
index 0000000..fae527c
--- /dev/null
+++ b/core/java/android/transition/Explode.java
@@ -0,0 +1,228 @@
+/*
+ * 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * This transition tracks changes to the visibility of target views in the
+ * start and end scenes and moves views in or out from the edges of the
+ * scene. Visibility is determined by both the
+ * {@link View#setVisibility(int)} state of the view as well as whether it
+ * is parented in the current view hierarchy. Disappearing Views are
+ * limited as described in {@link Visibility#onDisappear(android.view.ViewGroup,
+ * TransitionValues, int, TransitionValues, int)}.
+ * <p>Views move away from the focal View or the center of the Scene if
+ * no epicenter was provided.</p>
+ */
+public class Explode extends Visibility {
+    private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
+    private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
+    private static final String TAG = "Explode";
+
+    private static final String PROPNAME_SCREEN_BOUNDS = "android:out:screenBounds";
+
+    private int[] mTempLoc = new int[2];
+
+    public Explode() {
+        setPropagation(new CircularPropagation());
+    }
+
+    private void captureValues(TransitionValues transitionValues) {
+        View view = transitionValues.view;
+        view.getLocationOnScreen(mTempLoc);
+        int left = mTempLoc[0] + Math.round(view.getTranslationX());
+        int top = mTempLoc[1] + Math.round(view.getTranslationY());
+        int right = left + view.getWidth();
+        int bottom = top + view.getHeight();
+        transitionValues.values.put(PROPNAME_SCREEN_BOUNDS, new Rect(left, top, right, bottom));
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        super.captureStartValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        super.captureEndValues(transitionValues);
+        captureValues(transitionValues);
+    }
+
+    private Animator createAnimation(final View view, float startX, float startY, float endX,
+            float endY, float terminalX, float terminalY, TimeInterpolator interpolator) {
+        view.setTranslationX(startX);
+        view.setTranslationY(startY);
+        if (startY == endY && startX == endX) {
+            return null;
+        }
+        Path path = new Path();
+        path.moveTo(startX, startY);
+        path.lineTo(endX, endY);
+        ObjectAnimator pathAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
+                View.TRANSLATION_Y, path);
+        pathAnimator.setInterpolator(interpolator);
+        OutAnimatorListener listener = new OutAnimatorListener(view, terminalX, terminalY,
+                endX, endY);
+        pathAnimator.addListener(listener);
+        pathAnimator.addPauseListener(listener);
+
+        return pathAnimator;
+    }
+
+    @Override
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (endValues == null) {
+            return null;
+        }
+        Rect bounds = (Rect) endValues.values.get(PROPNAME_SCREEN_BOUNDS);
+        calculateOut(sceneRoot, bounds, mTempLoc);
+
+        final float endX = view.getTranslationX();
+        final float startX = endX + mTempLoc[0];
+        final float endY = view.getTranslationY();
+        final float startY = endY + mTempLoc[1];
+
+        return createAnimation(view, startX, startY, endX, endY, endX, endY, sDecelerate);
+    }
+
+    @Override
+    public Animator onDisappear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        Rect bounds = (Rect) startValues.values.get(PROPNAME_SCREEN_BOUNDS);
+        calculateOut(sceneRoot, bounds, mTempLoc);
+
+        final float startX = view.getTranslationX();
+        final float endX = startX + mTempLoc[0];
+        final float startY = view.getTranslationY();
+        final float endY = startY + mTempLoc[1];
+
+        return createAnimation(view, startX, startY, endX, endY, startX, startY,
+                sAccelerate);
+    }
+
+    private void calculateOut(View sceneRoot, Rect bounds, int[] outVector) {
+        sceneRoot.getLocationOnScreen(mTempLoc);
+        int sceneRootX = mTempLoc[0];
+        int sceneRootY = mTempLoc[1];
+        int focalX;
+        int focalY;
+
+        Rect epicenter = getEpicenter();
+        if (epicenter == null) {
+            focalX = sceneRootX + (sceneRoot.getWidth() / 2)
+                    + Math.round(sceneRoot.getTranslationX());
+            focalY = sceneRootY + (sceneRoot.getHeight() / 2)
+                    + Math.round(sceneRoot.getTranslationY());
+        } else {
+            focalX = epicenter.centerX();
+            focalY = epicenter.centerY();
+        }
+
+        int centerX = bounds.centerX();
+        int centerY = bounds.centerY();
+        float xVector = centerX - focalX;
+        float yVector = centerY - focalY;
+
+        if (xVector == 0 && yVector == 0) {
+            // Random direction when View is centered on focal View.
+            xVector = (float)(Math.random() * 2) - 1;
+            yVector = (float)(Math.random() * 2) - 1;
+        }
+        float vectorSize = calculateDistance(xVector, yVector);
+        xVector /= vectorSize;
+        yVector /= vectorSize;
+
+        float maxDistance =
+                calculateMaxDistance(sceneRoot, focalX - sceneRootX, focalY - sceneRootY);
+
+        outVector[0] = Math.round(maxDistance * xVector);
+        outVector[1] = Math.round(maxDistance * yVector);
+    }
+
+    private static float calculateMaxDistance(View sceneRoot, int focalX, int focalY) {
+        int maxX = Math.max(focalX, sceneRoot.getWidth() - focalX);
+        int maxY = Math.max(focalY, sceneRoot.getHeight() - focalY);
+        return calculateDistance(maxX, maxY);
+    }
+
+    private static float calculateDistance(float x, float y) {
+        return FloatMath.sqrt((x * x) + (y * y));
+    }
+
+    private static class OutAnimatorListener extends AnimatorListenerAdapter {
+        private final View mView;
+        private boolean mCanceled = false;
+        private float mPausedX;
+        private float mPausedY;
+        private final float mTerminalX;
+        private final float mTerminalY;
+        private final float mEndX;
+        private final float mEndY;
+
+        public OutAnimatorListener(View view, float terminalX, float terminalY,
+                float endX, float endY) {
+            mView = view;
+            mTerminalX = terminalX;
+            mTerminalY = terminalY;
+            mEndX = endX;
+            mEndY = endY;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animator) {
+            mView.setTranslationX(mTerminalX);
+            mView.setTranslationY(mTerminalY);
+            mCanceled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animator) {
+            if (!mCanceled) {
+                mView.setTranslationX(mTerminalX);
+                mView.setTranslationY(mTerminalY);
+            }
+        }
+
+        @Override
+        public void onAnimationPause(Animator animator) {
+            mPausedX = mView.getTranslationX();
+            mPausedY = mView.getTranslationY();
+            mView.setTranslationY(mEndX);
+            mView.setTranslationY(mEndY);
+        }
+
+        @Override
+        public void onAnimationResume(Animator animator) {
+            mView.setTranslationX(mPausedX);
+            mView.setTranslationY(mPausedY);
+        }
+    }
+}
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 8edb1ff..08e27d3 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -59,8 +59,6 @@
     private static boolean DBG = Transition.DBG && false;
 
     private static final String LOG_TAG = "Fade";
-    private static final String PROPNAME_SCREEN_X = "android:fade:screenX";
-    private static final String PROPNAME_SCREEN_Y = "android:fade:screenY";
 
     /**
      * Fading mode used in {@link #Fade(int)} to make the transition
@@ -98,245 +96,81 @@
     /**
      * Utility method to handle creating and running the Animator.
      */
-    private Animator createAnimation(View view, float startAlpha, float endAlpha,
-            AnimatorListenerAdapter listener) {
+    private Animator createAnimation(View view, float startAlpha, float endAlpha) {
         if (startAlpha == endAlpha) {
-            // run listener if we're noop'ing the animation, to get the end-state results now
-            if (listener != null) {
-                listener.onAnimationEnd(null);
-            }
             return null;
         }
-        final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", startAlpha,
-                endAlpha);
+        view.setTransitionAlpha(startAlpha);
+        final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", endAlpha);
         if (DBG) {
             Log.d(LOG_TAG, "Created animator " + anim);
         }
-        if (listener != null) {
-            anim.addListener(listener);
-            anim.addPauseListener(listener);
-        }
+        FadeAnimatorListener listener = new FadeAnimatorListener(view, endAlpha);
+        anim.addListener(listener);
+        anim.addPauseListener(listener);
         return anim;
     }
 
-    private void captureValues(TransitionValues transitionValues) {
-        int[] loc = new int[2];
-        transitionValues.view.getLocationOnScreen(loc);
-        transitionValues.values.put(PROPNAME_SCREEN_X, loc[0]);
-        transitionValues.values.put(PROPNAME_SCREEN_Y, loc[1]);
-    }
-
     @Override
-    public void captureStartValues(TransitionValues transitionValues) {
-        super.captureStartValues(transitionValues);
-        captureValues(transitionValues);
-    }
-
-    @Override
-    public Animator onAppear(ViewGroup sceneRoot,
-            TransitionValues startValues, int startVisibility,
-            TransitionValues endValues, int endVisibility) {
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues,
+            TransitionValues endValues) {
         if ((mFadingMode & IN) != IN || endValues == null) {
             return null;
         }
-        final View endView = endValues.view;
         if (DBG) {
             View startView = (startValues != null) ? startValues.view : null;
             Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " +
-                    startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
+                    startView + ", " + view);
         }
-        endView.setTransitionAlpha(0);
-        TransitionListener transitionListener = new TransitionListenerAdapter() {
-            boolean mCanceled = false;
-            float mPausedAlpha;
-
-            @Override
-            public void onTransitionCancel(Transition transition) {
-                endView.setTransitionAlpha(1);
-                mCanceled = true;
-            }
-
-            @Override
-            public void onTransitionEnd(Transition transition) {
-                if (!mCanceled) {
-                    endView.setTransitionAlpha(1);
-                }
-            }
-
-            @Override
-            public void onTransitionPause(Transition transition) {
-                mPausedAlpha = endView.getTransitionAlpha();
-                endView.setTransitionAlpha(1);
-            }
-
-            @Override
-            public void onTransitionResume(Transition transition) {
-                endView.setTransitionAlpha(mPausedAlpha);
-            }
-        };
-        addListener(transitionListener);
-        return createAnimation(endView, 0, 1, null);
+        return createAnimation(view, 0, 1);
     }
 
     @Override
-    public Animator onDisappear(ViewGroup sceneRoot,
-            TransitionValues startValues, int startVisibility,
-            TransitionValues endValues, int endVisibility) {
+    public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues,
+            TransitionValues endValues) {
         if ((mFadingMode & OUT) != OUT) {
             return null;
         }
-        View view = null;
-        View startView = (startValues != null) ? startValues.view : null;
-        View endView = (endValues != null) ? endValues.view : null;
-        if (DBG) {
-            Log.d(LOG_TAG, "Fade.onDisappear: startView, startVis, endView, endVis = " +
-                        startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
-        }
-        View overlayView = null;
-        View viewToKeep = null;
-        if (endView == null || endView.getParent() == null) {
-            if (endView != null) {
-                // endView was removed from its parent - add it to the overlay
-                view = overlayView = endView;
-            } else if (startView != null) {
-                // endView does not exist. Use startView only under certain
-                // conditions, because placing a view in an overlay necessitates
-                // it being removed from its current parent
-                if (startView.getParent() == null) {
-                    // no parent - safe to use
-                    view = overlayView = startView;
-                } else if (startView.getParent() instanceof View &&
-                        startView.getParent().getParent() == null) {
-                    View startParent = (View) startView.getParent();
-                    int id = startParent.getId();
-                    if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
-                        // no parent, but its parent is unparented  but the parent
-                        // hierarchy has been replaced by a new hierarchy with the same id
-                        // and it is safe to un-parent startView
-                        view = overlayView = startView;
-                    }
-                }
-            }
-        } else {
-            // visibility change
-            if (endVisibility == View.INVISIBLE) {
-                view = endView;
-                viewToKeep = view;
-            } else {
-                // Becoming GONE
-                if (startView == endView) {
-                    view = endView;
-                    viewToKeep = view;
-                } else {
-                    view = startView;
-                    overlayView = view;
-                }
-            }
-        }
-        final int finalVisibility = endVisibility;
-        // TODO: add automatic facility to Visibility superclass for keeping views around
-        if (overlayView != null) {
-            // TODO: Need to do this for general case of adding to overlay
-            int screenX = (Integer) startValues.values.get(PROPNAME_SCREEN_X);
-            int screenY = (Integer) startValues.values.get(PROPNAME_SCREEN_Y);
-            int[] loc = new int[2];
-            sceneRoot.getLocationOnScreen(loc);
-            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
-            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
-            sceneRoot.getOverlay().add(overlayView);
-            // TODO: add automatic facility to Visibility superclass for keeping views around
-            final float startAlpha = 1;
-            float endAlpha = 0;
-            final View finalView = view;
-            final View finalOverlayView = overlayView;
-            final View finalViewToKeep = viewToKeep;
-            final ViewGroup finalSceneRoot = sceneRoot;
-            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    finalView.setTransitionAlpha(startAlpha);
-                    // TODO: restore view offset from overlay repositioning
-                    if (finalViewToKeep != null) {
-                        finalViewToKeep.setVisibility(finalVisibility);
-                    }
-                    if (finalOverlayView != null) {
-                        finalSceneRoot.getOverlay().remove(finalOverlayView);
-                    }
-                }
 
-                @Override
-                public void onAnimationPause(Animator animation) {
-                    if (finalOverlayView != null) {
-                        finalSceneRoot.getOverlay().remove(finalOverlayView);
-                    }
-                }
-
-                @Override
-                public void onAnimationResume(Animator animation) {
-                    if (finalOverlayView != null) {
-                        finalSceneRoot.getOverlay().add(finalOverlayView);
-                    }
-                }
-            };
-            return createAnimation(view, startAlpha, endAlpha, endListener);
-        }
-        if (viewToKeep != null) {
-            // TODO: find a different way to do this, like just changing the view to be
-            // VISIBLE for the duration of the transition
-            viewToKeep.setVisibility((View.VISIBLE));
-            // TODO: add automatic facility to Visibility superclass for keeping views around
-            final float startAlpha = 1;
-            float endAlpha = 0;
-            final View finalView = view;
-            final View finalOverlayView = overlayView;
-            final View finalViewToKeep = viewToKeep;
-            final ViewGroup finalSceneRoot = sceneRoot;
-            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
-                boolean mCanceled = false;
-                float mPausedAlpha = -1;
-
-                @Override
-                public void onAnimationPause(Animator animation) {
-                    if (finalViewToKeep != null && !mCanceled) {
-                        finalViewToKeep.setVisibility(finalVisibility);
-                    }
-                    mPausedAlpha = finalView.getTransitionAlpha();
-                    finalView.setTransitionAlpha(startAlpha);
-                }
-
-                @Override
-                public void onAnimationResume(Animator animation) {
-                    if (finalViewToKeep != null && !mCanceled) {
-                        finalViewToKeep.setVisibility(View.VISIBLE);
-                    }
-                    finalView.setTransitionAlpha(mPausedAlpha);
-                }
-
-                @Override
-                public void onAnimationCancel(Animator animation) {
-                    mCanceled = true;
-                    if (mPausedAlpha >= 0) {
-                        finalView.setTransitionAlpha(mPausedAlpha);
-                    }
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (!mCanceled) {
-                        finalView.setTransitionAlpha(startAlpha);
-                    }
-                    // TODO: restore view offset from overlay repositioning
-                    if (finalViewToKeep != null && !mCanceled) {
-                        finalViewToKeep.setVisibility(finalVisibility);
-                    }
-                    if (finalOverlayView != null) {
-                        finalSceneRoot.getOverlay().remove(finalOverlayView);
-                    }
-                }
-            };
-            return createAnimation(view, startAlpha, endAlpha, endListener);
-        }
-        return null;
+        return createAnimation(view, 1, 0);
     }
 
-}
\ No newline at end of file
+    private static class FadeAnimatorListener extends AnimatorListenerAdapter {
+        private final View mView;
+        private final float mEndAlpha;
+        private boolean mCanceled = false;
+        private float mPausedAlpha;
+
+        public FadeAnimatorListener(View view, float endAlpha) {
+            mView = view;
+            mEndAlpha = endAlpha;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animator) {
+            mCanceled = true;
+            if (mPausedAlpha >= 0) {
+                mView.setTransitionAlpha(mPausedAlpha);
+            }
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animator) {
+            if (!mCanceled) {
+                mView.setTransitionAlpha(mEndAlpha);
+            }
+        }
+
+        @Override
+        public void onAnimationPause(Animator animator) {
+            mPausedAlpha = mView.getTransitionAlpha();
+            mView.setTransitionAlpha(mEndAlpha);
+        }
+
+        @Override
+        public void onAnimationResume(Animator animator) {
+            mView.setTransitionAlpha(mPausedAlpha);
+        }
+    }
+}
diff --git a/core/java/android/transition/MatrixClippedDrawable.java b/core/java/android/transition/MatrixClippedDrawable.java
new file mode 100644
index 0000000..ebaad59
--- /dev/null
+++ b/core/java/android/transition/MatrixClippedDrawable.java
@@ -0,0 +1,300 @@
+/*
+ * 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.transition;
+
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Property;
+
+/**
+ * Used in MoveImage to mock an ImageView as a Drawable to be scaled in the scene root Overlay.
+ * @hide
+ */
+class MatrixClippedDrawable extends Drawable implements Drawable.Callback {
+    private static final String TAG = "MatrixClippedDrawable";
+
+    private ClippedMatrixState mClippedMatrixState;
+
+    public static final Property<MatrixClippedDrawable, Rect> CLIP_PROPERTY
+            = new Property<MatrixClippedDrawable, Rect>(Rect.class, "clipRect") {
+
+        @Override
+        public Rect get(MatrixClippedDrawable object) {
+            return object.getClipRect();
+        }
+
+        @Override
+        public void set(MatrixClippedDrawable object, Rect value) {
+            object.setClipRect(value);
+        }
+    };
+
+    public static final Property<MatrixClippedDrawable, Matrix> MATRIX_PROPERTY
+            = new Property<MatrixClippedDrawable, Matrix>(Matrix.class, "matrix") {
+        @Override
+        public void set(MatrixClippedDrawable object, Matrix value) {
+            object.setMatrix(value);
+        }
+
+        @Override
+        public Matrix get(MatrixClippedDrawable object) {
+            return object.getMatrix();
+        }
+    };
+
+    public MatrixClippedDrawable(Drawable drawable) {
+        this(null, null);
+
+        mClippedMatrixState.mDrawable = drawable;
+
+        if (drawable != null) {
+            drawable.setCallback(this);
+        }
+    }
+
+    public void setMatrix(Matrix matrix) {
+        if (matrix == null) {
+            mClippedMatrixState.mMatrix = null;
+        } else {
+            if (mClippedMatrixState.mMatrix == null) {
+                mClippedMatrixState.mMatrix = new Matrix();
+            }
+            mClippedMatrixState.mMatrix.set(matrix);
+        }
+        invalidateSelf();
+    }
+
+    public Matrix getMatrix() {
+        return mClippedMatrixState.mMatrix;
+    }
+
+    public Rect getClipRect() {
+        return mClippedMatrixState.mClipRect;
+    }
+
+    public void setClipRect(Rect clipRect) {
+        if (clipRect == null) {
+            if (mClippedMatrixState.mClipRect != null) {
+                mClippedMatrixState.mClipRect = null;
+                invalidateSelf();
+            }
+        } else {
+            if (mClippedMatrixState.mClipRect == null) {
+                mClippedMatrixState.mClipRect = new Rect(clipRect);
+            } else {
+                mClippedMatrixState.mClipRect.set(clipRect);
+            }
+            invalidateSelf();
+        }
+    }
+
+    // overrides from Drawable.Callback
+
+    public void invalidateDrawable(Drawable who) {
+        final Drawable.Callback callback = getCallback();
+        if (callback != null) {
+            callback.invalidateDrawable(this);
+        }
+    }
+
+    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+        final Drawable.Callback callback = getCallback();
+        if (callback != null) {
+            callback.scheduleDrawable(this, what, when);
+        }
+    }
+
+    public void unscheduleDrawable(Drawable who, Runnable what) {
+        final Drawable.Callback callback = getCallback();
+        if (callback != null) {
+            callback.unscheduleDrawable(this, what);
+        }
+    }
+
+    // overrides from Drawable
+
+    @Override
+    public int getChangingConfigurations() {
+        return super.getChangingConfigurations()
+                | mClippedMatrixState.mChangingConfigurations
+                | mClippedMatrixState.mDrawable.getChangingConfigurations();
+    }
+
+    @Override
+    public boolean getPadding(Rect padding) {
+        // XXX need to adjust padding!
+        return mClippedMatrixState.mDrawable.getPadding(padding);
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        mClippedMatrixState.mDrawable.setVisible(visible, restart);
+        return super.setVisible(visible, restart);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mClippedMatrixState.mDrawable.setAlpha(alpha);
+    }
+
+    @Override
+    public int getAlpha() {
+        return mClippedMatrixState.mDrawable.getAlpha();
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        mClippedMatrixState.mDrawable.setColorFilter(cf);
+    }
+
+    @Override
+    public int getOpacity() {
+        return mClippedMatrixState.mDrawable.getOpacity();
+    }
+
+    @Override
+    public boolean isStateful() {
+        return mClippedMatrixState.mDrawable.isStateful();
+    }
+
+    @Override
+    protected boolean onStateChange(int[] state) {
+        return mClippedMatrixState.mDrawable.setState(state);
+    }
+
+    @Override
+    protected boolean onLevelChange(int level) {
+        mClippedMatrixState.mDrawable.setLevel(level);
+        invalidateSelf();
+        return true;
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        super.setBounds(bounds);
+        if (mClippedMatrixState.mMatrix == null) {
+            mClippedMatrixState.mDrawable.setBounds(bounds);
+        } else {
+            int drawableWidth = mClippedMatrixState.mDrawable.getIntrinsicWidth();
+            int drawableHeight = mClippedMatrixState.mDrawable.getIntrinsicHeight();
+            mClippedMatrixState.mDrawable.setBounds(bounds.left, bounds.top,
+                    drawableWidth + bounds.left, drawableHeight + bounds.top);
+        }
+        invalidateSelf();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        Rect bounds = getBounds();
+        int left = bounds.left;
+        int top = bounds.top;
+        int saveCount = canvas.getSaveCount();
+        canvas.save();
+        if (mClippedMatrixState.mClipRect != null) {
+            canvas.clipRect(mClippedMatrixState.mClipRect);
+        } else {
+            canvas.clipRect(bounds);
+        }
+
+        if (mClippedMatrixState != null && !mClippedMatrixState.mMatrix.isIdentity()) {
+            canvas.translate(left, top);
+            canvas.concat(mClippedMatrixState.mMatrix);
+            canvas.translate(-left, -top);
+        }
+        mClippedMatrixState.mDrawable.draw(canvas);
+        canvas.restoreToCount(saveCount);
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mClippedMatrixState.mDrawable.getIntrinsicWidth();
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mClippedMatrixState.mDrawable.getIntrinsicHeight();
+    }
+
+    @Override
+    public Drawable.ConstantState getConstantState() {
+        if (mClippedMatrixState.canConstantState()) {
+            mClippedMatrixState.mChangingConfigurations = getChangingConfigurations();
+            return mClippedMatrixState;
+        }
+        return null;
+    }
+
+    final static class ClippedMatrixState extends Drawable.ConstantState {
+        Drawable mDrawable;
+        Matrix mMatrix;
+        Rect mClipRect;
+
+        private boolean mCheckedConstantState;
+        private boolean mCanConstantState;
+        int mChangingConfigurations;
+
+        ClippedMatrixState(ClippedMatrixState orig, MatrixClippedDrawable owner, Resources res) {
+            if (orig != null) {
+                if (res != null) {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                }
+                mDrawable.setCallback(owner);
+                mCheckedConstantState = mCanConstantState = true;
+                if (orig.mMatrix != null) {
+                    mMatrix = new Matrix(orig.mMatrix);
+                }
+                if (orig.mClipRect != null) {
+                    mClipRect = new Rect(orig.mClipRect);
+                }
+            }
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return new MatrixClippedDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new MatrixClippedDrawable(this, res);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConfigurations;
+        }
+
+        boolean canConstantState() {
+            if (!mCheckedConstantState) {
+                mCanConstantState = mDrawable.getConstantState() != null;
+                mCheckedConstantState = true;
+            }
+
+            return mCanConstantState;
+        }
+    }
+
+    private MatrixClippedDrawable(ClippedMatrixState state, Resources res) {
+        mClippedMatrixState = new ClippedMatrixState(state, this, res);
+    }
+
+}
diff --git a/core/java/android/transition/MoveImage.java b/core/java/android/transition/MoveImage.java
new file mode 100644
index 0000000..d68e971
--- /dev/null
+++ b/core/java/android/transition/MoveImage.java
@@ -0,0 +1,326 @@
+/*
+ * 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.transition;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.RectEvaluator;
+import android.animation.TypeEvaluator;
+import android.animation.ValueAnimator;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
+import android.view.ViewParent;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * Transitions ImageViews, including size, scaleType, and matrix. The ImageView drawable
+ * must remain the same between both start and end states, but the
+ * {@link ImageView#setScaleType(android.widget.ImageView.ScaleType)} may
+ * differ.
+ */
+public class MoveImage extends Transition {
+    private static final String TAG = "MoveImage";
+    private static final String PROPNAME_MATRIX = "android:moveImage:matrix";
+    private static final String PROPNAME_BOUNDS = "android:moveImage:bounds";
+    private static final String PROPNAME_CLIP = "android:moveImage:clip";
+    private static final String PROPNAME_DRAWABLE = "android:moveImage:drawable";
+
+    private int[] mTempLoc = new int[2];
+
+    private static final String[] sTransitionProperties = {
+            PROPNAME_MATRIX,
+            PROPNAME_BOUNDS,
+            PROPNAME_CLIP,
+            PROPNAME_DRAWABLE,
+    };
+
+    private void captureValues(TransitionValues transitionValues) {
+        View view = transitionValues.view;
+        if (!(view instanceof ImageView) || view.getVisibility() != View.VISIBLE) {
+            return;
+        }
+        Map<String, Object> values = transitionValues.values;
+
+        ViewGroup parent = (ViewGroup) view.getParent();
+        parent.getLocationInWindow(mTempLoc);
+        int paddingLeft = view.getPaddingLeft();
+        int paddingTop = view.getPaddingTop();
+        int paddingRight = view.getPaddingRight();
+        int paddingBottom = view.getPaddingBottom();
+        int left = mTempLoc[0] + paddingLeft + view.getLeft() + Math.round(view.getTranslationX());
+        int top = mTempLoc[1] + paddingTop + view.getTop() + Math.round(view.getTranslationY());
+        int right = left + view.getWidth() - paddingRight - paddingLeft;
+        int bottom = top + view.getHeight() - paddingTop - paddingBottom;
+
+        Rect bounds = new Rect(left, top, right, bottom);
+        values.put(PROPNAME_BOUNDS, bounds);
+        ImageView imageView = (ImageView) view;
+        Matrix matrix = getMatrix(imageView);
+        values.put(PROPNAME_MATRIX, matrix);
+        values.put(PROPNAME_CLIP, findClip(imageView));
+        values.put(PROPNAME_DRAWABLE, imageView.getDrawable());
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public String[] getTransitionProperties() {
+        return sTransitionProperties;
+    }
+
+    /**
+     * Creates an Animator for ImageViews moving, changing dimensions, and/or changing
+     * {@link android.widget.ImageView.ScaleType}.
+     * @param sceneRoot The root of the transition hierarchy.
+     * @param startValues The values for a specific target in the start scene.
+     * @param endValues The values for the target in the end scene.
+     * @return An Animator to move an ImageView or null if the View is not an ImageView,
+     * the Drawable changed, the View is not VISIBLE, or there was no change.
+     */
+    @Override
+    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        if (startValues == null || endValues == null
+                || startValues.values.get(PROPNAME_BOUNDS) == null
+                || endValues.values.get(PROPNAME_BOUNDS) == null
+                || startValues.values.get(PROPNAME_DRAWABLE)
+                        != endValues.values.get(PROPNAME_DRAWABLE)) {
+            return null;
+        }
+        ArrayList<PropertyValuesHolder> changes = new ArrayList<PropertyValuesHolder>();
+
+        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
+        Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
+
+        if (!startMatrix.equals(endMatrix)) {
+            changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.MATRIX_PROPERTY,
+                    new MatrixEvaluator(), startMatrix, endMatrix));
+        }
+
+        sceneRoot.getLocationInWindow(mTempLoc);
+        int rootX = mTempLoc[0];
+        int rootY = mTempLoc[1];
+        final ImageView imageView = (ImageView) endValues.view;
+
+        Drawable drawable = imageView.getDrawable();
+
+        Rect startBounds = new Rect((Rect) startValues.values.get(PROPNAME_BOUNDS));
+        Rect endBounds = new Rect((Rect) endValues.values.get(PROPNAME_BOUNDS));
+        startBounds.offset(-rootX, -rootY);
+        endBounds.offset(-rootX, -rootY);
+
+        if (!startBounds.equals(endBounds)) {
+            changes.add(PropertyValuesHolder.ofObject("bounds", new RectEvaluator(new Rect()),
+                    startBounds, endBounds));
+        }
+
+        Rect startClip = (Rect) startValues.values.get(PROPNAME_CLIP);
+        Rect endClip = (Rect) endValues.values.get(PROPNAME_CLIP);
+        if (startClip != null || endClip != null) {
+            startClip = nonNullClip(startClip, sceneRoot, rootX, rootY);
+            endClip = nonNullClip(endClip, sceneRoot, rootX, rootY);
+
+            expandClip(startBounds, startMatrix, startClip, endClip);
+            expandClip(endBounds, endMatrix, endClip, startClip);
+            boolean clipped = !startClip.contains(startBounds) || !endClip.contains(endBounds);
+            if (!clipped) {
+                startClip = null;
+            } else if (!startClip.equals(endClip)) {
+                changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.CLIP_PROPERTY,
+                        new RectEvaluator(), startClip, endClip));
+            }
+        }
+
+        if (changes.isEmpty()) {
+            return null;
+        }
+
+        drawable = drawable.getConstantState().newDrawable();
+        final MatrixClippedDrawable matrixClippedDrawable = new MatrixClippedDrawable(drawable);
+        matrixClippedDrawable.setMatrix(startMatrix);
+        matrixClippedDrawable.setBounds(startBounds);
+        matrixClippedDrawable.setClipRect(startClip);
+
+        imageView.setVisibility(View.INVISIBLE);
+        final ViewGroupOverlay overlay = sceneRoot.getOverlay();
+        overlay.add(matrixClippedDrawable);
+        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(matrixClippedDrawable,
+                changes.toArray(new PropertyValuesHolder[changes.size()]));
+
+        AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                imageView.setVisibility(View.VISIBLE);
+                overlay.remove(matrixClippedDrawable);
+            }
+
+            @Override
+            public void onAnimationPause(Animator animation) {
+                imageView.setVisibility(View.VISIBLE);
+                overlay.remove(matrixClippedDrawable);
+            }
+
+            @Override
+            public void onAnimationResume(Animator animation) {
+                imageView.setVisibility(View.INVISIBLE);
+                overlay.add(matrixClippedDrawable);
+            }
+        };
+
+        animator.addListener(listener);
+        animator.addPauseListener(listener);
+
+        return animator;
+    }
+
+    private static Rect nonNullClip(Rect clip, ViewGroup sceneRoot, int rootX, int rootY) {
+        if (clip != null) {
+            clip = new Rect(clip);
+            clip.offset(-rootX, -rootY);
+        } else {
+            clip = new Rect(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
+        }
+        return clip;
+    }
+
+    private static void expandClip(Rect bounds, Matrix matrix, Rect clip, Rect otherClip) {
+        RectF boundsF = new RectF(bounds);
+        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);
+        clip.bottom = expandMaxDimension(boundsF.bottom, clip.bottom, otherClip.bottom);
+    }
+
+    private static int expandMinDimension(float boundsDimension, int clipDimension,
+            int otherClipDimension) {
+        if (clipDimension > boundsDimension) {
+            // Already clipped in that dimension, return the clipped value
+            return clipDimension;
+        }
+        return Math.min(clipDimension, otherClipDimension);
+    }
+
+    private static int expandMaxDimension(float boundsDimension, int clipDimension,
+            int otherClipDimension) {
+        return -expandMinDimension(-boundsDimension, -clipDimension, -otherClipDimension);
+    }
+
+    private static Matrix getMatrix(ImageView imageView) {
+        Drawable drawable = imageView.getDrawable();
+        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;
+        }
+        return new Matrix(imageView.getImageMatrix());
+    }
+
+    private Rect findClip(ImageView imageView) {
+        if (imageView.getCropToPadding()) {
+            Rect clip = getClip(imageView);
+            clip.left += imageView.getPaddingLeft();
+            clip.right -= imageView.getPaddingRight();
+            clip.top += imageView.getPaddingTop();
+            clip.bottom -= imageView.getPaddingBottom();
+            return clip;
+        } else {
+            View view = imageView;
+            ViewParent viewParent;
+            while ((viewParent = view.getParent()) instanceof ViewGroup) {
+                ViewGroup viewGroup = (ViewGroup) viewParent;
+                if (viewGroup.getClipChildren()) {
+                    Rect clip = getClip(view);
+                    return clip;
+                }
+                view = viewGroup;
+            }
+        }
+        return null;
+    }
+
+    private Rect getClip(View clipView) {
+        Rect clipBounds = clipView.getClipBounds();
+        if (clipBounds == null) {
+            clipBounds = new Rect(clipView.getLeft(), clipView.getTop(),
+                    clipView.getRight(), clipView.getBottom());
+        }
+
+        ViewParent parent = clipView.getParent();
+        if (parent instanceof ViewGroup) {
+            ViewGroup parentViewGroup = (ViewGroup) parent;
+            parentViewGroup.getLocationInWindow(mTempLoc);
+            clipBounds.offset(mTempLoc[0], mTempLoc[1]);
+        }
+
+        return clipBounds;
+    }
+
+    @Override
+    public Transition clone() {
+        MoveImage clone = (MoveImage) super.clone();
+        clone.mTempLoc = new int[2];
+        return clone;
+    }
+
+    private static class MatrixEvaluator implements TypeEvaluator<Matrix> {
+        static final Matrix sIdentity = new Matrix();
+        float[] mTempStartValues = new float[9];
+        float[] mTempEndValues = new float[9];
+        Matrix mTempMatrix = new Matrix();
+
+        @Override
+        public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
+            if (startValue == null && endValue == null) {
+                return null;
+            }
+            if (startValue == null) {
+                startValue = sIdentity;
+            } else if (endValue == null) {
+                endValue = sIdentity;
+            }
+            startValue.getValues(mTempStartValues);
+            endValue.getValues(mTempEndValues);
+            for (int i = 0; i < 9; i++) {
+                float diff = mTempEndValues[i] - mTempStartValues[i];
+                mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
+            }
+            mTempMatrix.setValues(mTempEndValues);
+            return mTempMatrix;
+        }
+    }
+}
diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java
new file mode 100644
index 0000000..c331945
--- /dev/null
+++ b/core/java/android/transition/SidePropagation.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 android.transition;
+
+import android.graphics.Rect;
+import android.util.FloatMath;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A <code>TransitionPropagation</code> that propagates based on the distance to the side
+ * and, orthogonally, the distance to epicenter. If the transitioning View is visible in
+ * the start of the transition, then it will transition sooner when closer to the side and
+ * later when farther. If the view is not visible in the start of the transition, then
+ * it will transition later when closer to the side and sooner when farther from the edge.
+ * This is the default TransitionPropagation used with {@link android.transition.Slide}.
+ */
+public class SidePropagation extends VisibilityPropagation {
+    private static final String TAG = "SlidePropagation";
+
+    /**
+     * Transition propagates relative to the distance of the left side of the scene.
+     */
+    public static final int LEFT = Slide.LEFT;
+
+    /**
+     * Transition propagates relative to the distance of the top of the scene.
+     */
+    public static final int TOP = Slide.TOP;
+
+    /**
+     * Transition propagates relative to the distance of the right side of the scene.
+     */
+    public static final int RIGHT = Slide.RIGHT;
+
+    /**
+     * Transition propagates relative to the distance of the bottom of the scene.
+     */
+    public static final int BOTTOM = Slide.BOTTOM;
+
+    private float mPropagationSpeed = 4.0f;
+    private int mSide = BOTTOM;
+
+    /**
+     * Sets the side that is used to calculate the transition propagation. If the transitioning
+     * View is visible in the start of the transition, then it will transition sooner when
+     * closer to the side and later when farther. If the view is not visible in the start of
+     * the transition, then it will transition later when closer to the side and sooner when
+     * farther from the edge. The default is {@link #BOTTOM}.
+     *
+     * @param side The side that is used to calculate the transition propagation. Must be one of
+     *             {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, or {@link #BOTTOM}.
+     */
+    public void setSide(int side) {
+        mSide = side;
+    }
+
+    /**
+     * Sets the speed at which transition propagation happens, relative to the duration of the
+     * Transition. A <code>propagationSpeed</code> of 1 means that a View centered at the side
+     * set in {@link #setSide(int)} and View centered at the opposite edge will have a difference
+     * in start delay of approximately the duration of the Transition. A speed of 2 means the
+     * start delay difference will be approximately half of the duration of the transition. A
+     * value of 0 is illegal, but negative values will invert the propagation.
+     *
+     * @param propagationSpeed The speed at which propagation occurs, relative to the duration
+     *                         of the transition. A speed of 4 means it works 4 times as fast
+     *                         as the duration of the transition. May not be 0.
+     */
+    public void setPropagationSpeed(float propagationSpeed) {
+        if (propagationSpeed == 0) {
+            throw new IllegalArgumentException("propagationSpeed may not be 0");
+        }
+        mPropagationSpeed = propagationSpeed;
+    }
+
+    @Override
+    public long getStartDelay(ViewGroup sceneRoot, Transition transition,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (startValues == null && endValues == null) {
+            return 0;
+        }
+        int directionMultiplier = 1;
+        Rect epicenter = transition.getEpicenter();
+        TransitionValues positionValues;
+        if (endValues == null || getViewVisibility(startValues) == View.VISIBLE) {
+            positionValues = startValues;
+            directionMultiplier = -1;
+        } else {
+            positionValues = endValues;
+        }
+
+        int viewCenterX = getViewX(positionValues);
+        int viewCenterY = getViewY(positionValues);
+
+        int[] loc = new int[2];
+        sceneRoot.getLocationOnScreen(loc);
+        int left = loc[0] + Math.round(sceneRoot.getTranslationX());
+        int top = loc[1] + Math.round(sceneRoot.getTranslationY());
+        int right = left + sceneRoot.getWidth();
+        int bottom = top + sceneRoot.getHeight();
+
+        int epicenterX;
+        int epicenterY;
+        if (epicenter != null) {
+            epicenterX = epicenter.centerX();
+            epicenterY = epicenter.centerY();
+        } else {
+            epicenterX = (left + right) / 2;
+            epicenterY = (top + bottom) / 2;
+        }
+
+        float distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY,
+                left, top, right, bottom);
+        float maxDistance = getMaxDistance(sceneRoot);
+        float distanceFraction = distance/maxDistance;
+
+        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
+                * distanceFraction);
+    }
+
+    private int distance(int viewX, int viewY, int epicenterX, int epicenterY,
+            int left, int top, int right, int bottom) {
+        int distance = 0;
+        switch (mSide) {
+            case LEFT:
+                distance = right - viewX + Math.abs(epicenterY - viewY);
+                break;
+            case TOP:
+                distance = bottom - viewY + Math.abs(epicenterX - viewX);
+                break;
+            case RIGHT:
+                distance = viewX - left + Math.abs(epicenterY - viewY);
+                break;
+            case BOTTOM:
+                distance = viewY - top + Math.abs(epicenterX - viewX);
+                break;
+        }
+        return distance;
+    }
+
+    private int getMaxDistance(ViewGroup sceneRoot) {
+        switch (mSide) {
+            case LEFT:
+            case RIGHT:
+                return sceneRoot.getWidth();
+            default:
+                return sceneRoot.getHeight();
+        }
+    }
+}
diff --git a/core/java/android/transition/Slide.java b/core/java/android/transition/Slide.java
index b38973c..0ff8ddd 100644
--- a/core/java/android/transition/Slide.java
+++ b/core/java/android/transition/Slide.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,53 +13,240 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package android.transition;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.util.Log;
+import android.util.Property;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 
 /**
- * This transition captures the visibility of target objects before and
- * after a scene change and animates any changes by sliding the target
- * objects into or out of place.
- *
- * @hide
+ * This transition tracks changes to the visibility of target views in the
+ * start and end scenes and moves views in or out from one of the edges of the
+ * scene. Visibility is determined by both the
+ * {@link View#setVisibility(int)} state of the view as well as whether it
+ * is parented in the current view hierarchy. Disappearing Views are
+ * limited as described in {@link Visibility#onDisappear(android.view.ViewGroup,
+ * TransitionValues, int, TransitionValues, int)}.
  */
 public class Slide extends Visibility {
+    private static final String TAG = "Slide";
 
-    // TODO: Add parameter for sliding factor - it's hard-coded below
+    /**
+     * Move Views in or out of the left edge of the scene.
+     * @see #setSlideEdge(int)
+     */
+    public static final int LEFT = 0;
 
-    private static final TimeInterpolator sAccelerator = new AccelerateInterpolator();
-    private static final TimeInterpolator sDecelerator = new DecelerateInterpolator();
+    /**
+     * Move Views in or out of the top edge of the scene.
+     * @see #setSlideEdge(int)
+     */
+    public static final int TOP = 1;
 
-    @Override
-    public Animator onAppear(ViewGroup sceneRoot,
-            TransitionValues startValues, int startVisibility,
-            TransitionValues endValues, int endVisibility) {
-        View endView = (endValues != null) ? endValues.view : null;
-        endView.setTranslationY(-2 * endView.getHeight());
-        ObjectAnimator anim = ObjectAnimator.ofFloat(endView, View.TRANSLATION_Y,
-                -2 * endView.getHeight(), 0);
-        anim.setInterpolator(sDecelerator);
+    /**
+     * Move Views in or out of the right edge of the scene.
+     * @see #setSlideEdge(int)
+     */
+    public static final int RIGHT = 2;
+
+    /**
+     * Move Views in or out of the bottom edge of the scene. This is the
+     * default slide direction.
+     * @see #setSlideEdge(int)
+     */
+    public static final int BOTTOM = 3;
+
+    private static final TimeInterpolator sDecelerate = new DecelerateInterpolator();
+    private static final TimeInterpolator sAccelerate = new AccelerateInterpolator();
+
+    private int[] mTempLoc = new int[2];
+    private CalculateSlide mSlideCalculator = sCalculateBottom;
+
+    private interface CalculateSlide {
+        /** Returns the translation value for view when it out of the scene */
+        float getGone(ViewGroup sceneRoot, View view);
+
+        /** Returns the translation value for view when it is in the scene */
+        float getHere(View view);
+
+        /** Returns the property to animate translation */
+        Property<View, Float> getProperty();
+    }
+
+    private static abstract class CalculateSlideHorizontal implements CalculateSlide {
+        @Override
+        public float getHere(View view) {
+            return view.getTranslationX();
+        }
+
+        @Override
+        public Property<View, Float> getProperty() {
+            return View.TRANSLATION_X;
+        }
+    }
+
+    private static abstract class CalculateSlideVertical implements CalculateSlide {
+        @Override
+        public float getHere(View view) {
+            return view.getTranslationY();
+        }
+
+        @Override
+        public Property<View, Float> getProperty() {
+            return View.TRANSLATION_Y;
+        }
+    }
+
+    private static final CalculateSlide sCalculateLeft = new CalculateSlideHorizontal() {
+        @Override
+        public float getGone(ViewGroup sceneRoot, View view) {
+            return view.getTranslationX() - sceneRoot.getWidth();
+        }
+    };
+
+    private static final CalculateSlide sCalculateTop = new CalculateSlideVertical() {
+        @Override
+        public float getGone(ViewGroup sceneRoot, View view) {
+            return view.getTranslationY() - sceneRoot.getHeight();
+        }
+    };
+
+    private static final CalculateSlide sCalculateRight = new CalculateSlideHorizontal() {
+        @Override
+        public float getGone(ViewGroup sceneRoot, View view) {
+            return view.getTranslationX() + sceneRoot.getWidth();
+        }
+    };
+
+    private static final CalculateSlide sCalculateBottom = new CalculateSlideVertical() {
+        @Override
+        public float getGone(ViewGroup sceneRoot, View view) {
+            return view.getTranslationY() + sceneRoot.getHeight();
+        }
+    };
+
+    /**
+     * Constructor using the default {@link android.transition.Slide#BOTTOM}
+     * slide edge direction.
+     */
+    public Slide() {
+        setSlideEdge(BOTTOM);
+    }
+
+    /**
+     * Constructor using the provided slide edge direction.
+     */
+    public Slide(int slideEdge) {
+        setSlideEdge(slideEdge);
+    }
+
+    /**
+     * Change the edge that Views appear and disappear from.
+     * @param slideEdge The edge of the scene to use for Views appearing and disappearing.
+     */
+    public void setSlideEdge(int slideEdge) {
+        switch (slideEdge) {
+            case LEFT:
+                mSlideCalculator = sCalculateLeft;
+                break;
+            case TOP:
+                mSlideCalculator = sCalculateTop;
+                break;
+            case RIGHT:
+                mSlideCalculator = sCalculateRight;
+                break;
+            case BOTTOM:
+                mSlideCalculator = sCalculateBottom;
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid slide direction");
+        }
+        SidePropagation propagation = new SidePropagation();
+        propagation.setSide(slideEdge);
+        setPropagation(propagation);
+    }
+
+    private Animator createAnimation(final View view, Property<View, Float> property,
+            float start, float end, float terminalValue, TimeInterpolator interpolator) {
+        view.setTranslationY(start);
+        if (start == end) {
+            return null;
+        }
+        final ObjectAnimator anim = ObjectAnimator.ofFloat(view, property, start, end);
+
+        SlideAnimatorListener listener = new SlideAnimatorListener(view, terminalValue, end);
+        anim.addListener(listener);
+        anim.addPauseListener(listener);
+        anim.setInterpolator(interpolator);
         return anim;
     }
 
     @Override
-    public Animator onDisappear(ViewGroup sceneRoot,
-            TransitionValues startValues, int startVisibility,
-            TransitionValues endValues, int endVisibility) {
-        View startView = (startValues != null) ? startValues.view : null;
-        startView.setTranslationY(0);
-        ObjectAnimator anim = ObjectAnimator.ofFloat(startView, View.TRANSLATION_Y, 0,
-                -2 * startView.getHeight());
-        anim.setInterpolator(sAccelerator);
-        return anim;
+    public Animator onAppear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        if (endValues == null) {
+            return null;
+        }
+        float end = mSlideCalculator.getHere(view);
+        float start = mSlideCalculator.getGone(sceneRoot, view);
+        return createAnimation(view, mSlideCalculator.getProperty(), start, end, end, sDecelerate);
     }
 
+    @Override
+    public Animator onDisappear(ViewGroup sceneRoot, View view,
+            TransitionValues startValues, TransitionValues endValues) {
+        float start = mSlideCalculator.getHere(view);
+        float end = mSlideCalculator.getGone(sceneRoot, view);
+
+        return createAnimation(view, mSlideCalculator.getProperty(), start, end, start,
+                sAccelerate);
+    }
+
+    private static class SlideAnimatorListener extends AnimatorListenerAdapter {
+        private boolean mCanceled = false;
+        private float mPausedY;
+        private final View mView;
+        private final float mEndY;
+        private final float mTerminalY;
+
+        public SlideAnimatorListener(View view, float terminalY, float endY) {
+            mView = view;
+            mTerminalY = terminalY;
+            mEndY = endY;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animator) {
+            mView.setTranslationY(mTerminalY);
+            mCanceled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animator) {
+            if (!mCanceled) {
+                mView.setTranslationY(mTerminalY);
+            }
+        }
+
+        @Override
+        public void onAnimationPause(Animator animator) {
+            mPausedY = mView.getTranslationY();
+            mView.setTranslationY(mEndY);
+        }
+
+        @Override
+        public void onAnimationResume(Animator animator) {
+            mView.setTranslationY(mPausedY);
+        }
+    }
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index c88b4c0..b7ae31e 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -19,10 +19,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
+import android.graphics.Rect;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.SparseArray;
+import android.util.SparseLongArray;
 import android.view.SurfaceView;
 import android.view.TextureView;
 import android.view.View;
@@ -60,10 +62,18 @@
  * <p>Transitions can be declared in XML resource files inside the <code>res/transition</code>
  * directory. Transition resources consist of a tag name for one of the Transition
  * subclasses along with attributes to define some of the attributes of that transition.
- * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:</p>
+ * For example, here is a minimal resource file that declares a {@link ChangeBounds} transition:
  *
  * {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
  *
+ * <p>{@link android.transition.Explode} transition:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/transition/explode.xml Explode}
+ *
+ * <p>{@link android.transition.MoveImage} transition:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/transition/move_image.xml MoveImage}
+ *
  * <p>Note that attributes for the transition are not required, just as they are
  * optional when declared in code; Transitions created from XML resources will use
  * the same defaults as their code-created equivalents. Here is a slightly more
@@ -87,7 +97,8 @@
  *
  * Further information on XML resource descriptions for transitions can be found for
  * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet},
- * {@link android.R.styleable#TransitionTarget}, and {@link android.R.styleable#Fade}.
+ * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, and
+ * {@link android.R.styleable#Slide}.
  *
  */
 public abstract class Transition implements Cloneable {
@@ -149,6 +160,13 @@
     // to be run in runAnimators()
     ArrayList<Animator> mAnimators = new ArrayList<Animator>();
 
+    // The function for calculating the Animation start delay.
+    TransitionPropagation mPropagation;
+
+    // The rectangular region for Transitions like Explode and TransitionPropagations
+    // like CircularPropagation
+    EpicenterCallback mEpicenterCallback;
+
     /**
      * Constructs a Transition object with no target objects. A transition with
      * no targets defaults to running on all target objects in the scene hierarchy
@@ -435,6 +453,9 @@
             endValuesList.add(end);
         }
         ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+        long minStartDelay = Long.MAX_VALUE;
+        int minAnimator = mAnimators.size();
+        SparseLongArray startDelays = new SparseLongArray();
         for (int i = 0; i < startValuesList.size(); ++i) {
             TransitionValues start = startValuesList.get(i);
             TransitionValues end = endValuesList.get(i);
@@ -497,6 +518,12 @@
                             view = (start != null) ? start.view : null;
                         }
                         if (animator != null) {
+                            if (mPropagation != null) {
+                                long delay = mPropagation
+                                        .getStartDelay(sceneRoot, this, start, end);
+                                startDelays.put(mAnimators.size(), delay);
+                                minStartDelay = Math.min(delay, minStartDelay);
+                            }
                             AnimationInfo info = new AnimationInfo(view, getName(),
                                     sceneRoot.getWindowId(), infoValues);
                             runningAnimators.put(animator, info);
@@ -506,6 +533,14 @@
                 }
             }
         }
+        if (minStartDelay != 0) {
+            for (int i = 0; i < startDelays.size(); i++) {
+                int index = startDelays.keyAt(i);
+                Animator animator = mAnimators.get(index);
+                long delay = startDelays.valueAt(i) - minStartDelay + animator.getStartDelay();
+                animator.setStartDelay(delay);
+            }
+        }
     }
 
     /**
@@ -565,7 +600,7 @@
 
     /**
      * This is called internally once all animations have been set up by the
-     * transition hierarchy. \
+     * transition hierarchy.
      *
      * @hide
      */
@@ -1010,6 +1045,7 @@
                         } else {
                             captureEndValues(values);
                         }
+                        capturePropagationValues(values);
                         if (start) {
                             mStartValues.viewValues.put(view, values);
                             if (id >= 0) {
@@ -1035,6 +1071,7 @@
                         } else {
                             captureEndValues(values);
                         }
+                        capturePropagationValues(values);
                         if (start) {
                             mStartValues.viewValues.put(view, values);
                         } else {
@@ -1122,6 +1159,7 @@
             } else {
                 captureEndValues(values);
             }
+            capturePropagationValues(values);
             if (start) {
                 if (!isListViewItem) {
                     mStartValues.viewValues.put(view, values);
@@ -1340,7 +1378,7 @@
                 animator.setDuration(getDuration());
             }
             if (getStartDelay() >= 0) {
-                animator.setStartDelay(getStartDelay());
+                animator.setStartDelay(getStartDelay() + animator.getStartDelay());
             }
             if (getInterpolator() != null) {
                 animator.setInterpolator(getInterpolator());
@@ -1473,6 +1511,98 @@
         return this;
     }
 
+    /**
+     * Sets the callback to use to find the epicenter of a Transition. A null value indicates
+     * that there is no epicenter in the Transition and getEpicenter() will return null.
+     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
+     * the direction of travel. This is called the epicenter of the Transition and is
+     * typically centered on a touched View. The
+     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
+     * dynamically retrieve the epicenter during a Transition.
+     * @param epicenterCallback The callback to use to find the epicenter of the Transition.
+     */
+    public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+        mEpicenterCallback = epicenterCallback;
+    }
+
+    /**
+     * Returns the callback used to find the epicenter of the Transition.
+     * Transitions like {@link android.transition.Explode} use a point or Rect to orient
+     * the direction of travel. This is called the epicenter of the Transition and is
+     * typically centered on a touched View. The
+     * {@link android.transition.Transition.EpicenterCallback} allows a Transition to
+     * dynamically retrieve the epicenter during a Transition.
+     * @return the callback used to find the epicenter of the Transition.
+     */
+    public EpicenterCallback getEpicenterCallback() {
+        return mEpicenterCallback;
+    }
+
+    /**
+     * Returns the epicenter as specified by the
+     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
+     * @return the epicenter as specified by the
+     * {@link android.transition.Transition.EpicenterCallback} or null if no callback exists.
+     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
+     */
+    public Rect getEpicenter() {
+        if (mEpicenterCallback == null) {
+            return null;
+        }
+        return mEpicenterCallback.getEpicenter(this);
+    }
+
+    /**
+     * Sets the method for determining Animator start delays.
+     * When a Transition affects several Views like {@link android.transition.Explode} or
+     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
+     * such that the Animator start delay depends on position of the View. The
+     * TransitionPropagation specifies how the start delays are calculated.
+     * @param transitionPropagation The class used to determine the start delay of
+     *                              Animators created by this Transition. A null value
+     *                              indicates that no delay should be used.
+     */
+    public void setPropagation(TransitionPropagation transitionPropagation) {
+        mPropagation = transitionPropagation;
+    }
+
+    /**
+     * Returns the {@link android.transition.TransitionPropagation} used to calculate Animator start
+     * delays.
+     * When a Transition affects several Views like {@link android.transition.Explode} or
+     * {@link android.transition.Slide}, there may be a desire to have a "wave-front" effect
+     * such that the Animator start delay depends on position of the View. The
+     * TransitionPropagation specifies how the start delays are calculated.
+     * @return the {@link android.transition.TransitionPropagation} used to calculate Animator start
+     * delays. This is null by default.
+     */
+    public TransitionPropagation getPropagation() {
+        return mPropagation;
+    }
+
+    /**
+     * Captures TransitionPropagation values for the given view and the
+     * hierarchy underneath it.
+     */
+    void capturePropagationValues(TransitionValues transitionValues) {
+        if (mPropagation != null) {
+            String[] propertyNames = mPropagation.getPropagationProperties();
+            if (propertyNames == null) {
+                return;
+            }
+            boolean containsAll = true;
+            for (int i = 0; i < propertyNames.length; i++) {
+                if (!transitionValues.values.containsKey(propertyNames[i])) {
+                    containsAll = false;
+                    break;
+                }
+            }
+            if (!containsAll) {
+                mPropagation.captureValues(transitionValues);
+            }
+        }
+    }
+
     Transition setSceneRoot(ViewGroup sceneRoot) {
         mSceneRoot = sceneRoot;
         return this;
@@ -1710,4 +1840,28 @@
         }
     }
 
+    /**
+     * Class to get the epicenter of Transition. Use
+     * {@link #setEpicenterCallback(android.transition.Transition.EpicenterCallback)} to
+     * set the callback used to calculate the epicenter of the Transition. Override
+     * {@link #getEpicenter()} to return the rectangular region in screen coordinates of
+     * the epicenter of the transition.
+     * @see #setEpicenterCallback(android.transition.Transition.EpicenterCallback)
+     */
+    public static abstract class EpicenterCallback {
+
+        /**
+         * Implementers must override to return the epicenter of the Transition in screen
+         * coordinates. Transitions like {@link android.transition.Explode} depend upon
+         * an epicenter for the Transition. In Explode, Views move toward or away from the
+         * center of the epicenter Rect along the vector between the epicenter and the center
+         * of the View appearing and disappearing. Some Transitions, such as
+         * {@link android.transition.Fade} pay no attention to the epicenter.
+         *
+         * @param transition The transition for which the epicenter applies.
+         * @return The Rect region of the epicenter of <code>transition</code> or null if
+         * there is no epicenter.
+         */
+        public abstract Rect getEpicenter(Transition transition);
+    }
 }
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 912f2ed..f675c6a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.InflateException;
@@ -146,7 +145,13 @@
                 transition = new ChangeBounds();
                 newTransition = true;
             } else if ("slide".equals(name)) {
-                transition = new Slide();
+                transition = createSlideTransition(attrs);
+                newTransition = true;
+            } else if ("explode".equals(name)) {
+                transition = new Explode();
+                newTransition = true;
+            } else if ("moveImage".equals(name)) {
+                transition = new MoveImage();
                 newTransition = true;
             } else if ("autoTransition".equals(name)) {
                 transition = new AutoTransition();
@@ -189,6 +194,15 @@
         return transition;
     }
 
+    private Slide createSlideTransition(AttributeSet attrs) {
+        TypedArray a = mContext.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Slide);
+        int edge = a.getInt(com.android.internal.R.styleable.Slide_slideEdge, Slide.BOTTOM);
+        Slide slide = new Slide(edge);
+        a.recycle();
+        return slide;
+    }
+
     private void getTargetIds(XmlPullParser parser,
             AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException {
 
diff --git a/core/java/android/transition/TransitionPropagation.java b/core/java/android/transition/TransitionPropagation.java
new file mode 100644
index 0000000..9a481c2
--- /dev/null
+++ b/core/java/android/transition/TransitionPropagation.java
@@ -0,0 +1,88 @@
+/*
+ * 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.transition;
+
+import android.graphics.Rect;
+import android.view.ViewGroup;
+
+/**
+ * Extend <code>TransitionPropagation</code> to customize start delays for Animators created
+ * in {@link android.transition.Transition#createAnimator(ViewGroup,
+ * TransitionValues, TransitionValues)}. A Transition such as {@link android.transition.Explode}
+ * defaults to using {@link android.transition.CircularPropagation} and Views closer to the
+ * epicenter will move out of the scene later and into the scene sooner than Views farther
+ * from the epicenter, giving the appearance of inertia. With no TransitionPropagation, all
+ * Views will react simultaneously to the start of the transition.
+ *
+ * @see Transition#setPropagation(TransitionPropagation)
+ * @see Transition#getEpicenter()
+ */
+public abstract class TransitionPropagation {
+    /**
+     * Called by Transition to alter the Animator start delay. All start delays will be adjusted
+     * such that the minimum becomes zero.
+     * @param sceneRoot The root of the View hierarchy running the transition.
+     * @param transition The transition that created the Animator
+     * @param startValues The values for a specific target in the start scene.
+     * @param endValues The values for the target in the end scene.
+     * @return A start delay to use with the Animator created by <code>transition</code>. The
+     * delay will be offset by the minimum delay of all <code>TransitionPropagation</code>s
+     * used in the Transition so that the smallest delay will be 0. Returned values may be
+     * negative.
+     */
+    public abstract long getStartDelay(ViewGroup sceneRoot, Transition transition,
+            TransitionValues startValues, TransitionValues endValues);
+
+    /**
+     * Captures the values in the start or end scene for the properties that this
+     * transition propagation monitors. These values are then passed as the startValues
+     * or endValues structure in a later call to
+     * {@link #getStartDelay(ViewGroup, Transition, TransitionValues, TransitionValues)}.
+     * The main concern for an implementation is what the
+     * properties are that the transition cares about and what the values are
+     * for all of those properties. The start and end values will be compared
+     * later during the
+     * {@link #getStartDelay(ViewGroup, Transition, TransitionValues, TransitionValues)}.
+     * method to determine the start delay.
+     *
+     * <p>Subclasses must implement this method. The method should only be called by the
+     * transition system; it is not intended to be called from external classes.</p>
+     *
+     * @param transitionValues The holder for any values that the Transition
+     * wishes to store. Values are stored in the <code>values</code> field
+     * of this TransitionValues object and are keyed from
+     * a String value. For example, to store a view's rotation value,
+     * a transition might call
+     * <code>transitionValues.values.put("appname:transitionname:rotation",
+     * view.getRotation())</code>. The target view will already be stored in
+     * the transitionValues structure when this method is called.
+     */
+    public abstract void captureValues(TransitionValues transitionValues);
+
+    /**
+     * Returns the set of property names stored in the {@link TransitionValues}
+     * object passed into {@link #captureValues(TransitionValues)} that
+     * this transition propagation cares about for the purposes of preventing
+     * duplicate capturing of property values.
+
+     * <p>A <code>TransitionPropagation</code> must override this method to prevent
+     * duplicate capturing of values and must contain at least one </p>
+     *
+     * @return An array of property names as described in the class documentation for
+     * {@link TransitionValues}.
+     */
+    public abstract String[] getPropagationProperties() ;
+}
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 19d6b3d..966b24d 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -17,6 +17,7 @@
 package android.transition;
 
 import android.animation.TimeInterpolator;
+import android.graphics.Rect;
 import android.util.AndroidRuntimeException;
 import android.view.View;
 import android.view.ViewGroup;
@@ -315,6 +316,15 @@
         }
     }
 
+    @Override
+    void capturePropagationValues(TransitionValues transitionValues) {
+        super.capturePropagationValues(transitionValues);
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).capturePropagationValues(transitionValues);
+        }
+    }
+
     /** @hide */
     @Override
     public void pause(View sceneRoot) {
@@ -365,6 +375,24 @@
     }
 
     @Override
+    public void setPropagation(TransitionPropagation propagation) {
+        super.setPropagation(propagation);
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).setPropagation(propagation);
+        }
+    }
+
+    @Override
+    public void setEpicenterCallback(EpicenterCallback epicenterCallback) {
+        super.setEpicenterCallback(epicenterCallback);
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).setEpicenterCallback(epicenterCallback);
+        }
+    }
+
+    @Override
     String toString(String indent) {
         String result = super.toString(indent);
         for (int i = 0; i < mTransitions.size(); ++i) {
@@ -383,5 +411,4 @@
         }
         return clone;
     }
-
 }
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 44f92cd..7783b6f 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -17,6 +17,7 @@
 package android.transition;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -29,15 +30,20 @@
  * information to determine the specific animations to run when visibility
  * changes occur. Subclasses should implement one or both of the methods
  * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
- * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)},
+ * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
+ * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
+ * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
  */
 public abstract class Visibility extends Transition {
 
     private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
     private static final String PROPNAME_PARENT = "android:visibility:parent";
+    private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
+
     private static final String[] sTransitionProperties = {
             PROPNAME_VISIBILITY,
             PROPNAME_PARENT,
+            PROPNAME_SCREEN_LOCATION,
     };
 
     private static class VisibilityInfo {
@@ -58,6 +64,9 @@
         int visibility = transitionValues.view.getVisibility();
         transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
         transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
+        int[] loc = new int[2];
+        transitionValues.view.getLocationOnScreen(loc);
+        transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
     }
 
     @Override
@@ -179,8 +188,11 @@
     }
 
     /**
-     * The default implementation of this method does nothing. Subclasses
-     * should override if they need to create an Animator when targets appear.
+     * The default implementation of this method calls
+     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
+     * Subclasses should override this method or
+     * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
+     * if they need to create an Animator when targets appear.
      * The method should only be called by the Visibility class; it is
      * not intended to be called from external classes.
      *
@@ -196,15 +208,53 @@
     public Animator onAppear(ViewGroup sceneRoot,
             TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
+        return onAppear(sceneRoot, endValues.view, startValues, endValues);
+    }
+
+    /**
+     * The default implementation of this method returns a null Animator. Subclasses should
+     * override this method to make targets appear with the desired transition. The
+     * method should only be called from
+     * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+     *
+     * @param sceneRoot The root of the transition hierarchy
+     * @param view The View to make appear. This will be in the target scene's View hierarchy and
+     *             will be VISIBLE.
+     * @param startValues The target values in the start scene
+     * @param endValues The target values in the end scene
+     * @return An Animator to be started at the appropriate time in the
+     * overall transition for this scene change. A null value means no animation
+     * should be run.
+     */
+    public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+            TransitionValues endValues) {
         return null;
     }
 
     /**
-     * The default implementation of this method does nothing. Subclasses
-     * should override if they need to create an Animator when targets disappear.
+     * Subclasses should override this method or
+     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
+     * if they need to create an Animator when targets disappear.
      * The method should only be called by the Visibility class; it is
      * not intended to be called from external classes.
-     *
+     * <p>
+     * The default implementation of this method attempts to find a View to use to call
+     * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
+     * based on the situation of the View in the View hierarchy. For example,
+     * if a View was simply removed from its parent, then the View will be added
+     * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code>
+     * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
+     * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
+     * then it can be used as the <code>view</code> and the visibility will be changed
+     * to {@link View#VISIBLE} for the duration of the animation. However, if a View
+     * is in a hierarchy which is also altering its visibility, the situation can be
+     * more complicated. In general, if a view that is no longer in the hierarchy in
+     * the end scene still has a parent (so its parent hierarchy was removed, but it
+     * was not removed from its parent), then it will be left alone to avoid side-effects from
+     * improperly removing it from its parent. The only exception to this is if
+     * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
+     * android.content.Context) created from a layout resource file}, then it is considered
+     * safe to un-parent the starting scene view in order to make it disappear.</p>
      *
      * @param sceneRoot The root of the transition hierarchy
      * @param startValues The target values in the start scene
@@ -218,6 +268,144 @@
     public Animator onDisappear(ViewGroup sceneRoot,
             TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
+        View startView = (startValues != null) ? startValues.view : null;
+        View endView = (endValues != null) ? endValues.view : null;
+        View overlayView = null;
+        View viewToKeep = null;
+        if (endView == null || endView.getParent() == null) {
+            if (endView != null) {
+                // endView was removed from its parent - add it to the overlay
+                overlayView = endView;
+            } else if (startView != null) {
+                // endView does not exist. Use startView only under certain
+                // conditions, because placing a view in an overlay necessitates
+                // it being removed from its current parent
+                if (startView.getParent() == null) {
+                    // no parent - safe to use
+                    overlayView = startView;
+                } else if (startView.getParent() instanceof View &&
+                        startView.getParent().getParent() == null) {
+                    View startParent = (View) startView.getParent();
+                    int id = startParent.getId();
+                    if (id != View.NO_ID && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
+                        // no parent, but its parent is unparented  but the parent
+                        // hierarchy has been replaced by a new hierarchy with the same id
+                        // and it is safe to un-parent startView
+                        overlayView = startView;
+                    }
+                }
+            }
+        } else {
+            // visibility change
+            if (endVisibility == View.INVISIBLE) {
+                viewToKeep = endView;
+            } else {
+                // Becoming GONE
+                if (startView == endView) {
+                    viewToKeep = endView;
+                } else {
+                    overlayView = startView;
+                }
+            }
+        }
+        final int finalVisibility = endVisibility;
+        final ViewGroup finalSceneRoot = sceneRoot;
+
+        if (overlayView != null) {
+            // TODO: Need to do this for general case of adding to overlay
+            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
+            int screenX = screenLoc[0];
+            int screenY = screenLoc[1];
+            int[] loc = new int[2];
+            sceneRoot.getLocationOnScreen(loc);
+            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
+            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
+            sceneRoot.getOverlay().add(overlayView);
+            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
+            if (animator == null) {
+                sceneRoot.getOverlay().remove(overlayView);
+            } else {
+                final View finalOverlayView = overlayView;
+                animator.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        finalSceneRoot.getOverlay().remove(finalOverlayView);
+                    }
+
+                    @Override
+                    public void onAnimationPause(Animator animation) {
+                        finalSceneRoot.getOverlay().remove(finalOverlayView);
+                    }
+
+                    @Override
+                    public void onAnimationResume(Animator animation) {
+                        finalSceneRoot.getOverlay().add(finalOverlayView);
+                    }
+                });
+            }
+            return animator;
+        }
+
+        if (viewToKeep != null) {
+            viewToKeep.setVisibility(View.VISIBLE);
+            Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
+            if (animator == null) {
+                viewToKeep.setVisibility(finalVisibility);
+            } else {
+                final View finalViewToKeep = viewToKeep;
+                animator.addListener(new AnimatorListenerAdapter() {
+                    boolean mCanceled = false;
+
+                    @Override
+                    public void onAnimationPause(Animator animation) {
+                        if (!mCanceled) {
+                            finalViewToKeep.setVisibility(finalVisibility);
+                        }
+                    }
+
+                    @Override
+                    public void onAnimationResume(Animator animation) {
+                        if (!mCanceled) {
+                            finalViewToKeep.setVisibility(View.VISIBLE);
+                        }
+                    }
+
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+                        mCanceled = true;
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        if (!mCanceled) {
+                            finalViewToKeep.setVisibility(finalVisibility);
+                        }
+                    }
+                });
+            }
+            return animator;
+        }
+        return null;
+    }
+
+    /**
+     * The default implementation of this method returns a null Animator. Subclasses should
+     * override this method to make targets disappear with the desired transition. The
+     * method should only be called from
+     * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
+     *
+     * @param sceneRoot The root of the transition hierarchy
+     * @param view The View to make disappear. This will be in the target scene's View
+     *             hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
+     *             VISIBLE.
+     * @param startValues The target values in the start scene
+     * @param endValues The target values in the end scene
+     * @return An Animator to be started at the appropriate time in the
+     * overall transition for this scene change. A null value means no animation
+     * should be run.
+     */
+    public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+            TransitionValues endValues) {
         return null;
     }
 }
diff --git a/core/java/android/transition/VisibilityPropagation.java b/core/java/android/transition/VisibilityPropagation.java
new file mode 100644
index 0000000..0326d47
--- /dev/null
+++ b/core/java/android/transition/VisibilityPropagation.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition;
+
+import android.view.View;
+
+/**
+ * Base class for <code>TransitionPropagation</code>s that care about
+ * View Visibility and the center position of the View.
+ */
+public abstract class VisibilityPropagation extends TransitionPropagation {
+
+    /**
+     * The property key used for {@link android.view.View#getVisibility()}.
+     */
+    private static final String PROPNAME_VISIBILITY = "android:visibilityPropagation:visibility";
+
+    /**
+     * The property key used for the center of the View in screen coordinates. This is an
+     * int[2] with the index 0 taking the x coordinate and index 1 taking the y coordinate.
+     */
+    private static final String PROPNAME_VIEW_CENTER = "android:visibilityPropagation:center";
+
+    private static final String[] VISIBILITY_PROPAGATION_VALUES = {
+            PROPNAME_VISIBILITY,
+            PROPNAME_VIEW_CENTER,
+    };
+
+    @Override
+    public void captureValues(TransitionValues values) {
+        View view = values.view;
+        values.values.put(PROPNAME_VISIBILITY, view.getVisibility());
+        int[] loc = new int[2];
+        view.getLocationOnScreen(loc);
+        loc[0] += Math.round(view.getTranslationX());
+        loc[0] += view.getWidth() / 2;
+        loc[1] += Math.round(view.getTranslationY());
+        loc[1] += view.getHeight() / 2;
+        values.values.put(PROPNAME_VIEW_CENTER, loc);
+    }
+
+    @Override
+    public String[] getPropagationProperties() {
+        return VISIBILITY_PROPAGATION_VALUES;
+    }
+
+    /**
+     * Returns {@link android.view.View#getVisibility()} for the View at the time the values
+     * were captured.
+     * @param values The TransitionValues captured at the start or end of the Transition.
+     * @return {@link android.view.View#getVisibility()} for the View at the time the values
+     * were captured.
+     */
+    public int getViewVisibility(TransitionValues values) {
+        if (values == null) {
+            return View.GONE;
+        }
+        Integer visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
+        if (visibility == null) {
+            return View.GONE;
+        }
+        return visibility;
+    }
+
+    /**
+     * Returns the View's center x coordinate, relative to the screen, at the time the values
+     * were captured.
+     * @param values The TransitionValues captured at the start or end of the Transition.
+     * @return the View's center x coordinate, relative to the screen, at the time the values
+     * were captured.
+     */
+    public int getViewX(TransitionValues values) {
+        return getViewCoordinate(values, 0);
+    }
+
+    /**
+     * Returns the View's center y coordinate, relative to the screen, at the time the values
+     * were captured.
+     * @param values The TransitionValues captured at the start or end of the Transition.
+     * @return the View's center y coordinate, relative to the screen, at the time the values
+     * were captured.
+     */
+    public int getViewY(TransitionValues values) {
+        return getViewCoordinate(values, 1);
+    }
+
+    private static int getViewCoordinate(TransitionValues values, int coordinateIndex) {
+        if (values == null) {
+            return -1;
+        }
+
+        int[] coordinates = (int[]) values.values.get(PROPNAME_VIEW_CENTER);
+        if (coordinates == null) {
+            return -1;
+        }
+
+        return coordinates[coordinateIndex];
+    }
+}
diff --git a/core/java/android/tv/ITvInputClient.aidl b/core/java/android/tv/ITvInputClient.aidl
new file mode 100644
index 0000000..43be6f0
--- /dev/null
+++ b/core/java/android/tv/ITvInputClient.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.tv;
+
+import android.content.ComponentName;
+import android.tv.ITvInputSession;
+
+/**
+ * Interface a client of the ITvInputManager implements, to identify itself and receive information
+ * about changes to the state of each TV input service.
+ * @hide
+ */
+oneway interface ITvInputClient {
+    void onSessionCreated(in ComponentName name, IBinder token, int seq);
+    void onAvailabilityChanged(in ComponentName name, boolean isAvailable);
+}
diff --git a/core/java/android/tv/ITvInputManager.aidl b/core/java/android/tv/ITvInputManager.aidl
new file mode 100644
index 0000000..a927dc9
--- /dev/null
+++ b/core/java/android/tv/ITvInputManager.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.tv;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.tv.ITvInputClient;
+import android.tv.TvInputInfo;
+import android.view.Surface;
+
+/**
+ * Interface to the TV input manager service.
+ * @hide
+ */
+interface ITvInputManager {
+    List<TvInputInfo> getTvInputList(int userId);
+
+    boolean getAvailability(in ITvInputClient client, in ComponentName name, int userId);
+
+    void registerCallback(in ITvInputClient client, in ComponentName name, int userId);
+    void unregisterCallback(in ITvInputClient client, in ComponentName name, int userId);
+
+    void createSession(in ITvInputClient client, in ComponentName name, int seq, int userId);
+    void releaseSession(in IBinder sessionToken, int userId);
+
+    void setSurface(in IBinder sessionToken, in Surface surface, int userId);
+    void setVolume(in IBinder sessionToken, float volume, int userId);
+    void tune(in IBinder sessionToken, in Uri channelUri, int userId);
+}
diff --git a/core/java/android/tv/ITvInputService.aidl b/core/java/android/tv/ITvInputService.aidl
new file mode 100644
index 0000000..d80f286
--- /dev/null
+++ b/core/java/android/tv/ITvInputService.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.tv;
+
+import android.tv.ITvInputServiceCallback;
+import android.tv.ITvInputSession;
+import android.tv.ITvInputSessionCallback;
+
+/**
+ * Top-level interface to a TV input component (implemented in a Service).
+ * @hide
+ */
+oneway interface ITvInputService {
+    void registerCallback(ITvInputServiceCallback callback);
+    void unregisterCallback(in ITvInputServiceCallback callback);
+    void createSession(ITvInputSessionCallback callback);
+}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/tv/ITvInputServiceCallback.aidl
similarity index 66%
copy from core/java/android/view/DisplayList.java
copy to core/java/android/tv/ITvInputServiceCallback.aidl
index ed52803..e535c81 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/tv/ITvInputServiceCallback.aidl
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.tv;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
+import android.content.ComponentName;
+
+/**
+ * Helper interface for ITvInputService to allow the TV input to notify the client when its status
+ * has been changed.
+ * @hide
  */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
+oneway interface ITvInputServiceCallback {
+    void onAvailabilityChanged(in ComponentName name, boolean isAvailable);
 }
diff --git a/core/java/android/tv/ITvInputSession.aidl b/core/java/android/tv/ITvInputSession.aidl
new file mode 100644
index 0000000..d379d2d
--- /dev/null
+++ b/core/java/android/tv/ITvInputSession.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.tv;
+
+import android.net.Uri;
+import android.view.Surface;
+
+/**
+ * Sub-interface of ITvInputService which is created per session and has its own context.
+ * @hide
+ */
+oneway interface ITvInputSession {
+    void release();
+
+    void setSurface(in Surface surface);
+    // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
+    // is to introduce some new concepts that will solve a number of problems in audio policy today.
+    void setVolume(float volume);
+    void tune(in Uri channelUri);
+}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/tv/ITvInputSessionCallback.aidl
similarity index 67%
copy from core/java/android/view/DisplayList.java
copy to core/java/android/tv/ITvInputSessionCallback.aidl
index ed52803..a2bd0d7 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/tv/ITvInputSessionCallback.aidl
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.tv;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
+import android.tv.ITvInputSession;
+
+/**
+ * Helper interface for ITvInputSession to allow the TV input to notify the system service when a
+ * new session has been created.
+ * @hide
  */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
+oneway interface ITvInputSessionCallback {
+    void onSessionCreated(ITvInputSession session);
 }
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/core/java/android/tv/ITvInputSessionWrapper.java
new file mode 100644
index 0000000..fd4e1e3
--- /dev/null
+++ b/core/java/android/tv/ITvInputSessionWrapper.java
@@ -0,0 +1,99 @@
+/*
+ * 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.tv;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Message;
+import android.util.Log;
+import android.view.Surface;
+
+import com.android.internal.os.HandlerCaller;
+
+/**
+ * Implements the internal ITvInputSession interface to convert incoming calls on to it back to
+ * calls on the public TvInputSession interface, scheduling them on the main thread of the process.
+ *
+ * @hide
+ */
+public class ITvInputSessionWrapper extends ITvInputSession.Stub implements HandlerCaller.Callback {
+    private static final String TAG = "TvInputSessionWrapper";
+
+    private static final int DO_RELEASE = 1;
+    private static final int DO_SET_SURFACE = 2;
+    private static final int DO_SET_VOLUME = 3;
+    private static final int DO_TUNE = 4;
+
+    private TvInputSession mTvInputSession;
+    private final HandlerCaller mCaller;
+
+    public ITvInputSessionWrapper(Context context, TvInputSession session) {
+        mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
+        mTvInputSession = session;
+    }
+
+    @Override
+    public void executeMessage(Message msg) {
+        if (mTvInputSession == null) {
+            return;
+        }
+
+        switch (msg.what) {
+            case DO_RELEASE: {
+                mTvInputSession.release();
+                mTvInputSession = null;
+                return;
+            }
+            case DO_SET_SURFACE: {
+                mTvInputSession.setSurface((Surface) msg.obj);
+                return;
+            }
+            case DO_SET_VOLUME: {
+                mTvInputSession.setVolume((Float) msg.obj);
+                return;
+            }
+            case DO_TUNE: {
+                mTvInputSession.tune((Uri) msg.obj);
+                return;
+            }
+            default: {
+                Log.w(TAG, "Unhandled message code: " + msg.what);
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void release() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
+    }
+
+    @Override
+    public void setSurface(Surface surface) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface));
+    }
+
+    @Override
+    public final void setVolume(float volume) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_VOLUME, volume));
+    }
+
+    @Override
+    public void tune(Uri channelUri) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_TUNE, channelUri));
+    }
+}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/tv/TvInputInfo.aidl
similarity index 76%
rename from core/java/android/view/DisplayList.java
rename to core/java/android/tv/TvInputInfo.aidl
index ed52803..abc4b47 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/tv/TvInputInfo.aidl
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.tv;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
- */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
-}
+parcelable TvInputInfo;
diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java
new file mode 100644
index 0000000..90625d8
--- /dev/null
+++ b/core/java/android/tv/TvInputInfo.java
@@ -0,0 +1,124 @@
+/*
+ * 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.tv;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class is used to specify meta information of a TV input.
+ */
+public final class TvInputInfo implements Parcelable {
+    private final ResolveInfo mService;
+    private final String mId;
+
+    /**
+     * Constructor.
+     *
+     * @param service The ResolveInfo returned from the package manager about this TV input service.
+     * @hide
+     */
+    public TvInputInfo(ResolveInfo service) {
+        mService = service;
+        ServiceInfo si = service.serviceInfo;
+        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+    }
+
+    /**
+     * Returns a unique ID for this TV input. The ID is generated from the package and class name
+     * implementing the TV input service.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the .apk package that implements this TV input service.
+     */
+    public String getPackageName() {
+        return mService.serviceInfo.packageName;
+    }
+
+    /**
+     * Returns the class name of the service component that implements this TV input service.
+     */
+    public String getServiceName() {
+        return mService.serviceInfo.name;
+    }
+
+    /**
+     * Returns the component of the service that implements this TV input.
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Loads the user-displayed label for this TV input service.
+     *
+     * @param pm Supplies a PackageManager used to load the TV input's resources.
+     * @return Returns a CharSequence containing the TV input's label. If the TV input does not have
+     *         a label, its name is returned.
+     */
+    public CharSequence loadLabel(PackageManager pm) {
+        return mService.loadLabel(pm);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        mService.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Used to make this class parcelable.
+     *
+     * @hide
+     */
+    public static final Parcelable.Creator<TvInputInfo> CREATOR =
+            new Parcelable.Creator<TvInputInfo>() {
+        @Override
+        public TvInputInfo createFromParcel(Parcel in) {
+            return new TvInputInfo(in);
+        }
+
+        @Override
+        public TvInputInfo[] newArray(int size) {
+            return new TvInputInfo[size];
+        }
+    };
+
+    private TvInputInfo(Parcel in) {
+        mId = in.readString();
+        mService = ResolveInfo.CREATOR.createFromParcel(in);
+    }
+}
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
new file mode 100644
index 0000000..0b6ab64
--- /dev/null
+++ b/core/java/android/tv/TvInputManager.java
@@ -0,0 +1,392 @@
+/*
+ * 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.tv;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Central system API to the overall TV input framework (TIF) architecture, which arbitrates
+ * interaction between applications and the selected TV inputs.
+ */
+public final class TvInputManager {
+    private static final String TAG = "TvInputManager";
+
+    private final ITvInputManager mService;
+
+    // A mapping from an input to the list of its TvInputListenerRecords.
+    private final Map<ComponentName, List<TvInputListenerRecord>> mTvInputListenerRecordsMap =
+            new HashMap<ComponentName, List<TvInputListenerRecord>>();
+
+    // A mapping from the sequence number of a session to its SessionCreateCallbackRecord.
+    private final SparseArray<SessionCreateCallbackRecord> mSessionCreateCallbackRecordMap =
+            new SparseArray<SessionCreateCallbackRecord>();
+
+    // A sequence number for the next session to be created. Should be protected by a lock
+    // {@code mSessionCreateCallbackRecordMap}.
+    private int mNextSeq;
+
+    private final ITvInputClient mClient;
+
+    private final int mUserId;
+
+    /**
+     * Interface used to receive the created session.
+     */
+    public interface SessionCreateCallback {
+        /**
+         * This is called after {@link TvInputManager#createSession} has been processed.
+         *
+         * @param session A {@link TvInputManager.Session} instance created. This can be
+         *            {@code null} if the creation request failed.
+         */
+        void onSessionCreated(Session session);
+    }
+
+    private static final class SessionCreateCallbackRecord {
+        private final SessionCreateCallback mSessionCreateCallback;
+        private final Handler mHandler;
+
+        public SessionCreateCallbackRecord(SessionCreateCallback sessionCreateCallback,
+                Handler handler) {
+            mSessionCreateCallback = sessionCreateCallback;
+            mHandler = handler;
+        }
+
+        public void postSessionCreated(final Session session) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCreateCallback.onSessionCreated(session);
+                }
+            });
+        }
+    }
+
+    /**
+     * Interface used to monitor status of the TV input.
+     */
+    public abstract static class TvInputListener {
+        /**
+         * This is called when the availability status of a given TV input is changed.
+         *
+         * @param name {@link ComponentName} of {@link android.app.Service} that implements the
+         *            given TV input.
+         * @param isAvailable {@code true} if the given TV input is available to show TV programs.
+         *            {@code false} otherwise.
+         */
+        public void onAvailabilityChanged(ComponentName name, boolean isAvailable) {
+        }
+    }
+
+    private static final class TvInputListenerRecord {
+        private final TvInputListener mListener;
+        private final Handler mHandler;
+
+        public TvInputListenerRecord(TvInputListener listener, Handler handler) {
+            mListener = listener;
+            mHandler = handler;
+        }
+
+        public TvInputListener getListener() {
+            return mListener;
+        }
+
+        public void postAvailabilityChanged(final ComponentName name, final boolean isAvailable) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mListener.onAvailabilityChanged(name, isAvailable);
+                }
+            });
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public TvInputManager(ITvInputManager service, int userId) {
+        mService = service;
+        mUserId = userId;
+        mClient = new ITvInputClient.Stub() {
+            @Override
+            public void onSessionCreated(ComponentName name, IBinder token, int seq) {
+                synchronized (mSessionCreateCallbackRecordMap) {
+                    SessionCreateCallbackRecord record = mSessionCreateCallbackRecordMap.get(seq);
+                    mSessionCreateCallbackRecordMap.delete(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for " + token);
+                        return;
+                    }
+                    Session session = null;
+                    if (token != null) {
+                        session = new Session(name, token, mService, mUserId);
+                    }
+                    record.postSessionCreated(session);
+                }
+            }
+
+            @Override
+            public void onAvailabilityChanged(ComponentName name, boolean isAvailable) {
+                synchronized (mTvInputListenerRecordsMap) {
+                    List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+                    if (records == null) {
+                        // Silently ignore - no listener is registered yet.
+                        return;
+                    }
+                    int recordsCount = records.size();
+                    for (int i = 0; i < recordsCount; i++) {
+                        records.get(i).postAvailabilityChanged(name, isAvailable);
+                    }
+                }
+            }
+        };
+    }
+
+    /**
+     * Returns the complete list of TV inputs on the system.
+     *
+     * @return List of {@link TvInputInfo} for each TV input that describes its meta information.
+     */
+    public List<TvInputInfo> getTvInputList() {
+        try {
+            return mService.getTvInputList(mUserId);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns the availability of a given TV input.
+     *
+     * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
+     *            input.
+     * @throws IllegalArgumentException if the argument is {@code null}.
+     * @throws IllegalStateException If there is no {@link TvInputListener} registered on the given
+     *             TV input.
+     */
+    public boolean getAvailability(ComponentName name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        synchronized (mTvInputListenerRecordsMap) {
+            List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+            if (records == null || records.size() == 0) {
+                throw new IllegalStateException("At least one listener should be registered.");
+            }
+        }
+        try {
+            return mService.getAvailability(mClient, name, mUserId);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Registers a {@link TvInputListener} for a given TV input.
+     *
+     * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
+     *            input.
+     * @param listener a listener used to monitor status of the given TV input.
+     * @param handler a {@link Handler} that the status change will be delivered to.
+     * @throws IllegalArgumentException if any of the arguments is {@code null}.
+     */
+    public void registerListener(ComponentName name, TvInputListener listener, Handler handler) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException("handler cannot be null");
+        }
+        synchronized (mTvInputListenerRecordsMap) {
+            List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+            if (records == null) {
+                records = new ArrayList<TvInputListenerRecord>();
+                mTvInputListenerRecordsMap.put(name, records);
+                try {
+                    mService.registerCallback(mClient, name, mUserId);
+                } catch (RemoteException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            records.add(new TvInputListenerRecord(listener, handler));
+        }
+    }
+
+    /**
+     * Unregisters the existing {@link TvInputListener} for a given TV input.
+     *
+     * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
+     *            input.
+     * @param listener the existing listener to remove for the given TV input.
+     * @throws IllegalArgumentException if any of the arguments is {@code null}.
+     */
+    public void unregisterListener(ComponentName name, final TvInputListener listener) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null");
+        }
+        synchronized (mTvInputListenerRecordsMap) {
+            List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(name);
+            if (records == null) {
+                Log.e(TAG, "No listener found for " + name.getClassName());
+                return;
+            }
+            for (Iterator<TvInputListenerRecord> it = records.iterator(); it.hasNext();) {
+                TvInputListenerRecord record = it.next();
+                if (record.getListener() == listener) {
+                    it.remove();
+                }
+            }
+            if (records.isEmpty()) {
+                try {
+                    mService.unregisterCallback(mClient, name, mUserId);
+                } catch (RemoteException e) {
+                    throw new RuntimeException(e);
+                } finally {
+                    mTvInputListenerRecordsMap.remove(name);
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates a {@link TvInputSession} interface for a given TV input.
+     * <p>
+     * The number of sessions that can be created at the same time is limited by the capability of
+     * the given TV input.
+     * </p>
+     *
+     * @param name {@link ComponentName} of {@link android.app.Service} that implements the given TV
+     *            input.
+     * @param callback a callback used to receive the created session.
+     * @param handler a {@link Handler} that the session creation will be delivered to.
+     * @throws IllegalArgumentException if any of the arguments is {@code null}.
+     */
+    public void createSession(ComponentName name, final SessionCreateCallback callback,
+            Handler handler) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("callback cannot be null");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException("handler cannot be null");
+        }
+        SessionCreateCallbackRecord record = new SessionCreateCallbackRecord(callback, handler);
+        synchronized (mSessionCreateCallbackRecordMap) {
+            int seq = mNextSeq++;
+            mSessionCreateCallbackRecordMap.put(seq, record);
+            try {
+                mService.createSession(mClient, name, seq, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /** The Session provides the per-session functionality of TV inputs. */
+    public static final class Session {
+        private final ITvInputManager mService;
+        private final IBinder mToken;
+        private final int mUserId;
+
+        /** @hide */
+        private Session(ComponentName name, IBinder token, ITvInputManager service, int userId) {
+            mToken = token;
+            mService = service;
+            mUserId = userId;
+        }
+
+        /**
+         * Releases this session.
+         */
+        public void release() {
+            try {
+                mService.releaseSession(mToken, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Sets the {@link android.view.Surface} for this session.
+         *
+         * @param surface A {@link android.view.Surface} used to render video.
+         */
+        public void setSurface(Surface surface) {
+            // surface can be null.
+            try {
+                mService.setSurface(mToken, surface, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Sets the relative volume of this session to handle a change of audio focus.
+         *
+         * @param volume A volume value between 0.0f to 1.0f.
+         * @throws IllegalArgumentException if the volume value is out of range.
+         */
+        public void setVolume(float volume) {
+            try {
+                if (volume < 0.0f || volume > 1.0f) {
+                    throw new IllegalArgumentException("volume should be between 0.0f and 1.0f");
+                }
+                mService.setVolume(mToken, volume, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Tunes to a given channel.
+         *
+         * @param channelUri The URI of a channel.
+         * @throws IllegalArgumentException if the argument is {@code null}.
+         */
+        public void tune(Uri channelUri) {
+            if (channelUri == null) {
+                throw new IllegalArgumentException("channelUri cannot be null");
+            }
+            try {
+                mService.tune(mToken, channelUri, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
new file mode 100644
index 0000000..e43cc95
--- /dev/null
+++ b/core/java/android/tv/TvInputService.java
@@ -0,0 +1,254 @@
+/*
+ * 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.tv;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A base class for implementing television input service.
+ */
+public abstract class TvInputService extends Service {
+    // STOPSHIP: Turn debugging off.
+    private static final boolean DEBUG = true;
+    private static final String TAG = "TvInputService";
+
+    /**
+     * This is the interface name that a service implementing a TV input should say that it support
+     * -- that is, this is the action it uses for its intent filter. To be supported, the service
+     * must also require the {@link android.Manifest.permission#BIND_TV_INPUT} permission so that
+     * other applications cannot abuse it.
+     */
+    public static final String SERVICE_INTERFACE = "android.tv.TvInputService";
+
+    private ComponentName mComponentName;
+    private final Handler mHandler = new ServiceHandler();
+    private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
+            new RemoteCallbackList<ITvInputServiceCallback>();
+    private boolean mAvailable;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mComponentName = new ComponentName(getPackageName(), getClass().getName());
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        return new ITvInputService.Stub() {
+            @Override
+            public void registerCallback(ITvInputServiceCallback cb) {
+                if (cb != null) {
+                    mCallbacks.register(cb);
+                    // The first time a callback is registered, the service needs to report its
+                    // availability status so that the system can know its initial value.
+                    try {
+                        cb.onAvailabilityChanged(mComponentName, mAvailable);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in onAvailabilityChanged", e);
+                    }
+                }
+            }
+
+            @Override
+            public void unregisterCallback(ITvInputServiceCallback cb) {
+                if (cb != null) {
+                    mCallbacks.unregister(cb);
+                }
+            }
+
+            @Override
+            public void createSession(ITvInputSessionCallback cb) {
+                if (cb != null) {
+                    mHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, cb).sendToTarget();
+                }
+            }
+        };
+    }
+
+    /**
+     * Convenience method to notify an availability change of this TV input service.
+     *
+     * @param available {@code true} if the input service is available to show TV programs.
+     */
+    public final void setAvailable(boolean available) {
+        if (available != mAvailable) {
+            mAvailable = available;
+            mHandler.obtainMessage(ServiceHandler.DO_BROADCAST_AVAILABILITY_CHANGE, available)
+                    .sendToTarget();
+        }
+    }
+
+    /**
+     * Get the number of callbacks that are registered.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public final int getRegisteredCallbackCount() {
+        return mCallbacks.getRegisteredCallbackCount();
+    }
+
+    /**
+     * Returns a concrete implementation of {@link TvInputSessionImpl}.
+     * <p>
+     * May return {@code null} if this TV input service fails to create a session for some reason.
+     * </p>
+     */
+    public abstract TvInputSessionImpl onCreateSession();
+
+    /**
+     * Base class for derived classes to implement to provide {@link TvInputSession}.
+     */
+    public abstract static class TvInputSessionImpl {
+        /**
+         * Called when the session is released.
+         */
+        public abstract void onRelease();
+
+        /**
+         * Sets the {@link Surface} for the current input session on which the TV input renders
+         * video.
+         *
+         * @param surface {@link Surface} an application passes to this TV input session.
+         * @return {@code true} if the surface was set, {@code false} otherwise.
+         */
+        public abstract boolean onSetSurface(Surface surface);
+
+        /**
+         * Sets the relative volume of the current TV input session to handle the change of audio
+         * focus by setting.
+         *
+         * @param volume Volume scale from 0.0 to 1.0.
+         */
+        public abstract void onSetVolume(float volume);
+
+        /**
+         * Tunes to a given channel.
+         *
+         * @param channelUri The URI of the channel.
+         * @return {@code true} the tuning was successful, {@code false} otherwise.
+         */
+        public abstract boolean onTune(Uri channelUri);
+    }
+
+    /**
+     * Internal implementation of {@link TvInputSession}. This takes care of basic maintenance of
+     * the TV input session but most behavior must be implemented in {@link TvInputSessionImpl}
+     * returned by {@link TvInputService#onCreateSession}.
+     */
+    private static class TvInputSessionImplInternal extends TvInputSession {
+        private final TvInputSessionImpl mSessionImpl;
+
+        public TvInputSessionImplInternal(TvInputSessionImpl sessionImpl) {
+            mSessionImpl = sessionImpl;
+        }
+
+        /**
+         * This method is called when the application would like to stop using the current input
+         * session.
+         */
+        @Override
+        public final void release() {
+            mSessionImpl.onRelease();
+        }
+
+        /**
+         * Calls {@link TvInputSessionImpl#onSetSurface}.
+         */
+        @Override
+        public final void setSurface(Surface surface) {
+            mSessionImpl.onSetSurface(surface);
+            // TODO: Handle failure.
+        }
+
+        /**
+         * Calls {@link TvInputSessionImpl#onSetVolume}.
+         */
+        @Override
+        public final void setVolume(float volume) {
+            mSessionImpl.onSetVolume(volume);
+        }
+
+        /**
+         * Calls {@link TvInputSessionImpl#onTune}.
+         */
+        @Override
+        public final void tune(Uri channelUri) {
+            mSessionImpl.onTune(channelUri);
+            // TODO: Handle failure.
+        }
+    }
+
+    private final class ServiceHandler extends Handler {
+        private static final int DO_CREATE_SESSION = 1;
+        private static final int DO_BROADCAST_AVAILABILITY_CHANGE = 2;
+
+        @Override
+        public final void handleMessage(Message msg) {
+            switch (msg.what) {
+                case DO_CREATE_SESSION: {
+                    ITvInputSessionCallback cb = (ITvInputSessionCallback) msg.obj;
+                    try {
+                        TvInputSessionImpl sessionImpl = onCreateSession();
+                        if (sessionImpl == null) {
+                            // Failed to create a session.
+                            cb.onSessionCreated(null);
+                            return;
+                        }
+                        ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
+                                new TvInputSessionImplInternal(sessionImpl));
+                        cb.onSessionCreated(stub);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in onSessionCreated");
+                    }
+                    return;
+                }
+                case DO_BROADCAST_AVAILABILITY_CHANGE: {
+                    boolean isAvailable = (Boolean) msg.obj;
+                    int n = mCallbacks.beginBroadcast();
+                    try {
+                        for (int i = 0; i < n; i++) {
+                            mCallbacks.getBroadcastItem(i).onAvailabilityChanged(mComponentName,
+                                    isAvailable);
+                        }
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Unexpected exception", e);
+                    } finally {
+                        mCallbacks.finishBroadcast();
+                    }
+                    return;
+                }
+                default: {
+                    Log.w(TAG, "Unhandled message code: " + msg.what);
+                    return;
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/tv/TvInputSession.java b/core/java/android/tv/TvInputSession.java
new file mode 100644
index 0000000..cdd363b
--- /dev/null
+++ b/core/java/android/tv/TvInputSession.java
@@ -0,0 +1,55 @@
+/*
+ * 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.tv;
+
+import android.net.Uri;
+import android.view.Surface;
+
+/**
+ * The TvInputSession provides the per-session functionality of TvInputService.
+ */
+public abstract class TvInputSession {
+    /**
+     * This method is called when the application would like to stop using the current input
+     * session.
+     */
+    public void release() { }
+
+    /**
+     * Sets the {@link Surface} for the current input session on which the TV input renders video.
+     *
+     * @param surface {@link Surface} to be used for the video playback of this session.
+     */
+    public void setSurface(Surface surface) { }
+
+    /**
+     * This method is called when the application needs to handle the change of audio focus by
+     * setting the relative volume of the current TV input service session.
+     *
+     * @param volume Volume scale from 0.0 to 1.0.
+     */
+    // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
+    // is to introduce some new concepts that will solve a number of problems in audio policy today.
+    public void setVolume(float volume) { }
+
+    /**
+     * Tunes to a given channel.
+     *
+     * @param channelUri The URI of the channel.
+     */
+    public void tune(Uri channelUri) { }
+}
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 0f8da44..13cc88b 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -28,7 +28,12 @@
      *  List accurate as of 2011/07/18.  List taken from:
      *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
      *  This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
+     *
+     *  @deprecated Due to the recent profileration of gTLDs, this API is
+     *  expected to become out-of-date very quickly. Therefore it is now
+     *  deprecated.
      */
+    @Deprecated
     public static final String TOP_LEVEL_DOMAIN_STR =
         "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
         + "|(biz|b[abdefghijmnorstvwyz])"
@@ -59,7 +64,9 @@
 
     /**
      *  Regular expression pattern to match all IANA top-level domains.
+     *  @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}.
      */
+    @Deprecated
     public static final Pattern TOP_LEVEL_DOMAIN =
         Pattern.compile(TOP_LEVEL_DOMAIN_STR);
 
@@ -68,7 +75,10 @@
      *  List accurate as of 2011/07/18.  List taken from:
      *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
      *  This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
+     *
+     *  @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}.
      */
+    @Deprecated
     public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL =
         "(?:"
         + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
@@ -107,6 +117,24 @@
     public static final String GOOD_IRI_CHAR =
         "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
 
+    public static final Pattern IP_ADDRESS
+        = Pattern.compile(
+            "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+            + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+            + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+            + "|[1-9][0-9]|[0-9]))");
+
+    /**
+     * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets.
+     */
+    private static final String IRI
+        = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
+
+    private static final String HOST_NAME = IRI + "(?:\\." + IRI + ")+";
+
+    public static final Pattern DOMAIN_NAME
+        = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
+
     /**
      *  Regular expression pattern to match most part of RFC 3987
      *  Internationalized URLs, aka IRIs.  Commonly used Unicode characters are
@@ -116,13 +144,7 @@
         "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
         + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
         + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
-        + "((?:(?:[" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]{0,64}\\.)+"   // named host
-        + TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL
-        + "|(?:(?:25[0-5]|2[0-4]" // or ip address
-        + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
-        + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
-        + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-        + "|[1-9][0-9]|[0-9])))"
+        + "(?:" + DOMAIN_NAME + ")"
         + "(?:\\:\\d{1,5})?)" // plus option port number
         + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
         + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
@@ -130,19 +152,6 @@
                         // input.  This is to stop foo.sure from
                         // matching as foo.su
 
-    public static final Pattern IP_ADDRESS
-        = Pattern.compile(
-            "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
-            + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
-            + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-            + "|[1-9][0-9]|[0-9]))");
-
-    public static final Pattern DOMAIN_NAME
-        = Pattern.compile(
-            "(((([" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]*)*[" + GOOD_IRI_CHAR + "]\\.)+"
-            + TOP_LEVEL_DOMAIN + ")|"
-            + IP_ADDRESS + ")");
-
     public static final Pattern EMAIL_ADDRESS
         = Pattern.compile(
             "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
@@ -159,7 +168,7 @@
      * might be phone numbers in arbitrary text, not for validating whether
      * something is in fact a phone number.  It will miss many things that
      * are legitimate phone numbers.
-     * 
+     *
      * <p> The pattern matches the following:
      * <ul>
      * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index abae068..477c994 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -52,7 +52,7 @@
  */
 final class AccessibilityInteractionController {
 
-    private static final boolean ENFORCE_NODE_TREE_CONSISTENT = Build.IS_DEBUGGABLE;
+    private static final boolean ENFORCE_NODE_TREE_CONSISTENT = false;
 
     private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
         new ArrayList<AccessibilityNodeInfo>();
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index 90824ab..ad33b6f 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -555,6 +555,32 @@
     }
 
     @Override
+    public void invokeFunctor(long functor, boolean waitForCompletion) {
+        boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
+        boolean hasContext = !needsContext;
+
+        if (needsContext) {
+            GLRendererEglContext managedContext =
+                    (GLRendererEglContext) sEglContextStorage.get();
+            if (managedContext != null) {
+                usePbufferSurface(managedContext.getContext());
+                hasContext = true;
+            }
+        }
+
+        try {
+            nInvokeFunctor(functor, hasContext);
+        } finally {
+            if (needsContext) {
+                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+                        EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            }
+        }
+    }
+
+    private static native void nInvokeFunctor(long functor, boolean hasContext);
+
+    @Override
     void destroyHardwareResources(final View view) {
         if (view != null) {
             safelyRun(new Runnable() {
@@ -1096,8 +1122,7 @@
             }
 
             if (checkRenderContext() != SURFACE_STATE_ERROR) {
-                int status = mCanvas.invokeFunctors(mRedrawClip);
-                handleFunctorStatus(attachInfo, status);
+                mCanvas.invokeFunctors(mRedrawClip);
             }
         }
     }
@@ -1201,9 +1226,14 @@
     }
     private static native void nSetDisplayListData(long displayList, long newData);
 
+    @Override
+    void fence() {
+        // Everything is immediate, so this is a no-op
+    }
+
     private RenderNode buildDisplayList(View view, HardwareCanvas canvas) {
         if (mDrawDelta <= 0) {
-            return view.mDisplayList;
+            return view.mRenderNode;
         }
 
         view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
@@ -1214,12 +1244,12 @@
         canvas.clearLayerUpdates();
 
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
-        RenderNode displayList = view.getDisplayList();
+        RenderNode renderNode = view.getDisplayList();
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
 
         endBuildDisplayListProfiling(buildDisplayListStartTime);
 
-        return displayList;
+        return renderNode;
     }
 
     private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) {
@@ -1301,7 +1331,6 @@
             mProfileData[mProfileCurrentFrame + 1] = total;
         }
 
-        handleFunctorStatus(attachInfo, status);
         return status;
     }
 
@@ -1337,26 +1366,6 @@
         }
     }
 
-    private void handleFunctorStatus(View.AttachInfo attachInfo, int status) {
-        // If the draw flag is set, functors will be invoked while executing
-        // the tree of display lists
-        if ((status & RenderNode.STATUS_DRAW) != 0) {
-            if (mRedrawClip.isEmpty()) {
-                attachInfo.mViewRootImpl.invalidate();
-            } else {
-                attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip);
-                mRedrawClip.setEmpty();
-            }
-        }
-
-        if ((status & RenderNode.STATUS_INVOKE) != 0 ||
-                attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
-            attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
-            mFunctorsRunnable.attachInfo = attachInfo;
-            attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
-        }
-    }
-
     @Override
     void detachFunctor(long functor) {
         if (mCanvas != null) {
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index f695b20..233f846 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -23,7 +23,7 @@
 
 /**
  * Hardware accelerated canvas.
- * 
+ *
  * @hide
  */
 public abstract class HardwareCanvas extends Canvas {
@@ -40,7 +40,7 @@
 
     /**
      * Invoked before any drawing operation is performed in this canvas.
-     * 
+     *
      * @param dirty The dirty rectangle to update, can be null.
      * @return {@link RenderNode#STATUS_DREW} if anything was drawn (such as a call to clear
      *         the canvas).
@@ -70,13 +70,11 @@
      * Draws the specified display list onto this canvas.
      *
      * @param displayList The display list to replay.
-     * @param dirty The dirty region to redraw in the next pass, matters only
-     *        if this method returns {@link RenderNode#STATUS_DRAW}, can be null.
+     * @param dirty Ignored, can be null.
      * @param flags Optional flags about drawing, see {@link RenderNode} for
      *              the possible flags.
      *
-     * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW}, or
-     *         {@link RenderNode#STATUS_INVOKE}, or'd with {@link RenderNode#STATUS_DREW}
+     * @return One of {@link RenderNode#STATUS_DONE} or {@link RenderNode#STATUS_DREW}
      *         if anything was drawn.
      *
      * @hide
@@ -101,9 +99,8 @@
      * This function may return true if an invalidation is needed after the call.
      *
      * @param drawGLFunction A native function pointer
-     *                       
-     * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW} or
-     *         {@link RenderNode#STATUS_INVOKE}
+     *
+     * @return {@link RenderNode#STATUS_DONE}
      *
      * @hide
      */
@@ -114,11 +111,10 @@
 
     /**
      * Invoke all the functors who requested to be invoked during the previous frame.
-     * 
-     * @param dirty The region to redraw when the functors return {@link RenderNode#STATUS_DRAW}
-     *              
-     * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW} or
-     *         {@link RenderNode#STATUS_INVOKE}
+     *
+     * @param dirty Ignored
+     *
+     * @return Ignored
      *
      * @hide
      */
@@ -154,7 +150,7 @@
 
     /**
      * Indicates that the specified layer must be updated as soon as possible.
-     * 
+     *
      * @param layer The layer to update
      *
      * @see #clearLayerUpdates()
@@ -187,7 +183,7 @@
 
     /**
      * Removes all enqueued layer updates.
-     * 
+     *
      * @see #pushLayerUpdate(HardwareLayer)
      *
      * @hide
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 34efcf5..92d85d1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -182,7 +182,7 @@
     public static boolean sSystemRendererDisabled = false;
 
     /** @hide */
-    public static boolean sUseRenderThread = false;
+    public static boolean sUseRenderThread = true;
 
     private boolean mEnabled;
     private boolean mRequested = true;
@@ -438,6 +438,17 @@
     abstract void attachFunctor(View.AttachInfo attachInfo, long functor);
 
     /**
+     * Schedules the functor for execution in either kModeProcess or
+     * kModeProcessNoContext, depending on whether or not there is an EGLContext.
+     *
+     * @param functor The native functor to invoke
+     * @param waitForCompletion If true, this will not return until the functor
+     *                          has invoked. If false, the functor may be invoked
+     *                          asynchronously.
+     */
+    public abstract void invokeFunctor(long functor, boolean waitForCompletion);
+
+    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -565,6 +576,11 @@
     abstract void setDisplayListData(long displayList, long newData);
 
     /**
+     * Blocks until all previously queued work has completed.
+     */
+    abstract void fence();
+
+    /**
      * Describes a series of frames that should be drawn on screen as a graph.
      * Each frame is composed of 1 or more elements.
      */
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 0b12cbe..ae5f37e 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -579,6 +579,18 @@
     }
 
     /**
+     * Determines whether the input device supports the given source or sources.
+     *
+     * @param source The input source or sources to check against. This can be a generic device
+     * type such as {@link InputDevice#SOURCE_MOUSE}, a more generic device class, such as
+     * {@link InputDevice#SOURCE_CLASS_POINTER}, or a combination of sources bitwise ORed together.
+     * @return Whether the device can produce all of the given sources.
+     */
+    public boolean supportsSource(int source) {
+        return (mSources & source) == source;
+    }
+
+    /**
      * Gets the keyboard type.
      * @return The keyboard type.
      */
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index c4fac46..e19bda9 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -590,6 +590,7 @@
             Object[] args = mConstructorArgs;
             args[1] = attrs;
 
+            constructor.setAccessible(true);
             final View view = constructor.newInstance(args);
             if (view instanceof ViewStub) {
                 // always use ourselves when inflating ViewStub later
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 6c8c3c7..78ddf5b 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.graphics.Matrix;
 import android.graphics.Outline;
 
@@ -196,18 +197,20 @@
     }
 
     /**
-     * Starts recording the display list. All operations performed on the
-     * returned canvas are recorded and stored in this display list.
+     * Starts recording a display list for the render node. All
+     * operations performed on the returned canvas are recorded and
+     * stored in this display list.
      *
-     * Calling this method will mark the display list invalid until
-     * {@link #end()} is called. Only valid display lists can be replayed.
+     * Calling this method will mark the render node invalid until
+     * {@link #end(HardwareRenderer, HardwareCanvas)} is called.
+     * Only valid render nodes can be replayed.
      *
-     * @param width The width of the display list's viewport
-     * @param height The height of the display list's viewport
+     * @param width The width of the recording viewport
+     * @param height The height of the recording viewport
      *
      * @return A canvas to record drawing operations.
      *
-     * @see #end()
+     * @see #end(HardwareRenderer, HardwareCanvas)
      * @see #isValid()
      */
     public HardwareCanvas start(int width, int height) {
@@ -269,8 +272,8 @@
     }
 
     /**
-     * Returns whether the display list is currently usable. If this returns false,
-     * the display list should be re-recorded prior to replaying it.
+     * Returns whether the RenderNode's display list content is currently usable.
+     * If this returns false, the display list should be re-recorded prior to replaying it.
      *
      * @return boolean true if the display list is able to be replayed, false otherwise.
      */
@@ -284,7 +287,23 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    // DisplayList Property Setters
+    // Matrix manipulation
+    ///////////////////////////////////////////////////////////////////////////
+
+    public boolean hasIdentityMatrix() {
+        return nHasIdentityMatrix(mNativeDisplayList);
+    }
+
+    public void getMatrix(@NonNull Matrix outMatrix) {
+        nGetTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+    }
+
+    public void getInverseMatrix(@NonNull Matrix outMatrix) {
+        nGetInverseTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // RenderProperty Setters
     ///////////////////////////////////////////////////////////////////////////
 
     /**
@@ -301,7 +320,7 @@
     }
 
     /**
-     * Set whether the display list should clip itself to its bounds. This property is controlled by
+     * Set whether the Render node should clip itself to its bounds. This property is controlled by
      * the view's parent.
      *
      * @param clipToBounds true if the display list should clip to its bounds
@@ -312,9 +331,7 @@
 
     /**
      * Sets whether the display list should be drawn immediately after the
-     * closest ancestor display list where isolateZVolume is true. If the
-     * display list itself satisfies this constraint, changing this attribute
-     * has no effect on drawing order.
+     * closest ancestor display list containing a projection receiver.
      *
      * @param shouldProject true if the display list should be projected onto a
      *            containing volume.
@@ -373,9 +390,6 @@
      * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
      *
      * @param matrix A transform matrix to apply to this display list
-     *
-     * @see #getMatrix(android.graphics.Matrix)
-     * @see #getMatrix()
      */
     public void setStaticMatrix(Matrix matrix) {
         nSetStaticMatrix(mNativeDisplayList, matrix.native_instance);
@@ -613,28 +627,6 @@
     }
 
     /**
-     * Sets all of the transform-related values of the display list
-     *
-     * @param alpha The alpha value of the display list
-     * @param translationX The translationX value of the display list
-     * @param translationY The translationY value of the display list
-     * @param rotation The rotation value of the display list
-     * @param rotationX The rotationX value of the display list
-     * @param rotationY The rotationY value of the display list
-     * @param scaleX The scaleX value of the display list
-     * @param scaleY The scaleY value of the display list
-     *
-     * @hide
-     */
-    public void setTransformationInfo(float alpha,
-            float translationX, float translationY, float translationZ,
-            float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
-        nSetTransformationInfo(mNativeDisplayList, alpha,
-                translationX, translationY, translationZ,
-                rotation, rotationX, rotationY, scaleX, scaleY);
-    }
-
-    /**
      * Sets the pivot value for the display list on the X axis
      *
      * @param pivotX The pivot value of the display list on the X axis, in pixels
@@ -676,6 +668,10 @@
         return nGetPivotY(mNativeDisplayList);
     }
 
+    public boolean isPivotExplicitlySet() {
+        return nIsPivotExplicitlySet(mNativeDisplayList);
+    }
+
     /**
      * Sets the camera distance for the display list. Refer to
      * {@link View#setCameraDistance(float)} for more information on how to
@@ -842,6 +838,12 @@
     private static native void nDestroyDisplayList(long displayList);
     private static native void nSetDisplayListName(long displayList, String name);
 
+    // Matrix
+
+    private static native void nGetTransformMatrix(long displayList, long nativeMatrix);
+    private static native void nGetInverseTransformMatrix(long displayList, long nativeMatrix);
+    private static native boolean nHasIdentityMatrix(long displayList);
+
     // Properties
 
     private static native void nOffsetTopAndBottom(long displayList, float offset);
@@ -877,9 +879,6 @@
     private static native void nSetRotationY(long displayList, float rotationY);
     private static native void nSetScaleX(long displayList, float scaleX);
     private static native void nSetScaleY(long displayList, float scaleY);
-    private static native void nSetTransformationInfo(long displayList, float alpha,
-            float translationX, float translationY, float translationZ,
-            float rotation, float rotationX, float rotationY, float scaleX, float scaleY);
     private static native void nSetStaticMatrix(long displayList, long nativeMatrix);
     private static native void nSetAnimationMatrix(long displayList, long animationMatrix);
 
@@ -898,6 +897,7 @@
     private static native float nGetRotation(long displayList);
     private static native float nGetRotationX(long displayList);
     private static native float nGetRotationY(long displayList);
+    private static native boolean nIsPivotExplicitlySet(long displayList);
     private static native float nGetPivotX(long displayList);
     private static native float nGetPivotY(long displayList);
     private static native void nOutput(long displayList);
@@ -909,7 +909,6 @@
     @Override
     protected void finalize() throws Throwable {
         try {
-            destroyDisplayListData();
             nDestroyDisplayList(mNativeDisplayList);
         } finally {
             super.finalize();
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2a488a0..a747ab6 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -186,6 +186,11 @@
     }
 
     @Override
+    public void invokeFunctor(long functor, boolean waitForCompletion) {
+        nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
+    }
+
+    @Override
     HardwareLayer createDisplayListLayer(int width, int height) {
         long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
         return HardwareLayer.adoptDisplayListLayer(this, layer);
@@ -240,9 +245,15 @@
     }
 
     @Override
+    void fence() {
+        nFence(mNativeProxy);
+    }
+
+    @Override
     protected void finalize() throws Throwable {
         try {
             nDeleteProxy(mNativeProxy);
+            mNativeProxy = 0;
         } finally {
             super.finalize();
         }
@@ -266,9 +277,12 @@
 
     private static native void nAttachFunctor(long nativeProxy, long functor);
     private static native void nDetachFunctor(long nativeProxy, long functor);
+    private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
 
     private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
     private static native long nCreateTextureLayer(long nativeProxy);
     private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
     private static native void nDestroyLayer(long nativeProxy, long layer);
+
+    private static native void nFence(long nativeProxy);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2b9b96..6c414f6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.animation.RevealAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1790,12 +1792,9 @@
     private static final int PFLAG_HOVERED             = 0x10000000;
 
     /**
-     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
-     * for transform operations
-     *
-     * @hide
+     * no longer needed, should be reused
      */
-    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
+    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
 
     /** {@hide} */
     static final int PFLAG_ACTIVATED                   = 0x40000000;
@@ -2928,123 +2927,23 @@
     static class TransformationInfo {
         /**
          * The transform matrix for the View. This transform is calculated internally
-         * based on the rotation, scaleX, and scaleY properties. The identity matrix
-         * is used by default. Do *not* use this variable directly; instead call
-         * getMatrix(), which will automatically recalculate the matrix if necessary
-         * to get the correct matrix based on the latest rotation and scale properties.
+         * based on the translation, rotation, and scale properties.
+         *
+         * Do *not* use this variable directly; instead call getMatrix(), which will
+         * load the value from the View's RenderNode.
          */
         private final Matrix mMatrix = new Matrix();
 
         /**
-         * The transform matrix for the View. This transform is calculated internally
-         * based on the rotation, scaleX, and scaleY properties. The identity matrix
-         * is used by default. Do *not* use this variable directly; instead call
-         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
-         * to get the correct matrix based on the latest rotation and scale properties.
+         * The inverse transform matrix for the View. This transform is calculated
+         * internally based on the translation, rotation, and scale properties.
+         *
+         * Do *not* use this variable directly; instead call getInverseMatrix(),
+         * which will load the value from the View's RenderNode.
          */
         private Matrix mInverseMatrix;
 
         /**
-         * An internal variable that tracks whether we need to recalculate the
-         * transform matrix, based on whether the rotation or scaleX/Y properties
-         * have changed since the matrix was last calculated.
-         */
-        boolean mMatrixDirty = false;
-
-        /**
-         * An internal variable that tracks whether we need to recalculate the
-         * transform matrix, based on whether the rotation or scaleX/Y properties
-         * have changed since the matrix was last calculated.
-         */
-        private boolean mInverseMatrixDirty = true;
-
-        /**
-         * A variable that tracks whether we need to recalculate the
-         * transform matrix, based on whether the rotation or scaleX/Y properties
-         * have changed since the matrix was last calculated. This variable
-         * is only valid after a call to updateMatrix() or to a function that
-         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
-         */
-        private boolean mMatrixIsIdentity = true;
-
-        /**
-         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
-         */
-        private Camera mCamera = null;
-
-        /**
-         * This matrix is used when computing the matrix for 3D rotations.
-         */
-        private Matrix matrix3D = null;
-
-        /**
-         * These prev values are used to recalculate a centered pivot point when necessary. The
-         * pivot point is only used in matrix operations (when rotation, scale, or translation are
-         * set), so thes values are only used then as well.
-         */
-        private int mPrevWidth = -1;
-        private int mPrevHeight = -1;
-
-        /**
-         * The degrees rotation around the vertical axis through the pivot point.
-         */
-        @ViewDebug.ExportedProperty
-        float mRotationY = 0f;
-
-        /**
-         * The degrees rotation around the horizontal axis through the pivot point.
-         */
-        @ViewDebug.ExportedProperty
-        float mRotationX = 0f;
-
-        /**
-         * The degrees rotation around the pivot point.
-         */
-        @ViewDebug.ExportedProperty
-        float mRotation = 0f;
-
-        /**
-         * The amount of translation of the object away from its left property (post-layout).
-         */
-        @ViewDebug.ExportedProperty
-        float mTranslationX = 0f;
-
-        /**
-         * The amount of translation of the object away from its top property (post-layout).
-         */
-        @ViewDebug.ExportedProperty
-        float mTranslationY = 0f;
-
-        @ViewDebug.ExportedProperty
-        float mTranslationZ = 0f;
-
-        /**
-         * The amount of scale in the x direction around the pivot point. A
-         * value of 1 means no scaling is applied.
-         */
-        @ViewDebug.ExportedProperty
-        float mScaleX = 1f;
-
-        /**
-         * The amount of scale in the y direction around the pivot point. A
-         * value of 1 means no scaling is applied.
-         */
-        @ViewDebug.ExportedProperty
-        float mScaleY = 1f;
-
-        /**
-         * The x location of the point around which the view is rotated and scaled.
-         */
-        @ViewDebug.ExportedProperty
-        float mPivotX = 0f;
-
-        /**
-         * The y location of the point around which the view is rotated and scaled.
-         */
-        @ViewDebug.ExportedProperty
-        float mPivotY = 0f;
-
-        /**
          * The opacity of the View. This is a value from 0 to 1, where 0 means
          * completely transparent and 1 means completely opaque.
          */
@@ -3549,13 +3448,13 @@
     private Bitmap mUnscaledDrawingCache;
 
     /**
-     * Display list used for the View content.
+     * RenderNode holding View properties, potentially holding a DisplayList of View content.
      * <p>
      * When non-null and valid, this is expected to contain an up-to-date copy
-     * of the View content. It is cleared on temporary detach and reset on
+     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
      * cleanup.
      */
-    RenderNode mDisplayList;
+    final RenderNode mRenderNode;
 
     /**
      * Set to true when the view is sending hover accessibility events because it
@@ -3606,6 +3505,7 @@
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = UNDEFINED_PADDING;
         mUserPaddingEnd = UNDEFINED_PADDING;
+        mRenderNode = RenderNode.create(getClass().getName());
 
         if (!sCompatibilityDone && context != null) {
             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -4170,6 +4070,7 @@
      */
     View() {
         mResources = null;
+        mRenderNode = RenderNode.create(getClass().getName());
     }
 
     public String toString() {
@@ -4845,10 +4746,10 @@
 
             final float x = r.exactCenterX();
             final float y = r.exactCenterY();
-            mBackground.setHotspot(Drawable.HOTSPOT_FOCUS, x, y);
+            mBackground.setHotspot(R.attr.state_focused, x, y);
 
             if (!focused) {
-                mBackground.removeHotspot(Drawable.HOTSPOT_FOCUS);
+                mBackground.removeHotspot(R.attr.state_focused);
             }
         }
     }
@@ -9016,10 +8917,13 @@
      * @return True if the event was handled, false otherwise.
      */
     public boolean onTouchEvent(MotionEvent event) {
+        final float x = event.getX();
+        final float y = event.getY();
         final int viewFlags = mViewFlags;
 
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
+                clearHotspot(R.attr.state_pressed);
                 setPressed(false);
             }
             // A disabled view that is clickable still consumes the touch
@@ -9052,6 +8956,7 @@
                             // showed it as pressed.  Make it show the pressed
                             // state now (before scheduling the click) to ensure
                             // the user sees it.
+                            setHotspot(R.attr.state_pressed, x, y);
                             setPressed(true);
                        }
 
@@ -9084,7 +8989,10 @@
                             // If the post failed, unpress right now
                             mUnsetPressedState.run();
                         }
+
                         removeTapCallback();
+                    } else {
+                        clearHotspot(R.attr.state_pressed);
                     }
                     break;
 
@@ -9105,23 +9013,26 @@
                         if (mPendingCheckForTap == null) {
                             mPendingCheckForTap = new CheckForTap();
                         }
+                        mPendingCheckForTap.x = event.getX();
+                        mPendingCheckForTap.y = event.getY();
                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                     } else {
                         // Not inside a scrolling container, so show the feedback right away
+                        setHotspot(R.attr.state_pressed, x, y);
                         setPressed(true);
                         checkForLongClick(0);
                     }
                     break;
 
                 case MotionEvent.ACTION_CANCEL:
+                    clearHotspot(R.attr.state_pressed);
                     setPressed(false);
                     removeTapCallback();
                     removeLongPressCallback();
                     break;
 
                 case MotionEvent.ACTION_MOVE:
-                    final int x = (int) event.getX();
-                    final int y = (int) event.getY();
+                    setHotspot(R.attr.state_pressed, x, y);
 
                     // Be lenient about moving outside of buttons
                     if (!pointInView(x, y, mTouchSlop)) {
@@ -9137,46 +9048,24 @@
                     break;
             }
 
-            if (mBackground != null && mBackground.supportsHotspots()) {
-                manageTouchHotspot(event);
-            }
-
             return true;
         }
 
         return false;
     }
 
-    private void manageTouchHotspot(MotionEvent event) {
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-            case MotionEvent.ACTION_POINTER_DOWN: {
-                final int index = event.getActionIndex();
-                setPointerHotspot(event, index);
-            } break;
-            case MotionEvent.ACTION_MOVE: {
-                final int count = event.getPointerCount();
-                for (int index = 0; index < count; index++) {
-                    setPointerHotspot(event, index);
-                }
-            } break;
-            case MotionEvent.ACTION_POINTER_UP: {
-                final int actionIndex = event.getActionIndex();
-                final int pointerId = event.getPointerId(actionIndex);
-                mBackground.removeHotspot(pointerId);
-            } break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mBackground.clearHotspots();
-                break;
+    private void setHotspot(int id, float x, float y) {
+        final Drawable bg = mBackground;
+        if (bg != null && bg.supportsHotspots()) {
+            bg.setHotspot(id, x, y);
         }
     }
 
-    private void setPointerHotspot(MotionEvent event, int index) {
-        final int id = event.getPointerId(index);
-        final float x = event.getX(index);
-        final float y = event.getY(index);
-        mBackground.setHotspot(id, x, y);
+    private void clearHotspot(int id) {
+        final Drawable bg = mBackground;
+        if (bg != null && bg.supportsHotspots()) {
+            bg.removeHotspot(id);
+        }
     }
 
     /**
@@ -9216,6 +9105,7 @@
      */
     private void removeUnsetPressCallback() {
         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
+            clearHotspot(R.attr.state_pressed);
             setPressed(false);
             removeCallbacks(mUnsetPressedState);
         }
@@ -9694,21 +9584,10 @@
      * @return The current transform matrix for the view
      */
     public Matrix getMatrix() {
-        if (mTransformationInfo != null) {
-            updateMatrix();
-            return mTransformationInfo.mMatrix;
-        }
-        return Matrix.IDENTITY_MATRIX;
-    }
-
-    /**
-     * Utility function to determine if the value is far enough away from zero to be
-     * considered non-zero.
-     * @param value A floating point value to check for zero-ness
-     * @return whether the passed-in value is far enough away from zero to be considered non-zero
-     */
-    private static boolean nonzero(float value) {
-        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
+        ensureTransformationInfo();
+        final Matrix matrix = mTransformationInfo.mMatrix;
+        mRenderNode.getMatrix(matrix);
+        return matrix;
     }
 
     /**
@@ -9718,11 +9597,7 @@
      * @return True if the transform matrix is the identity matrix, false otherwise.
      */
     final boolean hasIdentityMatrix() {
-        if (mTransformationInfo != null) {
-            updateMatrix();
-            return mTransformationInfo.mMatrixIsIdentity;
-        }
-        return true;
+        return mRenderNode.hasIdentityMatrix();
     }
 
     void ensureTransformationInfo() {
@@ -9731,53 +9606,6 @@
         }
     }
 
-    /**
-     * Recomputes the transform matrix if necessary.
-     */
-    private void updateMatrix() {
-        final TransformationInfo info = mTransformationInfo;
-        if (info == null) {
-            return;
-        }
-        if (info.mMatrixDirty) {
-            // transform-related properties have changed since the last time someone
-            // asked for the matrix; recalculate it with the current values
-
-            // Figure out if we need to update the pivot point
-            if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
-                    info.mPrevWidth = mRight - mLeft;
-                    info.mPrevHeight = mBottom - mTop;
-                    info.mPivotX = info.mPrevWidth / 2f;
-                    info.mPivotY = info.mPrevHeight / 2f;
-                }
-            }
-            info.mMatrix.reset();
-            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
-                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
-                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
-                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
-            } else {
-                if (info.mCamera == null) {
-                    info.mCamera = new Camera();
-                    info.matrix3D = new Matrix();
-                }
-                info.mCamera.save();
-                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
-                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
-                info.mCamera.getMatrix(info.matrix3D);
-                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
-                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
-                        info.mPivotY + info.mTranslationY);
-                info.mMatrix.postConcat(info.matrix3D);
-                info.mCamera.restore();
-            }
-            info.mMatrixDirty = false;
-            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
-            info.mInverseMatrixDirty = true;
-        }
-    }
-
    /**
      * Utility method to retrieve the inverse of the current mMatrix property.
      * We cache the matrix to avoid recalculating it when transform properties
@@ -9786,19 +9614,13 @@
      * @return The inverse of the current matrix of this view.
      */
     final Matrix getInverseMatrix() {
-        final TransformationInfo info = mTransformationInfo;
-        if (info != null) {
-            updateMatrix();
-            if (info.mInverseMatrixDirty) {
-                if (info.mInverseMatrix == null) {
-                    info.mInverseMatrix = new Matrix();
-                }
-                info.mMatrix.invert(info.mInverseMatrix);
-                info.mInverseMatrixDirty = false;
-            }
-            return info.mInverseMatrix;
+        ensureTransformationInfo();
+        if (mTransformationInfo.mInverseMatrix == null) {
+            mTransformationInfo.mInverseMatrix = new Matrix();
         }
-        return Matrix.IDENTITY_MATRIX;
+        final Matrix matrix = mTransformationInfo.mInverseMatrix;
+        mRenderNode.getInverseMatrix(matrix);
+        return matrix;
     }
 
     /**
@@ -9809,14 +9631,8 @@
      * @return The distance along the Z axis.
      */
     public float getCameraDistance() {
-        ensureTransformationInfo();
         final float dpi = mResources.getDisplayMetrics().densityDpi;
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mCamera == null) {
-            info.mCamera = new Camera();
-            info.matrix3D = new Matrix();
-        }
-        return -(info.mCamera.getLocationZ() * dpi);
+        return -(mRenderNode.getCameraDistance() * dpi);
     }
 
     /**
@@ -9859,27 +9675,13 @@
      * @see #setRotationY(float)
      */
     public void setCameraDistance(float distance) {
-        invalidateViewProperty(true, false);
-
-        ensureTransformationInfo();
         final float dpi = mResources.getDisplayMetrics().densityDpi;
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mCamera == null) {
-            info.mCamera = new Camera();
-            info.matrix3D = new Matrix();
-        }
 
-        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
-        info.mMatrixDirty = true;
-
+        invalidateViewProperty(true, false);
+        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
         invalidateViewProperty(false, false);
-        if (mDisplayList != null) {
-            mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
-        }
-        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-            // View was rejected last time it was drawn by its parent; this may have changed
-            invalidateParentIfNeeded();
-        }
+
+        invalidateParentIfNeededAndWasQuickRejected();
     }
 
     /**
@@ -9893,7 +9695,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotation() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
+        return mRenderNode.getRotation();
     }
 
     /**
@@ -9911,21 +9713,13 @@
      * @attr ref android.R.styleable#View_rotation
      */
     public void setRotation(float rotation) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mRotation != rotation) {
+        if (rotation != getRotation()) {
             // Double-invalidation is necessary to capture view's old and new areas
             invalidateViewProperty(true, false);
-            info.mRotation = rotation;
-            info.mMatrixDirty = true;
+            mRenderNode.setRotation(rotation);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setRotation(rotation);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -9940,7 +9734,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotationY() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
+        return mRenderNode.getRotationY();
     }
 
     /**
@@ -9963,20 +9757,12 @@
      * @attr ref android.R.styleable#View_rotationY
      */
     public void setRotationY(float rotationY) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mRotationY != rotationY) {
+        if (rotationY != getRotationY()) {
             invalidateViewProperty(true, false);
-            info.mRotationY = rotationY;
-            info.mMatrixDirty = true;
+            mRenderNode.setRotationY(rotationY);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setRotationY(rotationY);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -9991,7 +9777,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getRotationX() {
-        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
+        return mRenderNode.getRotationX();
     }
 
     /**
@@ -10014,20 +9800,12 @@
      * @attr ref android.R.styleable#View_rotationX
      */
     public void setRotationX(float rotationX) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mRotationX != rotationX) {
+        if (rotationX != getRotationX()) {
             invalidateViewProperty(true, false);
-            info.mRotationX = rotationX;
-            info.mMatrixDirty = true;
+            mRenderNode.setRotationX(rotationX);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setRotationX(rotationX);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10043,7 +9821,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getScaleX() {
-        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
+        return mRenderNode.getScaleX();
     }
 
     /**
@@ -10057,20 +9835,12 @@
      * @attr ref android.R.styleable#View_scaleX
      */
     public void setScaleX(float scaleX) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mScaleX != scaleX) {
+        if (scaleX != getScaleX()) {
             invalidateViewProperty(true, false);
-            info.mScaleX = scaleX;
-            info.mMatrixDirty = true;
+            mRenderNode.setScaleX(scaleX);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setScaleX(scaleX);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10086,7 +9856,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getScaleY() {
-        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
+        return mRenderNode.getScaleY();
     }
 
     /**
@@ -10100,20 +9870,12 @@
      * @attr ref android.R.styleable#View_scaleY
      */
     public void setScaleY(float scaleY) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mScaleY != scaleY) {
+        if (scaleY != getScaleY()) {
             invalidateViewProperty(true, false);
-            info.mScaleY = scaleY;
-            info.mMatrixDirty = true;
+            mRenderNode.setScaleY(scaleY);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setScaleY(scaleY);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10131,7 +9893,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotX() {
-        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
+        return mRenderNode.getPivotX();
     }
 
     /**
@@ -10150,23 +9912,12 @@
      * @attr ref android.R.styleable#View_transformPivotX
      */
     public void setPivotX(float pivotX) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
-                PFLAG_PIVOT_EXPLICITLY_SET;
-        if (info.mPivotX != pivotX || !pivotSet) {
-            mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
+        if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
             invalidateViewProperty(true, false);
-            info.mPivotX = pivotX;
-            info.mMatrixDirty = true;
+            mRenderNode.setPivotX(pivotX);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setPivotX(pivotX);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10184,7 +9935,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotY() {
-        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
+        return mRenderNode.getPivotY();
     }
 
     /**
@@ -10202,23 +9953,12 @@
      * @attr ref android.R.styleable#View_transformPivotY
      */
     public void setPivotY(float pivotY) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
-                PFLAG_PIVOT_EXPLICITLY_SET;
-        if (info.mPivotY != pivotY || !pivotSet) {
-            mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
+        if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
             invalidateViewProperty(true, false);
-            info.mPivotY = pivotY;
-            info.mMatrixDirty = true;
+            mRenderNode.setPivotY(pivotY);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setPivotY(pivotY);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10296,9 +10036,7 @@
             } else {
                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
                 invalidateViewProperty(true, false);
-                if (mDisplayList != null) {
-                    mDisplayList.setAlpha(getFinalAlpha());
-                }
+                mRenderNode.setAlpha(getFinalAlpha());
             }
         }
     }
@@ -10323,9 +10061,7 @@
                 return true;
             } else {
                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
-                if (mDisplayList != null) {
-                    mDisplayList.setAlpha(getFinalAlpha());
-                }
+                mRenderNode.setAlpha(getFinalAlpha());
             }
         }
         return false;
@@ -10346,9 +10082,7 @@
             mTransformationInfo.mTransitionAlpha = alpha;
             mPrivateFlags &= ~PFLAG_ALPHA_SET;
             invalidateViewProperty(true, false);
-            if (mDisplayList != null) {
-                mDisplayList.setAlpha(getFinalAlpha());
-            }
+            mRenderNode.setAlpha(getFinalAlpha());
         }
     }
 
@@ -10395,9 +10129,7 @@
      */
     public final void setTop(int top) {
         if (top != mTop) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (mAttachInfo != null) {
                     int minTop;
@@ -10420,17 +10152,11 @@
             int oldHeight = mBottom - mTop;
 
             mTop = top;
-            if (mDisplayList != null) {
-                mDisplayList.setTop(mTop);
-            }
+            mRenderNode.setTop(mTop);
 
             sizeChange(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                    // A change in dimension means an auto-centered pivot point changes, too
-                    mTransformationInfo.mMatrixDirty = true;
-                }
                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
@@ -10471,9 +10197,7 @@
      */
     public final void setBottom(int bottom) {
         if (bottom != mBottom) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (mAttachInfo != null) {
                     int maxBottom;
@@ -10493,17 +10217,11 @@
             int oldHeight = mBottom - mTop;
 
             mBottom = bottom;
-            if (mDisplayList != null) {
-                mDisplayList.setBottom(mBottom);
-            }
+            mRenderNode.setBottom(mBottom);
 
             sizeChange(width, mBottom - mTop, width, oldHeight);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                    // A change in dimension means an auto-centered pivot point changes, too
-                    mTransformationInfo.mMatrixDirty = true;
-                }
                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
@@ -10535,9 +10253,7 @@
      */
     public final void setLeft(int left) {
         if (left != mLeft) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (mAttachInfo != null) {
                     int minLeft;
@@ -10560,17 +10276,11 @@
             int height = mBottom - mTop;
 
             mLeft = left;
-            if (mDisplayList != null) {
-                mDisplayList.setLeft(left);
-            }
+            mRenderNode.setLeft(left);
 
             sizeChange(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                    // A change in dimension means an auto-centered pivot point changes, too
-                    mTransformationInfo.mMatrixDirty = true;
-                }
                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
@@ -10602,9 +10312,7 @@
      */
     public final void setRight(int right) {
         if (right != mRight) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (mAttachInfo != null) {
                     int maxRight;
@@ -10624,17 +10332,11 @@
             int height = mBottom - mTop;
 
             mRight = right;
-            if (mDisplayList != null) {
-                mDisplayList.setRight(mRight);
-            }
+            mRenderNode.setRight(mRight);
 
             sizeChange(mRight - mLeft, height, oldWidth, height);
 
             if (!matrixIsIdentity) {
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                    // A change in dimension means an auto-centered pivot point changes, too
-                    mTransformationInfo.mMatrixDirty = true;
-                }
                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
                 invalidate(true);
             }
@@ -10656,7 +10358,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getX() {
-        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
+        return mLeft + getTranslationX();
     }
 
     /**
@@ -10679,7 +10381,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getY() {
-        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
+        return mTop + getTranslationY();
     }
 
     /**
@@ -10703,7 +10405,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationX() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
+        return mRenderNode.getTranslationX();
     }
 
     /**
@@ -10717,21 +10419,12 @@
      * @attr ref android.R.styleable#View_translationX
      */
     public void setTranslationX(float translationX) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mTranslationX != translationX) {
-            // Double-invalidation is necessary to capture view's old and new areas
+        if (translationX != getTranslationX()) {
             invalidateViewProperty(true, false);
-            info.mTranslationX = translationX;
-            info.mMatrixDirty = true;
+            mRenderNode.setTranslationX(translationX);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setTranslationX(translationX);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10745,7 +10438,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationY() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
+        return mRenderNode.getTranslationY();
     }
 
     /**
@@ -10759,20 +10452,12 @@
      * @attr ref android.R.styleable#View_translationY
      */
     public void setTranslationY(float translationY) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mTranslationY != translationY) {
+        if (translationY != getTranslationY()) {
             invalidateViewProperty(true, false);
-            info.mTranslationY = translationY;
-            info.mMatrixDirty = true;
+            mRenderNode.setTranslationY(translationY);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setTranslationY(translationY);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
@@ -10783,7 +10468,7 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationZ() {
-        return mTransformationInfo != null ? mTransformationInfo.mTranslationZ : 0;
+        return mRenderNode.getTranslationZ();
     }
 
     /**
@@ -10792,24 +10477,53 @@
      * @attr ref android.R.styleable#View_translationZ
      */
     public void setTranslationZ(float translationZ) {
-        ensureTransformationInfo();
-        final TransformationInfo info = mTransformationInfo;
-        if (info.mTranslationZ != translationZ) {
+        if (translationZ != getTranslationZ()) {
             invalidateViewProperty(true, false);
-            info.mTranslationZ = translationZ;
-            info.mMatrixDirty = true;
+            mRenderNode.setTranslationZ(translationZ);
             invalidateViewProperty(false, true);
-            if (mDisplayList != null) {
-                mDisplayList.setTranslationZ(translationZ);
-            }
-            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
-                // View was rejected last time it was drawn by its parent; this may have changed
-                invalidateParentIfNeeded();
-            }
+
+            invalidateParentIfNeededAndWasQuickRejected();
         }
     }
 
     /**
+     * Returns a ValueAnimator which can animate a clipping circle.
+     * <p>
+     * The View will be clipped to the animating circle.
+     * <p>
+     * Any shadow cast by the View will respect the circular clip from this animator.
+     *
+     * @param centerX The x coordinate of the center of the animating circle.
+     * @param centerY The y coordinate of the center of the animating circle.
+     * @param startRadius The starting radius of the animating circle.
+     * @param endRadius The ending radius of the animating circle.
+     */
+    public final ValueAnimator createRevealAnimator(int centerX,  int centerY,
+            float startRadius, float endRadius) {
+        return RevealAnimator.ofRevealCircle(this, centerX, centerY,
+                startRadius, endRadius, false);
+    }
+
+    /**
+     * Returns a ValueAnimator which can animate a clearing circle.
+     * <p>
+     * The View is prevented from drawing within the circle, so the content
+     * behind the View shows through.
+     *
+     * @param centerX The x coordinate of the center of the animating circle.
+     * @param centerY The y coordinate of the center of the animating circle.
+     * @param startRadius The starting radius of the animating circle.
+     * @param endRadius The ending radius of the animating circle.
+     *
+     * @hide
+     */
+    public final ValueAnimator createClearCircleAnimator(int centerX,  int centerY,
+            float startRadius, float endRadius) {
+        return RevealAnimator.ofRevealCircle(this, centerX, centerY,
+                startRadius, endRadius, true);
+    }
+
+    /**
      * Sets the outline of the view, which defines the shape of the shadow it
      * casts, and can used for clipping.
      * <p>
@@ -10838,10 +10552,7 @@
             }
             mOutline.set(outline);
         }
-
-        if (mDisplayList != null) {
-            mDisplayList.setOutline(mOutline);
-        }
+        mRenderNode.setOutline(mOutline);
     }
 
     /**
@@ -10876,9 +10587,7 @@
             } else {
                 mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE;
             }
-            if (mDisplayList != null) {
-                mDisplayList.setClipToOutline(clipToOutline);
-            }
+            mRenderNode.setClipToOutline(clipToOutline);
         }
     }
 
@@ -10889,9 +10598,9 @@
      */
     public void setRevealClip(boolean shouldClip, boolean inverseClip,
             float x, float y, float radius) {
-        if (mDisplayList != null) {
-            mDisplayList.setRevealClip(shouldClip, inverseClip, x, y, radius);
-        }
+        mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius);
+        // TODO: Handle this invalidate in a better way, or purely in native.
+        invalidate();
     }
 
     /**
@@ -10900,14 +10609,12 @@
      * @param outRect The hit rectangle of the view.
      */
     public void getHitRect(Rect outRect) {
-        updateMatrix();
-        final TransformationInfo info = mTransformationInfo;
-        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
+        if (hasIdentityMatrix() || mAttachInfo == null) {
             outRect.set(mLeft, mTop, mRight, mBottom);
         } else {
             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
             tmpRect.set(0, 0, getWidth(), getHeight());
-            info.mMatrix.mapRect(tmpRect);
+            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
         }
@@ -10996,11 +10703,9 @@
      */
     public void offsetTopAndBottom(int offset) {
         if (offset != 0) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
-                if (mDisplayList != null) {
+                if (isHardwareAccelerated()) {
                     invalidateViewProperty(false, false);
                 } else {
                     final ViewParent p = mParent;
@@ -11028,8 +10733,8 @@
 
             mTop += offset;
             mBottom += offset;
-            if (mDisplayList != null) {
-                mDisplayList.offsetTopAndBottom(offset);
+            mRenderNode.offsetTopAndBottom(offset);
+            if (isHardwareAccelerated()) {
                 invalidateViewProperty(false, false);
             } else {
                 if (!matrixIsIdentity) {
@@ -11047,11 +10752,9 @@
      */
     public void offsetLeftAndRight(int offset) {
         if (offset != 0) {
-            updateMatrix();
-            final boolean matrixIsIdentity = mTransformationInfo == null
-                    || mTransformationInfo.mMatrixIsIdentity;
+            final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
-                if (mDisplayList != null) {
+                if (isHardwareAccelerated()) {
                     invalidateViewProperty(false, false);
                 } else {
                     final ViewParent p = mParent;
@@ -11076,8 +10779,8 @@
 
             mLeft += offset;
             mRight += offset;
-            if (mDisplayList != null) {
-                mDisplayList.offsetLeftAndRight(offset);
+            mRenderNode.offsetLeftAndRight(offset);
+            if (isHardwareAccelerated()) {
                 invalidateViewProperty(false, false);
             } else {
                 if (!matrixIsIdentity) {
@@ -11457,7 +11160,7 @@
             }
 
             // Damage the entire IsolatedZVolume recieving this view's shadow.
-            if (getTranslationZ() != 0) {
+            if (isHardwareAccelerated() && getTranslationZ() != 0) {
                 damageShadowReceiver();
             }
         }
@@ -11520,7 +11223,9 @@
      * list properties are not being used in this view
      */
     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
-        if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
+        if (!isHardwareAccelerated()
+                || !mRenderNode.isValid()
+                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
             if (invalidateParent) {
                 invalidateParentCaches();
             }
@@ -11531,7 +11236,7 @@
         } else {
             damageInParent();
         }
-        if (invalidateParent && getTranslationZ() != 0) {
+        if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) {
             damageShadowReceiver();
         }
     }
@@ -11548,7 +11253,7 @@
             final Rect r = ai.mTmpInvalRect;
             r.set(0, 0, mRight - mLeft, mBottom - mTop);
             if (mParent instanceof ViewGroup) {
-                ((ViewGroup) mParent).invalidateChildFast(this, r);
+                ((ViewGroup) mParent).damageChild(this, r);
             } else {
                 mParent.invalidateChild(this, r);
             }
@@ -11601,6 +11306,16 @@
     }
 
     /**
+     * @hide
+     */
+    protected void invalidateParentIfNeededAndWasQuickRejected() {
+        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
+            // View was rejected last time it was drawn by its parent; this may have changed
+            invalidateParentIfNeeded();
+        }
+    }
+
+    /**
      * Indicates whether this View is opaque. An opaque View guarantees that it will
      * draw all the pixels overlapping its bounds using a fully opaque color.
      *
@@ -13687,10 +13402,7 @@
 
             mHardwareLayer.setLayerPaint(mLayerPaint);
             RenderNode displayList = mHardwareLayer.startRecording();
-            if (getDisplayList(displayList, true) != displayList) {
-                throw new IllegalStateException("getDisplayList() didn't return"
-                        + " the input displaylist for a hardware layer!");
-            }
+            updateDisplayListIfDirty(displayList, true);
             mHardwareLayer.endRecording(mLocalDirtyRect);
             mLocalDirtyRect.setEmpty();
         }
@@ -13831,29 +13543,34 @@
      * Otherwise, the same display list will be returned (after having been rendered into
      * along the way, depending on the invalidation state of the view).
      *
-     * @param displayList The previous version of this displayList, could be null.
+     * @param renderNode The previous version of this displayList, could be null.
      * @param isLayer Whether the requester of the display list is a layer. If so,
      * the view will avoid creating a layer inside the resulting display list.
      * @return A new or reused DisplayList object.
      */
-    private RenderNode getDisplayList(RenderNode displayList, boolean isLayer) {
+    private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) {
         final HardwareRenderer renderer = getHardwareRenderer();
+        if (renderNode == null) {
+            throw new IllegalArgumentException("RenderNode must not be null");
+        }
         if (renderer == null || !canHaveDisplayList()) {
-            return null;
+            // can't populate RenderNode, don't try
+            return;
         }
 
-        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
-                displayList == null || !displayList.isValid() ||
-                (!isLayer && mRecreateDisplayList))) {
+        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
+                || !renderNode.isValid()
+                || (!isLayer && mRecreateDisplayList)) {
             // Don't need to recreate the display list, just need to tell our
             // children to restore/recreate theirs
-            if (displayList != null && displayList.isValid() &&
-                    !isLayer && !mRecreateDisplayList) {
+            if (renderNode.isValid()
+                    && !isLayer
+                    && !mRecreateDisplayList) {
                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchGetDisplayList();
 
-                return displayList;
+                return; // no work needed
             }
 
             if (!isLayer) {
@@ -13861,20 +13578,13 @@
                 // we copy in child display lists into ours in drawChild()
                 mRecreateDisplayList = true;
             }
-            if (displayList == null) {
-                displayList = RenderNode.create(getClass().getName());
-                // If we're creating a new display list, make sure our parent gets invalidated
-                // since they will need to recreate their display list to account for this
-                // new child display list.
-                invalidateParentCaches();
-            }
 
             boolean caching = false;
             int width = mRight - mLeft;
             int height = mBottom - mTop;
             int layerType = getLayerType();
 
-            final HardwareCanvas canvas = displayList.start(width, height);
+            final HardwareCanvas canvas = renderNode.start(width, height);
 
             try {
                 if (!isLayer && layerType != LAYER_TYPE_NONE) {
@@ -13917,12 +13627,12 @@
                     }
                 }
             } finally {
-                displayList.end(renderer, canvas);
-                displayList.setCaching(caching);
+                renderNode.end(renderer, canvas);
+                renderNode.setCaching(caching);
                 if (isLayer) {
-                    displayList.setLeftTopRightBottom(0, 0, width, height);
+                    renderNode.setLeftTopRightBottom(0, 0, width, height);
                 } else {
-                    setDisplayListProperties(displayList);
+                    setDisplayListProperties(renderNode);
                 }
 
                 if (renderer != getHardwareRenderer()) {
@@ -13937,26 +13647,24 @@
             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
         }
-
-        return displayList;
     }
 
     /**
-     * <p>Returns a display list that can be used to draw this view again
-     * without executing its draw method.</p>
+     * Returns a RenderNode with View draw content recorded, which can be
+     * used to draw this view again without executing its draw method.
      *
-     * @return A DisplayList ready to replay, or null if caching is not enabled.
+     * @return A RenderNode ready to replay, or null if caching is not enabled.
      *
      * @hide
      */
     public RenderNode getDisplayList() {
-        mDisplayList = getDisplayList(mDisplayList, false);
-        return mDisplayList;
+        updateDisplayListIfDirty(mRenderNode, false);
+        return mRenderNode;
     }
 
     private void resetDisplayList() {
-        if (mDisplayList != null && mDisplayList.isValid()) {
-            mDisplayList.destroyDisplayListData();
+        if (mRenderNode.isValid()) {
+            mRenderNode.destroyDisplayListData();
         }
 
         if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
@@ -14550,21 +14258,16 @@
     }
 
     /**
-     * This method is called by getDisplayList() when a display list is created or re-rendered.
-     * It sets or resets the current value of all properties on that display list (resetting is
-     * necessary when a display list is being re-created, because we need to make sure that
-     * previously-set transform values
+     * This method is called by getDisplayList() when a display list is recorded for a View.
+     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
      */
-    void setDisplayListProperties(RenderNode displayList) {
-        if (displayList != null) {
-            displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
-            displayList.setHasOverlappingRendering(hasOverlappingRendering());
+    void setDisplayListProperties(RenderNode renderNode) {
+        if (renderNode != null) {
+            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
             if (mParent instanceof ViewGroup) {
-                displayList.setClipToBounds(
+                renderNode.setClipToBounds(
                         (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
             }
-            displayList.setOutline(mOutline);
-            displayList.setClipToOutline(getClipToOutline());
             float alpha = 1;
             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -14577,7 +14280,7 @@
                             alpha = t.getAlpha();
                         }
                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
-                            displayList.setStaticMatrix(t.getMatrix());
+                            renderNode.setStaticMatrix(t.getMatrix());
                         }
                     }
                 }
@@ -14590,23 +14293,9 @@
                         alpha = 1;
                     }
                 }
-                displayList.setTransformationInfo(alpha,
-                        mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
-                        mTransformationInfo.mTranslationZ,
-                        mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
-                        mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
-                        mTransformationInfo.mScaleY);
-                if (mTransformationInfo.mCamera == null) {
-                    mTransformationInfo.mCamera = new Camera();
-                    mTransformationInfo.matrix3D = new Matrix();
-                }
-                displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
-                    displayList.setPivotX(getPivotX());
-                    displayList.setPivotY(getPivotY());
-                }
+                renderNode.setAlpha(alpha);
             } else if (alpha < 1) {
-                displayList.setAlpha(alpha);
+                renderNode.setAlpha(alpha);
             }
         }
     }
@@ -14653,10 +14342,9 @@
             }
             transformToApply = parent.getChildTransformation();
         } else {
-            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
-                    PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
+            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
                 // No longer animating: clear out old animation matrix
-                mDisplayList.setAnimationMatrix(null);
+                mRenderNode.setAnimationMatrix(null);
                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
             }
             if (!useDisplayListProperties &&
@@ -15169,9 +14857,7 @@
             if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) {
                 // Outline not currently define, query from background
                 mOutline = background.getOutline();
-                if (mDisplayList != null) {
-                    mDisplayList.setOutline(mOutline);
-                }
+                mRenderNode.setOutline(mOutline);
             }
         }
 
@@ -15506,20 +15192,12 @@
             mTop = top;
             mRight = right;
             mBottom = bottom;
-            if (mDisplayList != null) {
-                mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
-            }
+            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
 
             mPrivateFlags |= PFLAG_HAS_BOUNDS;
 
 
             if (sizeChanged) {
-                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
-                    // A change in dimension means an auto-centered pivot point changes, too
-                    if (mTransformationInfo != null) {
-                        mTransformationInfo.mMatrixDirty = true;
-                    }
-                }
                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
             }
 
@@ -19093,10 +18771,10 @@
         }
     }
 
-    class CheckForLongPress implements Runnable {
-
+    private final class CheckForLongPress implements Runnable {
         private int mOriginalWindowAttachCount;
 
+        @Override
         public void run() {
             if (isPressed() && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
@@ -19112,14 +18790,20 @@
     }
 
     private final class CheckForTap implements Runnable {
+        public float x;
+        public float y;
+
+        @Override
         public void run() {
             mPrivateFlags &= ~PFLAG_PREPRESSED;
+            setHotspot(R.attr.state_pressed, x, y);
             setPressed(true);
             checkForLongClick(ViewConfiguration.getTapTimeout());
         }
     }
 
     private final class PerformClick implements Runnable {
+        @Override
         public void run() {
             performClick();
         }
@@ -19398,7 +19082,9 @@
     }
 
     private final class UnsetPressedState implements Runnable {
+        @Override
         public void run() {
+            clearHotspot(R.attr.state_pressed);
             setPressed(false);
         }
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index aadaa7f..d2c6302 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -31,7 +31,6 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -3174,8 +3173,8 @@
             setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
             for (int i = 0; i < mChildrenCount; ++i) {
                 View child = getChildAt(i);
-                if (child.mDisplayList != null) {
-                    child.mDisplayList.setClipToBounds(clipChildren);
+                if (child.mRenderNode != null) {
+                    child.mRenderNode.setClipToBounds(clipChildren);
                 }
             }
         }
@@ -4450,7 +4449,7 @@
      *
      * @hide
      */
-    public void invalidateChildFast(View child, final Rect dirty) {
+    public void damageChild(View child, final Rect dirty) {
         ViewParent parent = this;
 
         final AttachInfo attachInfo = mAttachInfo;
@@ -4473,7 +4472,7 @@
                         parentVG.invalidate();
                         parent = null;
                     } else {
-                        parent = parentVG.invalidateChildInParentFast(left, top, dirty);
+                        parent = parentVG.damageChildInParent(left, top, dirty);
                         left = parentVG.mLeft;
                         top = parentVG.mTop;
                     }
@@ -4495,9 +4494,9 @@
      *
      * @hide
      */
-    protected ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
-        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
-                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
+    protected ViewParent damageChildInParent(int left, int top, final Rect dirty) {
+        if ((mPrivateFlags & PFLAG_DRAWN) != 0
+                || (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) != 0) {
             dirty.offset(left - mScrollX, top - mScrollY);
             if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {
                 dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
@@ -4610,9 +4609,9 @@
             final View v = children[i];
             v.mTop += offset;
             v.mBottom += offset;
-            if (v.mDisplayList != null) {
+            if (v.mRenderNode != null) {
                 invalidate = true;
-                v.mDisplayList.offsetTopAndBottom(offset);
+                v.mRenderNode.offsetTopAndBottom(offset);
             }
         }
 
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 47de780..0cf9ddd 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -290,7 +290,11 @@
             }
         }
 
-        public void invalidateChildFast(View child, final Rect dirty) {
+        /**
+         * @hide
+         */
+        @Override
+        public void damageChild(View child, final Rect dirty) {
             if (mHostView != null) {
                 // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
                 // using DisplayList properties and a dirty rect instead of causing a real
@@ -309,9 +313,9 @@
          * @hide
          */
         @Override
-        protected ViewParent invalidateChildInParentFast(int left, int top, Rect dirty) {
+        protected ViewParent damageChildInParent(int left, int top, Rect dirty) {
             if (mHostView instanceof ViewGroup) {
-                return ((ViewGroup) mHostView).invalidateChildInParentFast(left, top, dirty);
+                return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty);
             }
             return null;
         }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 563ffb7..6b21451 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -925,51 +925,41 @@
      */
     private void setValue(int propertyConstant, float value) {
         final View.TransformationInfo info = mView.mTransformationInfo;
-        final RenderNode displayList = mView.mDisplayList;
+        final RenderNode renderNode = mView.mRenderNode;
         switch (propertyConstant) {
             case TRANSLATION_X:
-                info.mTranslationX = value;
-                if (displayList != null) displayList.setTranslationX(value);
+                renderNode.setTranslationX(value);
                 break;
             case TRANSLATION_Y:
-                info.mTranslationY = value;
-                if (displayList != null) displayList.setTranslationY(value);
+                renderNode.setTranslationY(value);
                 break;
             case TRANSLATION_Z:
-                info.mTranslationZ = value;
-                if (displayList != null) displayList.setTranslationZ(value);
+                renderNode.setTranslationZ(value);
                 break;
             case ROTATION:
-                info.mRotation = value;
-                if (displayList != null) displayList.setRotation(value);
+                renderNode.setRotation(value);
                 break;
             case ROTATION_X:
-                info.mRotationX = value;
-                if (displayList != null) displayList.setRotationX(value);
+                renderNode.setRotationX(value);
                 break;
             case ROTATION_Y:
-                info.mRotationY = value;
-                if (displayList != null) displayList.setRotationY(value);
+                renderNode.setRotationY(value);
                 break;
             case SCALE_X:
-                info.mScaleX = value;
-                if (displayList != null) displayList.setScaleX(value);
+                renderNode.setScaleX(value);
                 break;
             case SCALE_Y:
-                info.mScaleY = value;
-                if (displayList != null) displayList.setScaleY(value);
+                renderNode.setScaleY(value);
                 break;
             case X:
-                info.mTranslationX = value - mView.mLeft;
-                if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
+                renderNode.setTranslationX(value - mView.mLeft);
                 break;
             case Y:
-                info.mTranslationY = value - mView.mTop;
-                if (displayList != null) displayList.setTranslationY(value - mView.mTop);
+                renderNode.setTranslationY(value - mView.mTop);
                 break;
             case ALPHA:
                 info.mAlpha = value;
-                if (displayList != null) displayList.setAlpha(value);
+                renderNode.setAlpha(value);
                 break;
         }
     }
@@ -981,30 +971,30 @@
      * @return float The value of the named property
      */
     private float getValue(int propertyConstant) {
-        final View.TransformationInfo info = mView.mTransformationInfo;
+        final RenderNode node = mView.mRenderNode;
         switch (propertyConstant) {
             case TRANSLATION_X:
-                return info.mTranslationX;
+                return node.getTranslationX();
             case TRANSLATION_Y:
-                return info.mTranslationY;
+                return node.getTranslationY();
             case TRANSLATION_Z:
-                return info.mTranslationZ;
+                return node.getTranslationZ();
             case ROTATION:
-                return info.mRotation;
+                return node.getRotation();
             case ROTATION_X:
-                return info.mRotationX;
+                return node.getRotationX();
             case ROTATION_Y:
-                return info.mRotationY;
+                return node.getRotationY();
             case SCALE_X:
-                return info.mScaleX;
+                return node.getScaleX();
             case SCALE_Y:
-                return info.mScaleY;
+                return node.getScaleY();
             case X:
-                return mView.mLeft + info.mTranslationX;
+                return mView.mLeft + node.getTranslationX();
             case Y:
-                return mView.mTop + info.mTranslationY;
+                return mView.mTop + node.getTranslationY();
             case ALPHA:
-                return info.mAlpha;
+                return mView.mTransformationInfo.mAlpha;
         }
         return 0;
     }
@@ -1093,7 +1083,7 @@
                 // Shouldn't happen, but just to play it safe
                 return;
             }
-            boolean useDisplayListProperties = mView.mDisplayList != null;
+            boolean useRenderNodeProperties = mView.mRenderNode != null;
 
             // alpha requires slightly different treatment than the other (transform) properties.
             // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
@@ -1101,7 +1091,7 @@
             // We track what kinds of properties are set, and how alpha is handled when it is
             // set, and perform the invalidation steps appropriately.
             boolean alphaHandled = false;
-            if (!useDisplayListProperties) {
+            if (!useRenderNodeProperties) {
                 mView.invalidateParentCaches();
             }
             float fraction = animation.getAnimatedFraction();
@@ -1123,8 +1113,7 @@
                 }
             }
             if ((propertyMask & TRANSFORM_MASK) != 0) {
-                mView.mTransformationInfo.mMatrixDirty = true;
-                if (!useDisplayListProperties) {
+                if (!useRenderNodeProperties) {
                     mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
                 }
             }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0e523e..94f0683 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1465,8 +1465,8 @@
                                     mWidth, mHeight);
                         }
                         mResizeBuffer.prepare(mWidth, mHeight, false);
-                        RenderNode layerDisplayList = mResizeBuffer.startRecording();
-                        HardwareCanvas layerCanvas = layerDisplayList.start(mWidth, mHeight);
+                        RenderNode layerRenderNode = mResizeBuffer.startRecording();
+                        HardwareCanvas layerCanvas = layerRenderNode.start(mWidth, mHeight);
                         final int restoreCount = layerCanvas.save();
 
                         int yoff;
@@ -1484,9 +1484,9 @@
                             mTranslator.translateCanvas(layerCanvas);
                         }
 
-                        RenderNode displayList = mView.mDisplayList;
-                        if (displayList != null && displayList.isValid()) {
-                            layerCanvas.drawDisplayList(displayList, null,
+                        RenderNode renderNode = mView.mRenderNode;
+                        if (renderNode != null && renderNode.isValid()) {
+                            layerCanvas.drawDisplayList(renderNode, null,
                                     RenderNode.FLAG_CLIP_CHILDREN);
                         } else {
                             mView.draw(layerCanvas);
@@ -1499,9 +1499,9 @@
                                 com.android.internal.R.integer.config_mediumAnimTime);
 
                         layerCanvas.restoreToCount(restoreCount);
-                        layerDisplayList.end(mAttachInfo.mHardwareRenderer, layerCanvas);
-                        layerDisplayList.setCaching(true);
-                        layerDisplayList.setLeftTopRightBottom(0, 0, mWidth, mHeight);
+                        layerRenderNode.end(mAttachInfo.mHardwareRenderer, layerCanvas);
+                        layerRenderNode.setCaching(true);
+                        layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
                         mTempRect.set(0, 0, mWidth, mHeight);
                         mResizeBuffer.endRecording(mTempRect);
                         mAttachInfo.mHardwareRenderer.flushLayerUpdates();
@@ -2178,9 +2178,9 @@
      * @hide
      */
     void outputDisplayList(View view) {
-        RenderNode displayList = view.getDisplayList();
-        if (displayList != null) {
-            displayList.output();
+        RenderNode renderNode = view.getDisplayList();
+        if (renderNode != null) {
+            renderNode.output();
         }
     }
 
@@ -2259,6 +2259,9 @@
 
         if (mReportNextDraw) {
             mReportNextDraw = false;
+            if (mAttachInfo.mHardwareRenderer != null) {
+                mAttachInfo.mHardwareRenderer.fence();
+            }
 
             if (LOCAL_LOGV) {
                 Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
@@ -5218,10 +5221,10 @@
     }
 
     private static void getGfxInfo(View view, int[] info) {
-        RenderNode displayList = view.mDisplayList;
+        RenderNode renderNode = view.mRenderNode;
         info[0]++;
-        if (displayList != null) {
-            info[1] += 0; /* TODO: Memory used by display lists */
+        if (renderNode != null) {
+            info[1] += 0; /* TODO: Memory used by RenderNodes (properties + DisplayLists) */
         }
 
         if (view instanceof ViewGroup) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0cd6325..7bd1f56 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -1390,11 +1389,11 @@
      * @param options Options to set or null for none
      * @hide
      */
-    public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+    public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
     }
 
     /**
-     * A callback for Activity transitions to be told when the shared element is ready to be shown
+     * A callback for Window transitions to be told when the shared element is ready to be shown
      * and start the transition to its target location.
      * @hide
      */
@@ -1407,27 +1406,57 @@
     }
 
     /**
-     * Controls when the Activity enter scene is triggered and the background is faded in. If
-     * triggerEarly is true, the enter scene will begin as soon as possible and the background
-     * will fade in when all shared elements are ready to begin transitioning. If triggerEarly is
-     * false, the Activity enter scene and background fade will be triggered when the calling
-     * Activity's exit transition completes.
-     *
-     * @param triggerEarly Set to true to have the Activity enter scene transition in as early as
-     *                     possible or set to false to wait for the calling Activity to exit first.
+     * Controls how the Activity's start Scene is faded in and when the enter scene
+     * is triggered to start.
+     * <p>When allow is true, the enter Scene will begin as soon as possible
+     * and the background will fade in when all shared elements are ready to begin
+     * transitioning. If allow is false, the Activity enter Scene and
+     * background fade will be triggered when the calling Activity's exit transition
+     * completes.</p>
+     * @param allow Set to true to have the Activity enter scene transition in
+     *              as early as possible or set to false to wait for the calling
+     *              Activity to exit first. The default value is true.
      */
-    public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
+    public void setAllowOverlappingEnterTransition(boolean allow) {
+    }
+
+    /**
+     * Controls how the Activity's Scene fades out and when the calling Activity's
+     * enter scene is triggered when finishing to return to a calling Activity.
+     * <p>When allow is true, the Scene will fade out quickly
+     * and inform the calling Activity to transition in when the fade completes.
+     * When allow is false, the calling Activity will transition in after
+     * the Activity's Scene has exited.
+     * </p>
+     * @param allow Set to true to have the Activity fade out as soon as possible
+     *              and transition in the calling Activity. The default value is
+     *              true.
+     */
+    public void setAllowOverlappingExitTransition(boolean allow) {
     }
 
     /**
      * Start the exit transition.
      * @hide
      */
-    public Bundle startExitTransition(ActivityOptions options) {
+    public Bundle startExitTransitionToCallee(Bundle options) {
         return null;
     }
 
     /**
+     * Starts the transition back to the calling Activity.
+     * onTransitionEnd will be called on the current thread if there is no exit transition.
+     * @hide
+     */
+    public void startExitTransitionToCaller(Runnable onTransitionEnd) {
+        onTransitionEnd.run();
+    }
+
+    /** @hide */
+    public void restoreViewVisibilityAfterTransitionToCallee() {
+    }
+
+    /**
      * On entering Activity Scene transitions, shared element names may be mapped from a
      * source Activity's specified name to a unique shared element name in the View hierarchy.
      * Under most circumstances, mapping is not necessary - a single View will have the
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index f2ce113..e3bd9fd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,6 +26,7 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -41,13 +42,13 @@
 import android.util.Pools.SimplePool;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
+import android.util.SparseArray;
 import android.view.InputChannel;
 import android.view.InputEvent;
 import android.view.InputEventSender;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
-import android.util.SparseArray;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -334,6 +335,11 @@
     InputChannel mCurChannel;
     ImeInputEventSender mCurSender;
 
+    /**
+     * The current cursor/anchor monitor mode.
+     */
+    int mCursorAnchorMonitorMode = InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_NONE;
+
     final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
 
@@ -346,6 +352,7 @@
     static final int MSG_SEND_INPUT_EVENT = 5;
     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
     static final int MSG_FLUSH_INPUT_EVENT = 7;
+    static final int SET_CURSOR_ANCHOR_MONITOR_MODE = 8;
 
     class H extends Handler {
         H(Looper looper) {
@@ -476,6 +483,12 @@
                     finishedInputEvent(msg.arg1, false, false);
                     return;
                 }
+                case SET_CURSOR_ANCHOR_MONITOR_MODE: {
+                    synchronized (mH) {
+                        mCursorAnchorMonitorMode = msg.arg1;
+                    }
+                    return;
+                }
             }
         }
     }
@@ -540,6 +553,11 @@
         public void setActive(boolean active) {
             mH.sendMessage(mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, 0));
         }
+
+        @Override
+        public void setCursorAnchorMonitorMode(int monitorMode) {
+            mH.sendMessage(mH.obtainMessage(SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, 0));
+        }
     };
 
     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
@@ -1465,9 +1483,30 @@
      * of the input editor's cursor in its window.
      */
     public boolean isWatchingCursor(View view) {
-        return false;
+        if (!isActive(view)) {
+            return false;
+        }
+        synchronized (mH) {
+            return mCursorAnchorMonitorMode ==
+                    InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT;
+        }
     }
-    
+
+    /**
+     * Set cursor/anchor monitor mode via {@link com.android.server.InputMethodManagerService}.
+     * This is an internal method for {@link android.inputmethodservice.InputMethodService} and
+     * should never be used from IMEs and applications.
+     *
+     * @hide
+     */
+    public void setCursorAnchorMonitorMode(IBinder imeToken, int monitorMode) {
+        try {
+            mService.setCursorAnchorMonitorMode(imeToken, monitorMode);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * Report the current cursor location in its window.
      */
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 1f405a7..e4575e5 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -640,16 +640,6 @@
         }
 
         @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
-                // Fill available height
-                heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                        MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
-            }
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-
-        @Override
         public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
             super.onInitializeAccessibilityNodeInfo(info);
             info.setCanOpenPopup(true);
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 32c7086..3975edf 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -20,6 +20,7 @@
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
@@ -27,6 +28,7 @@
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.view.menu.MenuView;
 
 /**
@@ -50,6 +52,8 @@
     private int mMinCellSize;
     private int mGeneratedItemPadding;
 
+    private OnMenuItemClickListener mOnMenuItemClickListener;
+
     public ActionMenuView(Context context) {
         this(context, null);
     }
@@ -78,6 +82,10 @@
         }
     }
 
+    public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
+        mOnMenuItemClickListener = listener;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // If we've been given an exact size to match, apply special formatting during layout.
@@ -96,11 +104,11 @@
             mMenu.onItemsChanged(true);
         }
 
-        if (mFormatItems) {
+        final int childCount = getChildCount();
+        if (mFormatItems && childCount > 0) {
             onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
         } else {
             // Previous measurement at exact format may have set margins - reset them.
-            final int childCount = getChildCount();
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -559,9 +567,11 @@
         if (mMenu == null) {
             final Context context = getContext();
             mMenu = new MenuBuilder(context);
+            mMenu.setCallback(new MenuBuilderCallback());
             mPresenter = new ActionMenuPresenter(context);
-            mPresenter.initForMenu(context, mMenu);
             mPresenter.setMenuView(this);
+            mPresenter.setCallback(new ActionMenuPresenterCallback());
+            mMenu.addMenuPresenter(mPresenter);
         }
 
         return mMenu;
@@ -591,6 +601,44 @@
         return false;
     }
 
+    /**
+     * Interface responsible for receiving menu item click events if the items themselves
+     * do not have individual item click listeners.
+     */
+    public interface OnMenuItemClickListener {
+        /**
+         * This method will be invoked when a menu item is clicked if the item itself did
+         * not already handle the event.
+         *
+         * @param item {@link MenuItem} that was clicked
+         * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
+         */
+        public boolean onMenuItemClick(MenuItem item);
+    }
+
+    private class MenuBuilderCallback implements MenuBuilder.Callback {
+        @Override
+        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+            return mOnMenuItemClickListener != null &&
+                    mOnMenuItemClickListener.onMenuItemClick(item);
+        }
+
+        @Override
+        public void onMenuModeChange(MenuBuilder menu) {
+        }
+    }
+
+    private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback {
+        @Override
+        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+        }
+
+        @Override
+        public boolean onOpenSubMenu(MenuBuilder subMenu) {
+            return false;
+        }
+    }
+
     /** @hide */
     public interface ActionMenuChildView {
         public boolean needsDividerBefore();
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 64953f8..b47177a 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.IntProperty;
@@ -1225,6 +1226,15 @@
                 forwarding = onTouchForwarded(event) || !onForwardingStopped();
             } else {
                 forwarding = onTouchObserved(event) && onForwardingStarted();
+
+                if (forwarding) {
+                    // Make sure we cancel any ongoing source event stream.
+                    final long now = SystemClock.uptimeMillis();
+                    final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL,
+                            0.0f, 0.0f, 0);
+                    mSrc.onTouchEvent(e);
+                    e.recycle();
+                }
             }
 
             mForwarding = forwarding;
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 1eedc5d..d8a6867 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1171,8 +1171,8 @@
                     || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
                 if (mSearchable != null) {
                     launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
-                    setImeVisibility(false);
                 }
+                setImeVisibility(false);
                 dismissSuggestions();
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 687036c..5e4c143 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5163,12 +5163,12 @@
                 final int width = mRight - mLeft;
                 final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
                 final float dx = mLayout.getLineRight(0) - (width - padding);
-                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
+                canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
             }
 
             if (mMarquee != null && mMarquee.isRunning()) {
                 final float dx = -mMarquee.getScroll();
-                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
+                canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
             }
         }
 
@@ -5182,8 +5182,8 @@
         }
 
         if (mMarquee != null && mMarquee.shouldDrawGhost()) {
-            final int dx = (int) mMarquee.getGhostOffset();
-            canvas.translate(isLayoutRtl ? -dx : dx, 0.0f);
+            final float dx = mMarquee.getGhostOffset();
+            canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
             layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
         }
 
diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java
index c9a9894..79256e5 100644
--- a/core/java/android/widget/TimePickerDelegate.java
+++ b/core/java/android/widget/TimePickerDelegate.java
@@ -152,11 +152,11 @@
         final int headerBackgroundColor = a.getColor(
                 R.styleable.TimePicker_headerBackgroundColor, 0);
 
-        a.recycle();
-
         final int layoutResourceId = a.getResourceId(
                 R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo);
 
+        a.recycle();
+
         final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
 
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
new file mode 100644
index 0000000..075feba
--- /dev/null
+++ b/core/java/android/widget/Toolbar.java
@@ -0,0 +1,1048 @@
+/*
+ * 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.widget;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A standard toolbar for use within application content.
+ *
+ * <p>A Toolbar is a generalization of {@link android.app.ActionBar action bars} for use
+ * within application layouts. While an action bar is traditionally part of an
+ * {@link android.app.Activity Activity's} opaque window decor controlled by the framework,
+ * a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy.
+ * An application may choose to designate a Toolbar as the action bar for an Activity
+ * using the {@link android.app.Activity#setActionBar(Toolbar) setActionBar()} method.</p>
+ *
+ * <p>Toolbar supports a more focused feature set than ActionBar. From start to end, a toolbar
+ * may contain a combination of the following optional elements:
+ *
+ * <ul>
+ *     <li><em>A navigation button.</em> This may be an Up arrow, navigation menu toggle, close,
+ *     collapse, done or another glyph of the app's choosing. This button should always be used
+ *     to access other navigational destinations within the container of the Toolbar and
+ *     its signified content or otherwise leave the current context signified by the Toolbar.</li>
+ *     <li><em>A branded logo image.</em> This may extend to the height of the bar and can be
+ *     arbitrarily wide.</li>
+ *     <li><em>A title and subtitle.</em> The title should be a signpost for the Toolbar's current
+ *     position in the navigation hierarchy and the content contained there. The subtitle,
+ *     if present should indicate any extended information about the current content.
+ *     If an app uses a logo image it should strongly consider omitting a title and subtitle.</li>
+ *     <li><em>One or more custom views.</em> The application may add arbitrary child views
+ *     to the Toolbar. They will appear at this position within the layout. If a child view's
+ *     {@link LayoutParams} indicates a {@link Gravity} value of
+ *     {@link Gravity#CENTER_HORIZONTAL CENTER_HORIZONTAL} the view will attempt to center
+ *     within the available space remaining in the Toolbar after all other elements have been
+ *     measured.</li>
+ *     <li><em>An {@link ActionMenuView action menu}.</em> The menu of actions will pin to the
+ *     end of the Toolbar offering a few
+ *     <a href="http://developer.android.com/design/patterns/actionbar.html#ActionButtons">
+ *         frequent, important or typical</a> actions along with an optional overflow menu for
+ *         additional actions.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>In modern Android UIs developers should lean more on a visually distinct color scheme for
+ * toolbars than on their application icon. The use of application icon plus title as a standard
+ * layout is discouraged on API 21 devices and newer.</p>
+ */
+public class Toolbar extends ViewGroup {
+    private ActionMenuView mMenuView;
+    private TextView mTitleTextView;
+    private TextView mSubtitleTextView;
+    private ImageButton mNavButtonView;
+    private ImageView mLogoView;
+
+    private int mTitleTextAppearance;
+    private int mSubtitleTextAppearance;
+    private int mTitleMarginStart;
+    private int mTitleMarginEnd;
+    private int mTitleMarginTop;
+    private int mTitleMarginBottom;
+
+    private int mGravity = Gravity.START | Gravity.CENTER_VERTICAL;
+
+    private CharSequence mTitleText;
+    private CharSequence mSubtitleText;
+
+    // Clear me after use.
+    private final ArrayList<View> mTempViews = new ArrayList<View>();
+
+    private OnMenuItemClickListener mOnMenuItemClickListener;
+
+    private final ActionMenuView.OnMenuItemClickListener mMenuViewItemClickListener =
+            new ActionMenuView.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    if (mOnMenuItemClickListener != null) {
+                        return mOnMenuItemClickListener.onMenuItemClick(item);
+                    }
+                    return false;
+                }
+            };
+
+    public Toolbar(Context context) {
+        this(context, null);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.toolbarStyle);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public Toolbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Toolbar,
+                defStyleAttr, defStyleRes);
+
+        mTitleTextAppearance = a.getResourceId(R.styleable.Toolbar_titleTextAppearance, 0);
+        mSubtitleTextAppearance = a.getResourceId(R.styleable.Toolbar_subtitleTextAppearance, 0);
+        mGravity = a.getInteger(R.styleable.Toolbar_gravity, mGravity);
+        mTitleMarginStart = mTitleMarginEnd = Math.max(0, a.getDimensionPixelOffset(
+                R.styleable.Toolbar_titleMargins, -1));
+
+        final int marginStart = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginStart, -1);
+        if (marginStart >= 0) {
+            mTitleMarginStart = marginStart;
+        }
+
+        final int marginEnd = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginEnd, -1);
+        if (marginEnd >= 0) {
+            mTitleMarginEnd = marginEnd;
+        }
+
+        final int marginTop = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginTop, -1);
+        if (marginTop >= 0) {
+            mTitleMarginTop = marginTop;
+        }
+
+        final int marginBottom = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMarginBottom,
+                -1);
+        if (marginBottom >= 0) {
+            mTitleMarginBottom = marginBottom;
+        }
+
+        final CharSequence title = a.getText(R.styleable.Toolbar_title);
+        if (!TextUtils.isEmpty(title)) {
+            setTitle(title);
+        }
+
+        final CharSequence subtitle = a.getText(R.styleable.Toolbar_subtitle);
+        if (!TextUtils.isEmpty(subtitle)) {
+            setSubtitle(title);
+        }
+        a.recycle();
+    }
+
+    /**
+     * Set a logo drawable from a resource id.
+     *
+     * <p>This drawable should generally take the place of title text. The logo cannot be
+     * clicked. Apps using a logo should also supply a description using
+     * {@link #setLogoDescription(int)}.</p>
+     *
+     * @param resId ID of a drawable resource
+     */
+    public void setLogo(int resId) {
+        setLogo(getContext().getDrawable(resId));
+    }
+
+    /**
+     * Set a logo drawable.
+     *
+     * <p>This drawable should generally take the place of title text. The logo cannot be
+     * clicked. Apps using a logo should also supply a description using
+     * {@link #setLogoDescription(int)}.</p>
+     *
+     * @param drawable Drawable to use as a logo
+     */
+    public void setLogo(Drawable drawable) {
+        if (drawable != null) {
+            if (mLogoView == null) {
+                mLogoView = new ImageView(getContext());
+            }
+            if (mLogoView.getParent() == null) {
+                addSystemView(mLogoView);
+            }
+        } else if (mLogoView != null && mLogoView.getParent() != null) {
+            removeView(mLogoView);
+        }
+        if (mLogoView != null) {
+            mLogoView.setImageDrawable(drawable);
+        }
+    }
+
+    /**
+     * Return the current logo drawable.
+     *
+     * @return The current logo drawable
+     * @see #setLogo(int)
+     * @see #setLogo(android.graphics.drawable.Drawable)
+     */
+    public Drawable getLogo() {
+        return mLogoView != null ? mLogoView.getDrawable() : null;
+    }
+
+    /**
+     * Set a description of the toolbar's logo.
+     *
+     * <p>This description will be used for accessibility or other similar descriptions
+     * of the UI.</p>
+     *
+     * @param resId String resource id
+     */
+    public void setLogoDescription(int resId) {
+        setLogoDescription(getContext().getText(resId));
+    }
+
+    /**
+     * Set a description of the toolbar's logo.
+     *
+     * <p>This description will be used for accessibility or other similar descriptions
+     * of the UI.</p>
+     *
+     * @param description Description to set
+     */
+    public void setLogoDescription(CharSequence description) {
+        if (!TextUtils.isEmpty(description) && mLogoView == null) {
+            mLogoView = new ImageView(getContext());
+        }
+        if (mLogoView != null) {
+            mLogoView.setContentDescription(description);
+        }
+    }
+
+    /**
+     * Return the description of the toolbar's logo.
+     *
+     * @return A description of the logo
+     */
+    public CharSequence getLogoDescription() {
+        return mLogoView != null ? mLogoView.getContentDescription() : null;
+    }
+
+    /**
+     * Return the current title displayed in the toolbar.
+     *
+     * @return The current title
+     */
+    public CharSequence getTitle() {
+        return mTitleText;
+    }
+
+    /**
+     * Set the title of this toolbar.
+     *
+     * <p>A title should be used as the anchor for a section of content. It should
+     * describe or name the content being viewed.</p>
+     *
+     * @param resId Resource ID of a string to set as the title
+     */
+    public void setTitle(int resId) {
+        setTitle(getContext().getText(resId));
+    }
+
+    /**
+     * Set the title of this toolbar.
+     *
+     * <p>A title should be used as the anchor for a section of content. It should
+     * describe or name the content being viewed.</p>
+     *
+     * @param title Title to set
+     */
+    public void setTitle(CharSequence title) {
+        if (!TextUtils.isEmpty(title)) {
+            if (mTitleTextView == null) {
+                final Context context = getContext();
+                mTitleTextView = new TextView(context);
+                mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
+            }
+            if (mTitleTextView.getParent() == null) {
+                addSystemView(mTitleTextView);
+            }
+        } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
+            removeView(mTitleTextView);
+        }
+        if (mTitleTextView != null) {
+            mTitleTextView.setText(title);
+        }
+        mTitleText = title;
+    }
+
+    /**
+     * Return the subtitle of this toolbar.
+     *
+     * @return The current subtitle
+     */
+    public CharSequence getSubtitle() {
+        return mSubtitleText;
+    }
+
+    /**
+     * Set the subtitle of this toolbar.
+     *
+     * <p>Subtitles should express extended information about the current content.</p>
+     *
+     * @param resId String resource ID
+     */
+    public void setSubtitle(int resId) {
+        setSubtitle(getContext().getText(resId));
+    }
+
+    /**
+     * Set the subtitle of this toolbar.
+     *
+     * <p>Subtitles should express extended information about the current content.</p>
+     *
+     * @param subtitle Subtitle to set
+     */
+    public void setSubtitle(CharSequence subtitle) {
+        if (!TextUtils.isEmpty(subtitle)) {
+            if (mSubtitleTextView == null) {
+                final Context context = getContext();
+                mSubtitleTextView = new TextView(context);
+                mSubtitleTextView.setTextAppearance(context, mSubtitleTextAppearance);
+            }
+            if (mSubtitleTextView.getParent() == null) {
+                addSystemView(mSubtitleTextView);
+            }
+        } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
+            removeView(mSubtitleTextView);
+        }
+        if (mSubtitleTextView != null) {
+            mSubtitleTextView.setText(subtitle);
+        }
+        mSubtitleText = subtitle;
+    }
+
+    /**
+     * Set the icon to use for the toolbar's navigation button.
+     *
+     * <p>The navigation button appears at the start of the toolbar if present. Setting an icon
+     * will make the navigation button visible.</p>
+     *
+     * <p>If you use a navigation icon you should also set a description for its action using
+     * {@link #setNavigationDescription(int)}. This is used for accessibility and tooltips.</p>
+     *
+     * @param resId Resource ID of a drawable to set
+     */
+    public void setNavigationIcon(int resId) {
+        setNavigationIcon(getContext().getDrawable(resId));
+    }
+
+    /**
+     * Set the icon to use for the toolbar's navigation button.
+     *
+     * <p>The navigation button appears at the start of the toolbar if present. Setting an icon
+     * will make the navigation button visible.</p>
+     *
+     * <p>If you use a navigation icon you should also set a description for its action using
+     * {@link #setNavigationDescription(int)}. This is used for accessibility and tooltips.</p>
+     *
+     * @param icon Drawable to set
+     */
+    public void setNavigationIcon(Drawable icon) {
+        if (icon != null) {
+            ensureNavButtonView();
+            if (mNavButtonView.getParent() == null) {
+                addSystemView(mNavButtonView);
+            }
+        } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
+            removeView(mNavButtonView);
+        }
+        if (mNavButtonView != null) {
+            mNavButtonView.setImageDrawable(icon);
+        }
+    }
+
+    /**
+     * Return the current drawable used as the navigation icon.
+     *
+     * @return The navigation icon drawable
+     */
+    public Drawable getNavigationIcon() {
+        return mNavButtonView != null ? mNavButtonView.getDrawable() : null;
+    }
+
+    /**
+     * Set a description for the navigation button.
+     *
+     * <p>This description string is used for accessibility, tooltips and other facilities
+     * to improve discoverability.</p>
+     *
+     * @param resId Resource ID of a string to set
+     */
+    public void setNavigationDescription(int resId) {
+        setNavigationDescription(getContext().getText(resId));
+    }
+
+    /**
+     * Set a description for the navigation button.
+     *
+     * <p>This description string is used for accessibility, tooltips and other facilities
+     * to improve discoverability.</p>
+     *
+     * @param description String to set as the description
+     */
+    public void setNavigationDescription(CharSequence description) {
+        if (!TextUtils.isEmpty(description)) {
+            ensureNavButtonView();
+        }
+        if (mNavButtonView != null) {
+            mNavButtonView.setContentDescription(description);
+        }
+    }
+
+    /**
+     * Set a listener to respond to navigation events.
+     *
+     * <p>This listener will be called whenever the user clicks the navigation button
+     * at the start of the toolbar. An icon must be set for the navigation button to appear.</p>
+     *
+     * @param listener Listener to set
+     * @see #setNavigationIcon(android.graphics.drawable.Drawable)
+     */
+    public void setNavigationOnClickListener(OnClickListener listener) {
+        ensureNavButtonView();
+        mNavButtonView.setOnClickListener(listener);
+    }
+
+    /**
+     * Return the Menu shown in the toolbar.
+     *
+     * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
+     * an XML menu resource, use {@link #inflateMenu(int)}.</p>
+     *
+     * @return The toolbar's Menu
+     */
+    public Menu getMenu() {
+        if (mMenuView == null) {
+            mMenuView = new ActionMenuView(getContext());
+            mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
+            addSystemView(mMenuView);
+        }
+        return mMenuView.getMenu();
+    }
+
+    private MenuInflater getMenuInflater() {
+        return new MenuInflater(getContext());
+    }
+
+    /**
+     * Inflate a menu resource into this toolbar.
+     *
+     * <p>Inflate an XML menu resource into this toolbar. Existing items in the menu will not
+     * be modified or removed.</p>
+     *
+     * @param resId ID of a menu resource to inflate
+     */
+    public void inflateMenu(int resId) {
+        getMenuInflater().inflate(resId, getMenu());
+    }
+
+    /**
+     * Set a listener to respond to menu item click events.
+     *
+     * <p>This listener will be invoked whenever a user selects a menu item from
+     * the action buttons presented at the end of the toolbar or the associated overflow.</p>
+     *
+     * @param listener Listener to set
+     */
+    public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
+        mOnMenuItemClickListener = listener;
+    }
+
+    private void ensureNavButtonView() {
+        if (mNavButtonView == null) {
+            mNavButtonView = new ImageButton(getContext(), null, R.attr.borderlessButtonStyle);
+        }
+    }
+
+    private void addSystemView(View v) {
+        final LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
+                LayoutParams.WRAP_CONTENT);
+        lp.mViewType = LayoutParams.SYSTEM;
+        addView(v, lp);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        SavedState state = new SavedState(super.onSaveInstanceState());
+        return state;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        final SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = 0;
+        int height = 0;
+        int childState = 0;
+
+        // System views measure first.
+
+        if (shouldLayout(mNavButtonView)) {
+            measureChildWithMargins(mNavButtonView, widthMeasureSpec, width, heightMeasureSpec, 0);
+            width += mNavButtonView.getMeasuredWidth() + getHorizontalMargins(mNavButtonView);
+            height = Math.max(height, mNavButtonView.getMeasuredHeight() +
+                    getVerticalMargins(mNavButtonView));
+            childState = combineMeasuredStates(childState, mNavButtonView.getMeasuredState());
+        }
+
+        if (shouldLayout(mMenuView)) {
+            measureChildWithMargins(mMenuView, widthMeasureSpec, width, heightMeasureSpec, 0);
+            width += mMenuView.getMeasuredWidth() + getHorizontalMargins(mMenuView);
+            height = Math.max(height, mMenuView.getMeasuredHeight() +
+                    getVerticalMargins(mMenuView));
+            childState = combineMeasuredStates(childState, mMenuView.getMeasuredState());
+        }
+
+        if (shouldLayout(mLogoView)) {
+            measureChildWithMargins(mLogoView, widthMeasureSpec, width, heightMeasureSpec, 0);
+            width += mLogoView.getMeasuredWidth() + getHorizontalMargins(mLogoView);
+            height = Math.max(height, mLogoView.getMeasuredHeight() +
+                    getVerticalMargins(mLogoView));
+            childState = combineMeasuredStates(childState, mLogoView.getMeasuredState());
+        }
+
+        int titleWidth = 0;
+        int titleHeight = 0;
+        final int titleVertMargins = mTitleMarginTop + mTitleMarginBottom;
+        final int titleHorizMargins = mTitleMarginStart + mTitleMarginEnd;
+        if (shouldLayout(mTitleTextView)) {
+            measureChildWithMargins(mTitleTextView, widthMeasureSpec, width + titleHorizMargins,
+                    heightMeasureSpec, titleVertMargins);
+            titleWidth = mTitleTextView.getMeasuredWidth() + getHorizontalMargins(mTitleTextView);
+            titleHeight = mTitleTextView.getMeasuredHeight() + getVerticalMargins(mTitleTextView);
+            childState = combineMeasuredStates(childState, mTitleTextView.getMeasuredState());
+        }
+        if (shouldLayout(mSubtitleTextView)) {
+            measureChildWithMargins(mSubtitleTextView, widthMeasureSpec, width + titleHorizMargins,
+                    heightMeasureSpec, titleHeight + titleVertMargins);
+            titleWidth = Math.max(titleWidth, mSubtitleTextView.getMeasuredWidth() +
+                    getHorizontalMargins(mSubtitleTextView));
+            titleHeight += mSubtitleTextView.getMeasuredHeight() +
+                    getVerticalMargins(mSubtitleTextView);
+            childState = combineMeasuredStates(childState, mSubtitleTextView.getMeasuredState());
+        }
+
+        width += titleWidth;
+        height = Math.max(height, titleHeight);
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            if (lp.mViewType == LayoutParams.SYSTEM || !shouldLayout(child)) {
+                // We already got all system views above. Skip them and GONE views.
+                continue;
+            }
+
+            measureChildWithMargins(child, widthMeasureSpec, width, heightMeasureSpec, 0);
+            width += child.getMeasuredWidth() + getHorizontalMargins(child);
+            height = Math.max(height, child.getMeasuredHeight() + getVerticalMargins(child));
+            childState = combineMeasuredStates(childState, child.getMeasuredState());
+        }
+
+        // Measurement already took padding into account for available space for the children,
+        // add it in for the final size.
+        width += getPaddingLeft() + getPaddingRight();
+        height += getPaddingTop() + getPaddingBottom();
+
+        final int measuredWidth = resolveSizeAndState(
+                Math.max(width, getSuggestedMinimumWidth()),
+                widthMeasureSpec, childState & MEASURED_STATE_MASK);
+        final int measuredHeight = resolveSizeAndState(
+                Math.max(height, getSuggestedMinimumHeight()),
+                heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT);
+        setMeasuredDimension(measuredWidth, measuredHeight);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+        final int width = getWidth();
+        final int height = getHeight();
+        final int paddingLeft = getPaddingLeft();
+        final int paddingRight = getPaddingRight();
+        final int paddingTop = getPaddingTop();
+        final int paddingBottom = getPaddingBottom();
+        int left = paddingLeft;
+        int right = width - paddingRight;
+
+        if (shouldLayout(mNavButtonView)) {
+            if (isRtl) {
+                right = layoutChildRight(mNavButtonView, right);
+            } else {
+                left = layoutChildLeft(mNavButtonView, left);
+            }
+        }
+
+        if (shouldLayout(mMenuView)) {
+            if (isRtl) {
+                left = layoutChildLeft(mMenuView, left);
+            } else {
+                right = layoutChildRight(mMenuView, right);
+            }
+        }
+
+        if (shouldLayout(mLogoView)) {
+            if (isRtl) {
+                right = layoutChildRight(mLogoView, right);
+            } else {
+                left = layoutChildLeft(mLogoView, left);
+            }
+        }
+
+        final boolean layoutTitle = shouldLayout(mTitleTextView);
+        final boolean layoutSubtitle = shouldLayout(mSubtitleTextView);
+        int titleHeight = 0;
+        if (layoutTitle) {
+            final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+            titleHeight += lp.topMargin + mTitleTextView.getMeasuredHeight() + lp.bottomMargin;
+        }
+        if (layoutSubtitle) {
+            final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+            titleHeight += lp.bottomMargin + mTitleTextView.getMeasuredHeight() + lp.bottomMargin;
+        }
+
+        if (layoutTitle || layoutSubtitle) {
+            int titleTop;
+            switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
+                case Gravity.TOP:
+                    titleTop = getPaddingTop();
+                    break;
+                default:
+                case Gravity.CENTER_VERTICAL:
+                    final View child = layoutTitle ? mTitleTextView : mSubtitleTextView;
+                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                    final int space = height - paddingTop - paddingBottom;
+                    int spaceAbove = (space - titleHeight) / 2;
+                    if (spaceAbove < lp.topMargin + mTitleMarginTop) {
+                        spaceAbove = lp.topMargin + mTitleMarginTop;
+                    } else {
+                        final int spaceBelow = height - paddingBottom - titleHeight -
+                                spaceAbove - paddingTop;
+                        if (spaceBelow < lp.bottomMargin + mTitleMarginBottom) {
+                            spaceAbove = Math.max(0, spaceAbove -
+                                    (lp.bottomMargin + mTitleMarginBottom - spaceBelow));
+                        }
+                    }
+                    titleTop = paddingTop + spaceAbove;
+                    break;
+                case Gravity.BOTTOM:
+                    titleTop = height - paddingBottom - titleHeight;
+                    break;
+            }
+            if (isRtl) {
+                int titleRight = right;
+                int subtitleRight = right;
+                titleTop += mTitleMarginTop;
+                if (layoutTitle) {
+                    final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+                    titleRight -= lp.rightMargin + mTitleMarginStart;
+                    titleTop += lp.topMargin;
+                    final int titleLeft = titleRight - mTitleTextView.getMeasuredWidth();
+                    final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
+                    mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
+                    titleRight = titleLeft - lp.leftMargin - mTitleMarginEnd;
+                    titleTop = titleBottom + lp.bottomMargin;
+                }
+                if (layoutSubtitle) {
+                    final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+                    subtitleRight -= lp.rightMargin + mTitleMarginStart;
+                    titleTop += lp.topMargin;
+                    final int subtitleLeft = subtitleRight - mSubtitleTextView.getMeasuredWidth();
+                    final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
+                    mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
+                    subtitleRight = subtitleRight - lp.leftMargin - mTitleMarginEnd;
+                    titleTop = subtitleBottom + lp.bottomMargin;
+                }
+                right = Math.max(titleRight, subtitleRight);
+            } else {
+                int titleLeft = left;
+                int subtitleLeft = left;
+                titleTop += mTitleMarginTop;
+                if (layoutTitle) {
+                    final LayoutParams lp = (LayoutParams) mTitleTextView.getLayoutParams();
+                    titleLeft += lp.leftMargin + mTitleMarginStart;
+                    titleTop += lp.topMargin;
+                    final int titleRight = titleLeft + mTitleTextView.getMeasuredWidth();
+                    final int titleBottom = titleTop + mTitleTextView.getMeasuredHeight();
+                    mTitleTextView.layout(titleLeft, titleTop, titleRight, titleBottom);
+                    titleLeft = titleRight + lp.rightMargin + mTitleMarginEnd;
+                    titleTop = titleBottom + lp.bottomMargin;
+                }
+                if (layoutSubtitle) {
+                    final LayoutParams lp = (LayoutParams) mSubtitleTextView.getLayoutParams();
+                    subtitleLeft += lp.leftMargin + mTitleMarginStart;
+                    titleTop += lp.topMargin;
+                    final int subtitleRight = subtitleLeft + mSubtitleTextView.getMeasuredWidth();
+                    final int subtitleBottom = titleTop + mSubtitleTextView.getMeasuredHeight();
+                    mSubtitleTextView.layout(subtitleLeft, titleTop, subtitleRight, subtitleBottom);
+                    subtitleLeft = subtitleRight + lp.rightMargin + mTitleMarginEnd;
+                    titleTop = subtitleBottom + lp.bottomMargin;
+                }
+                left = Math.max(titleLeft, subtitleLeft);
+            }
+        }
+
+        // Get all remaining children sorted for layout. This is all prepared
+        // such that absolute layout direction can be used below.
+
+        addCustomViewsWithGravity(mTempViews, Gravity.LEFT);
+        final int leftViewsCount = mTempViews.size();
+        for (int i = 0; i < leftViewsCount; i++) {
+            left = layoutChildLeft(getChildAt(i), left);
+        }
+
+        addCustomViewsWithGravity(mTempViews, Gravity.RIGHT);
+        final int rightViewsCount = mTempViews.size();
+        for (int i = 0; i < rightViewsCount; i++) {
+            right = layoutChildRight(getChildAt(i), right);
+        }
+
+        // Centered views try to center with respect to the whole bar, but views pinned
+        // to the left or right can push the mass of centered views to one side or the other.
+        addCustomViewsWithGravity(mTempViews, Gravity.CENTER);
+        final int centerViewsWidth = getViewListMeasuredWidth(mTempViews);
+        final int parentCenter = paddingLeft + (width - paddingLeft - paddingRight) / 2;
+        final int halfCenterViewsWidth = centerViewsWidth / 2;
+        int centerLeft = parentCenter - halfCenterViewsWidth;
+        final int centerRight = centerLeft + centerViewsWidth;
+        if (centerLeft < left) {
+            centerLeft = left;
+        } else if (centerRight > right) {
+            centerLeft -= centerRight - right;
+        }
+
+        final int centerViewsCount = mTempViews.size();
+        for (int i = 0; i < centerViewsCount; i++) {
+            centerLeft = layoutChildLeft(getChildAt(i), centerLeft);
+        }
+        mTempViews.clear();
+    }
+
+    private int getViewListMeasuredWidth(List<View> views) {
+        int width = 0;
+        final int count = views.size();
+        for (int i = 0; i < count; i++) {
+            final View v = views.get(i);
+            final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+            width += lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
+        }
+        return width;
+    }
+
+    private int layoutChildLeft(View child, int left) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+        left += lp.leftMargin;
+        int top = getChildTop(child);
+        child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
+        left += lp.rightMargin;
+        return left;
+    }
+
+    private int layoutChildRight(View child, int right) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+        right -= lp.rightMargin;
+        int top = getChildTop(child);
+        child.layout(right - child.getMeasuredWidth(), top, right, top + child.getMeasuredHeight());
+        right -= lp.leftMargin;
+        return right;
+    }
+
+    private int getChildTop(View child) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+        switch (getChildVerticalGravity(lp.gravity)) {
+            case Gravity.TOP:
+                return getPaddingTop();
+
+            case Gravity.BOTTOM:
+                return getPaddingBottom() - child.getMeasuredHeight() - lp.bottomMargin;
+
+            default:
+            case Gravity.CENTER_VERTICAL:
+                final int paddingTop = getPaddingTop();
+                final int paddingBottom = getPaddingBottom();
+                final int height = getHeight();
+                final int childHeight = child.getMeasuredHeight();
+                final int space = height - paddingTop - paddingBottom;
+                int spaceAbove = (space - childHeight) / 2;
+                if (spaceAbove < lp.topMargin) {
+                    spaceAbove = lp.topMargin;
+                } else {
+                    final int spaceBelow = height - paddingBottom - childHeight -
+                            spaceAbove - paddingTop;
+                    if (spaceBelow < lp.bottomMargin) {
+                        spaceAbove = Math.max(0, spaceAbove - (lp.bottomMargin - spaceBelow));
+                    }
+                }
+                return paddingTop + spaceAbove;
+        }
+    }
+
+    private int getChildVerticalGravity(int gravity) {
+        final int vgrav = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+        switch (vgrav) {
+            case Gravity.TOP:
+            case Gravity.BOTTOM:
+            case Gravity.CENTER_VERTICAL:
+                return vgrav;
+            default:
+                return mGravity & Gravity.VERTICAL_GRAVITY_MASK;
+        }
+    }
+
+    /**
+     * Prepare a list of non-SYSTEM child views. If the layout direction is RTL
+     * this will be in reverse child order.
+     *
+     * @param views List to populate. It will be cleared before use.
+     * @param gravity Horizontal gravity to match against
+     */
+    private void addCustomViewsWithGravity(List<View> views, int gravity) {
+        final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+        final int childCount = getChildCount();
+        final int absGrav = Gravity.getAbsoluteGravity(gravity, getLayoutDirection());
+
+        views.clear();
+
+        if (isRtl) {
+            for (int i = childCount - 1; i >= 0; i--) {
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                if (lp.mViewType != LayoutParams.SYSTEM && shouldLayout(child) &&
+                        getChildHorizontalGravity(lp.gravity) == absGrav) {
+                    views.add(child);
+                }
+
+            }
+        } else {
+            for (int i = 0; i < childCount; i++) {
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                if (lp.mViewType != LayoutParams.SYSTEM && shouldLayout(child) &&
+                        getChildHorizontalGravity(lp.gravity) == absGrav) {
+                    views.add(child);
+                }
+            }
+        }
+    }
+
+    private int getChildHorizontalGravity(int gravity) {
+        final int ld = getLayoutDirection();
+        final int absGrav = Gravity.getAbsoluteGravity(gravity, ld);
+        final int hGrav = absGrav & Gravity.HORIZONTAL_GRAVITY_MASK;
+        switch (hGrav) {
+            case Gravity.LEFT:
+            case Gravity.RIGHT:
+            case Gravity.CENTER_HORIZONTAL:
+                return hGrav;
+            default:
+                return ld == LAYOUT_DIRECTION_RTL ? Gravity.RIGHT : Gravity.LEFT;
+        }
+    }
+
+    private boolean shouldLayout(View view) {
+        return view != null && view.getParent() == this && view.getVisibility() != GONE;
+    }
+
+    private int getHorizontalMargins(View v) {
+        final MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
+        return mlp.getMarginStart() + mlp.getMarginEnd();
+    }
+
+    private int getVerticalMargins(View v) {
+        final MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
+        return mlp.topMargin + mlp.bottomMargin;
+    }
+
+    @Override
+    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return super.generateLayoutParams(attrs);
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        if (p instanceof LayoutParams) {
+            return new LayoutParams((LayoutParams) p);
+        } else if (p instanceof MarginLayoutParams) {
+            return new LayoutParams((MarginLayoutParams) p);
+        } else {
+            return new LayoutParams(p);
+        }
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return super.checkLayoutParams(p) && p instanceof LayoutParams;
+    }
+
+    private static boolean isCustomView(View child) {
+        return ((LayoutParams) child.getLayoutParams()).mViewType == LayoutParams.CUSTOM;
+    }
+
+    /**
+     * Interface responsible for receiving menu item click events if the items themselves
+     * do not have individual item click listeners.
+     */
+    public interface OnMenuItemClickListener {
+        /**
+         * This method will be invoked when a menu item is clicked if the item itself did
+         * not already handle the event.
+         *
+         * @param item {@link MenuItem} that was clicked
+         * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
+         */
+        public boolean onMenuItemClick(MenuItem item);
+    }
+
+    /**
+     * Layout information for child views of Toolbars.
+     *
+     * @attr ref android.R.styleable#Toolbar_LayoutParams_layout_gravity
+     */
+    public static class LayoutParams extends MarginLayoutParams {
+        /**
+         * Gravity for the view associated with these LayoutParams.
+         *
+         * @see android.view.Gravity
+         */
+        @ViewDebug.ExportedProperty(category = "layout", mapping = {
+                @ViewDebug.IntToString(from =  -1,                       to = "NONE"),
+                @ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
+                @ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
+                @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
+                @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
+                @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
+                @ViewDebug.IntToString(from = Gravity.START,             to = "START"),
+                @ViewDebug.IntToString(from = Gravity.END,               to = "END"),
+                @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
+                @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
+                @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
+                @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
+                @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
+                @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
+        })
+        public int gravity = Gravity.NO_GRAVITY;
+
+        static final int CUSTOM = 0;
+        static final int SYSTEM = 1;
+
+        int mViewType = CUSTOM;
+
+        public LayoutParams(@NonNull Context c, AttributeSet attrs) {
+            super(c, attrs);
+
+            TypedArray a = c.obtainStyledAttributes(attrs,
+                    com.android.internal.R.styleable.Toolbar_LayoutParams);
+            gravity = a.getInt(
+                    com.android.internal.R.styleable.Toolbar_LayoutParams_layout_gravity,
+                    Gravity.NO_GRAVITY);
+            a.recycle();
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+            this.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
+        }
+
+        public LayoutParams(int width, int height, int gravity) {
+            super(width, height);
+            this.gravity = gravity;
+        }
+
+        public LayoutParams(int gravity) {
+            this(WRAP_CONTENT, MATCH_PARENT, gravity);
+        }
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+
+            this.gravity = source.gravity;
+        }
+
+        public LayoutParams(MarginLayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+        }
+    }
+
+    static class SavedState extends BaseSavedState {
+        public SavedState(Parcel source) {
+            super(source);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+        }
+
+        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+            @Override
+            public SavedState createFromParcel(Parcel source) {
+                return new SavedState(source);
+            }
+
+            @Override
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
new file mode 100644
index 0000000..34156e5
--- /dev/null
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.annotation.Nullable;
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
+import android.view.ActionMode;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.SpinnerAdapter;
+import android.widget.Toolbar;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public class ToolbarActionBar extends ActionBar {
+    private Toolbar mToolbar;
+    private View mCustomView;
+
+    private int mDisplayOptions;
+
+    private int mNavResId;
+    private int mIconResId;
+    private int mLogoResId;
+    private Drawable mNavDrawable;
+    private Drawable mIconDrawable;
+    private Drawable mLogoDrawable;
+    private int mTitleResId;
+    private int mSubtitleResId;
+    private CharSequence mTitle;
+    private CharSequence mSubtitle;
+
+    private boolean mLastMenuVisibility;
+    private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
+            new ArrayList<OnMenuVisibilityListener>();
+
+    public ToolbarActionBar(Toolbar toolbar) {
+        mToolbar = toolbar;
+    }
+
+    @Override
+    public void setCustomView(View view) {
+        setCustomView(view, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+    }
+
+    @Override
+    public void setCustomView(View view, LayoutParams layoutParams) {
+        if (mCustomView != null) {
+            mToolbar.removeView(mCustomView);
+        }
+        mCustomView = view;
+        if (view != null) {
+            mToolbar.addView(view, generateLayoutParams(layoutParams));
+        }
+    }
+
+    private Toolbar.LayoutParams generateLayoutParams(LayoutParams lp) {
+        final Toolbar.LayoutParams result = new Toolbar.LayoutParams(lp);
+        result.gravity = lp.gravity;
+        return result;
+    }
+
+    @Override
+    public void setCustomView(int resId) {
+        final LayoutInflater inflater = LayoutInflater.from(mToolbar.getContext());
+        setCustomView(inflater.inflate(resId, mToolbar, false));
+    }
+
+    @Override
+    public void setIcon(int resId) {
+        mIconResId = resId;
+        mIconDrawable = null;
+        updateToolbarLogo();
+    }
+
+    @Override
+    public void setIcon(Drawable icon) {
+        mIconResId = 0;
+        mIconDrawable = icon;
+        updateToolbarLogo();
+    }
+
+    @Override
+    public void setLogo(int resId) {
+        mLogoResId = resId;
+        mLogoDrawable = null;
+        updateToolbarLogo();
+    }
+
+    @Override
+    public void setLogo(Drawable logo) {
+        mLogoResId = 0;
+        mLogoDrawable = logo;
+        updateToolbarLogo();
+    }
+
+    private void updateToolbarLogo() {
+        Drawable drawable = null;
+        if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
+            final int resId;
+            if ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
+                resId = mLogoResId;
+                drawable = mLogoDrawable;
+            } else {
+                resId = mIconResId;
+                drawable = mIconDrawable;
+            }
+            if (resId != 0) {
+                drawable = mToolbar.getContext().getDrawable(resId);
+            }
+        }
+        mToolbar.setLogo(drawable);
+    }
+
+    @Override
+    public void setStackedBackgroundDrawable(Drawable d) {
+        // This space for rent (do nothing)
+    }
+
+    @Override
+    public void setSplitBackgroundDrawable(Drawable d) {
+        // This space for rent (do nothing)
+    }
+
+    @Override
+    public void setHomeButtonEnabled(boolean enabled) {
+        // If the nav button on a Toolbar is present, it's enabled. No-op.
+    }
+
+    @Override
+    public Context getThemedContext() {
+        return mToolbar.getContext();
+    }
+
+    @Override
+    public boolean isTitleTruncated() {
+        return super.isTitleTruncated();
+    }
+
+    @Override
+    public void setHomeAsUpIndicator(Drawable indicator) {
+        mToolbar.setNavigationIcon(indicator);
+    }
+
+    @Override
+    public void setHomeAsUpIndicator(int resId) {
+        mToolbar.setNavigationIcon(resId);
+    }
+
+    @Override
+    public void setHomeActionContentDescription(CharSequence description) {
+        mToolbar.setNavigationDescription(description);
+    }
+
+    @Override
+    public void setDefaultDisplayHomeAsUpEnabled(boolean enabled) {
+        // Do nothing
+    }
+
+    @Override
+    public void setHomeActionContentDescription(int resId) {
+        mToolbar.setNavigationDescription(resId);
+    }
+
+    @Override
+    public void setShowHideAnimationEnabled(boolean enabled) {
+        // This space for rent; no-op.
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration config) {
+        super.onConfigurationChanged(config);
+    }
+
+    @Override
+    public ActionMode startActionMode(ActionMode.Callback callback) {
+        return mToolbar.startActionMode(callback);
+    }
+
+    @Override
+    public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void setSelectedNavigationItem(int position) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public int getSelectedNavigationIndex() {
+        return -1;
+    }
+
+    @Override
+    public int getNavigationItemCount() {
+        return 0;
+    }
+
+    @Override
+    public void setTitle(CharSequence title) {
+        mTitle = title;
+        mTitleResId = 0;
+        updateToolbarTitle();
+    }
+
+    @Override
+    public void setTitle(int resId) {
+        mTitleResId = resId;
+        mTitle = null;
+        updateToolbarTitle();
+    }
+
+    @Override
+    public void setSubtitle(CharSequence subtitle) {
+        mSubtitle = subtitle;
+        mSubtitleResId = 0;
+        updateToolbarTitle();
+    }
+
+    @Override
+    public void setSubtitle(int resId) {
+        mSubtitleResId = resId;
+        mSubtitle = null;
+        updateToolbarTitle();
+    }
+
+    private void updateToolbarTitle() {
+        final Context context = mToolbar.getContext();
+        CharSequence title = null;
+        CharSequence subtitle = null;
+        if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+            title = mTitleResId != 0 ? context.getText(mTitleResId) : mTitle;
+            subtitle = mSubtitleResId != 0 ? context.getText(mSubtitleResId) : mSubtitle;
+        }
+        mToolbar.setTitle(title);
+        mToolbar.setSubtitle(subtitle);
+    }
+
+    @Override
+    public void setDisplayOptions(@DisplayOptions int options) {
+        setDisplayOptions(options, 0xffffffff);
+    }
+
+    @Override
+    public void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask) {
+        final int oldOptions = mDisplayOptions;
+        mDisplayOptions = (options & mask) | (mDisplayOptions & ~mask);
+        final int optionsChanged = oldOptions ^ mDisplayOptions;
+    }
+
+    @Override
+    public void setDisplayUseLogoEnabled(boolean useLogo) {
+        setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
+    }
+
+    @Override
+    public void setDisplayShowHomeEnabled(boolean showHome) {
+        setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
+    }
+
+    @Override
+    public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
+        setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
+    }
+
+    @Override
+    public void setDisplayShowTitleEnabled(boolean showTitle) {
+        setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
+    }
+
+    @Override
+    public void setDisplayShowCustomEnabled(boolean showCustom) {
+        setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
+    }
+
+    @Override
+    public void setBackgroundDrawable(@Nullable Drawable d) {
+        mToolbar.setBackground(d);
+    }
+
+    @Override
+    public View getCustomView() {
+        return mCustomView;
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        return mToolbar.getTitle();
+    }
+
+    @Override
+    public CharSequence getSubtitle() {
+        return mToolbar.getSubtitle();
+    }
+
+    @Override
+    public int getNavigationMode() {
+        return NAVIGATION_MODE_STANDARD;
+    }
+
+    @Override
+    public void setNavigationMode(@NavigationMode int mode) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public int getDisplayOptions() {
+        return mDisplayOptions;
+    }
+
+    @Override
+    public Tab newTab() {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void addTab(Tab tab) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void addTab(Tab tab, boolean setSelected) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void addTab(Tab tab, int position) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void addTab(Tab tab, int position, boolean setSelected) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void removeTab(Tab tab) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void removeTabAt(int position) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void removeAllTabs() {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public void selectTab(Tab tab) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public Tab getSelectedTab() {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public Tab getTabAt(int index) {
+        throw new UnsupportedOperationException(
+                "Navigation modes are not supported in toolbar action bars");
+    }
+
+    @Override
+    public int getTabCount() {
+        return 0;
+    }
+
+    @Override
+    public int getHeight() {
+        return mToolbar.getHeight();
+    }
+
+    @Override
+    public void show() {
+        // TODO: Consider a better transition for this.
+        // Right now use no automatic transition so that the app can supply one if desired.
+        mToolbar.setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    public void hide() {
+        // TODO: Consider a better transition for this.
+        // Right now use no automatic transition so that the app can supply one if desired.
+        mToolbar.setVisibility(View.GONE);
+    }
+
+    @Override
+    public boolean isShowing() {
+        return mToolbar.getVisibility() == View.VISIBLE;
+    }
+
+    public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+        mMenuVisibilityListeners.add(listener);
+    }
+
+    public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+        mMenuVisibilityListeners.remove(listener);
+    }
+
+    public void dispatchMenuVisibilityChanged(boolean isVisible) {
+        if (isVisible == mLastMenuVisibility) {
+            return;
+        }
+        mLastMenuVisibility = isVisible;
+
+        final int count = mMenuVisibilityListeners.size();
+        for (int i = 0; i < count; i++) {
+            mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
+        }
+    }
+
+    @Override
+    public void captureSharedElements(Map<String, View> sharedElements) {
+        mToolbar.findSharedElements(sharedElements);
+    }
+}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
similarity index 98%
rename from core/java/com/android/internal/app/ActionBarImpl.java
rename to core/java/com/android/internal/app/WindowDecorActionBar.java
index cc51a8b..c6afae0 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -60,14 +60,14 @@
 import java.util.Map;
 
 /**
- * ActionBarImpl is the ActionBar implementation used
- * by devices of all screen sizes. If it detects a compatible decor,
- * it will split contextual modes across both the ActionBarView at
- * the top of the screen and a horizontal LinearLayout at the bottom
- * which is normally hidden.
+ * WindowDecorActionBar is the ActionBar implementation used
+ * by devices of all screen sizes as part of the window decor layout.
+ * If it detects a compatible decor, it will split contextual modes
+ * across both the ActionBarView at the top of the screen and
+ * a horizontal LinearLayout at the bottom which is normally hidden.
  */
-public class ActionBarImpl extends ActionBar {
-    private static final String TAG = "ActionBarImpl";
+public class WindowDecorActionBar extends ActionBar {
+    private static final String TAG = "WindowDecorActionBar";
 
     private Context mContext;
     private Context mThemedContext;
@@ -105,9 +105,6 @@
     private int mContextDisplayMode;
     private boolean mHasEmbeddedTabs;
 
-    final Handler mHandler = new Handler();
-    Runnable mTabSelector;
-
     private int mCurWindowVisibility = View.VISIBLE;
 
     private boolean mContentAnimations = true;
@@ -157,7 +154,7 @@
         }
     };
 
-    public ActionBarImpl(Activity activity) {
+    public WindowDecorActionBar(Activity activity) {
         mActivity = activity;
         Window window = activity.getWindow();
         View decor = window.getDecorView();
@@ -168,13 +165,12 @@
         }
     }
 
-    public ActionBarImpl(Dialog dialog) {
+    public WindowDecorActionBar(Dialog dialog) {
         mDialog = dialog;
         init(dialog.getWindow().getDecorView());
     }
 
     private void init(View decor) {
-        mContext = decor.getContext();
         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
                 com.android.internal.R.id.action_bar_overlay_layout);
         if (mOverlayLayout != null) {
@@ -193,6 +189,7 @@
                     "with a compatible window decor layout");
         }
 
+        mContext = mActionView.getContext();
         mActionView.setContextView(mContextView);
         mContextDisplayMode = mActionView.isSplitActionBar() ?
                 CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 31ca3de..9df8ad5 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -242,7 +242,11 @@
     public boolean anyPackagesDisappearing() {
         return mDisappearingPackages != null;
     }
-    
+
+    public boolean isReplacing() {
+        return mChangeType == PACKAGE_UPDATING;
+    }
+
     public boolean isPackageModified(String packageName) {
         if (mModifiedPackages != null) {
             for (int i=mModifiedPackages.length-1; i>=0; i--) {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 03a053c..ac3274d 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -504,7 +504,7 @@
 
         private String mEnabledInputMethodsStrCache;
         private int mCurrentUserId;
-        private int[] mRelatedUserIds = new int[0];
+        private int[] mCurrentProfileIds = new int[0];
 
         private static void buildEnabledInputMethodsSettingString(
                 StringBuilder builder, Pair<String, ArrayList<String>> pair) {
@@ -537,17 +537,17 @@
             mCurrentUserId = userId;
         }
 
-        public void setRelatedUserIds(int[] relatedUserIds) {
+        public void setCurrentProfileIds(int[] currentProfileIds) {
             synchronized (this) {
-                mRelatedUserIds = relatedUserIds;
+                mCurrentProfileIds = currentProfileIds;
             }
         }
 
-        public boolean isRelatedToOrCurrentUser(int userId) {
+        public boolean isCurrentProfile(int userId) {
             synchronized (this) {
                 if (userId == mCurrentUserId) return true;
-                for (int i = 0; i < mRelatedUserIds.length; i++) {
-                    if (userId == mRelatedUserIds[i]) return true;
+                for (int i = 0; i < mCurrentProfileIds.length; i++) {
+                    if (userId == mCurrentProfileIds[i]) return true;
                 }
                 return false;
             }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 39636fe..4c11fa9 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -574,6 +574,7 @@
             mUptime = in.readLong();
             mPastUptime = in.readLong();
             mUptimeStart = in.readLong();
+            mRealtime = in.readLong();
             mPastRealtime = in.readLong();
             mRealtimeStart = in.readLong();
             mUnpluggedUptime = in.readLong();
@@ -586,6 +587,7 @@
             out.writeLong(mUptime);
             out.writeLong(runningUptime);
             out.writeLong(mUptimeStart);
+            out.writeLong(mRealtime);
             out.writeLong(runningRealtime);
             out.writeLong(mRealtimeStart);
             out.writeLong(mUnpluggedUptime);
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 1766f7b..3301cbe 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -26,8 +26,6 @@
 
 import libcore.io.IoUtils;
 
-import dalvik.system.Zygote;
-
 /**
  * Startup class for the wrapper process.
  * @hide
@@ -94,7 +92,7 @@
      * @param niceName The nice name for the application, or null if none.
      * @param targetSdkVersion The target SDK version for the app.
      * @param pipeFd The pipe to which the application's pid should be written, or null if none.
-     * @param args Arguments for {@link RuntimeInit.main}.
+     * @param args Arguments for {@link RuntimeInit#main}.
      */
     public static void execApplication(String invokeWith, String niceName,
             int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
new file mode 100644
index 0000000..c5fa0a1
--- /dev/null
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import dalvik.system.ZygoteHooks;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
+/** @hide */
+public final class Zygote {
+    /*
+    * Bit values for "debugFlags" argument.  The definitions are duplicated
+    * in the native code.
+    */
+
+    /** enable debugging over JDWP */
+    public static final int DEBUG_ENABLE_DEBUGGER   = 1;
+    /** enable JNI checks */
+    public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
+    /** enable Java programming language "assert" statements */
+    public static final int DEBUG_ENABLE_ASSERT     = 1 << 2;
+    /** disable the JIT compiler */
+    public static final int DEBUG_ENABLE_SAFEMODE   = 1 << 3;
+    /** Enable logging of third-party JNI activity. */
+    public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
+
+    /** No external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_NONE = 0;
+    /** Single-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
+    /** Multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
+    /** All multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+
+    private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
+
+    private Zygote() {}
+
+    /**
+     * Forks a new VM instance.  The current VM must have been started
+     * with the -Xzygote flag. <b>NOTE: new instance keeps all
+     * root capabilities. The new process is expected to call capset()</b>.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param seInfo null-ok a string specifying SELinux information for
+     * the new process.
+     * @param niceName null-ok a string specifying the process name.
+     * @param fdsToClose an array of ints, holding one or more POSIX
+     * file descriptor numbers that are to be closed by the child
+     * (and replaced by /dev/null) after forking.  An integer value
+     * of -1 in any entry in the array means "ignore this one".
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkAndSpecialize(
+                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+
+    /**
+     * Special method to start the system server process. In addition to the
+     * common actions performed in forkAndSpecialize, the pid of the child
+     * process is recorded such that the death of the child process will cause
+     * zygote to exit.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param permittedCapabilities argument for setcap()
+     * @param effectiveCapabilities argument for setcap()
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkSystemServer(
+                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
+
+    private static void callPostForkChildHooks(int debugFlags) {
+        VM_HOOKS.postForkChild(debugFlags);
+    }
+
+
+    /**
+     * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
+     * This method throws a runtime exception if exec() failed, otherwise, this
+     * method never returns.
+     *
+     * @param command The shell command to execute.
+     */
+    public static void execShell(String command) {
+        String[] args = { "/system/bin/sh", "-c", command };
+        try {
+            Libcore.os.execv(args[0], args);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Appends quotes shell arguments to the specified string builder.
+     * The arguments are quoted using single-quotes, escaped if necessary,
+     * prefixed with a space, and appended to the command.
+     *
+     * @param command A string builder for the shell command being constructed.
+     * @param args An array of argument strings to be quoted and appended to the command.
+     * @see #execShell(String)
+     */
+    public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
+        for (String arg : args) {
+            command.append(" '").append(arg.replace("'", "'\\''")).append("'");
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f9a1f89..aad534c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 
 import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -807,7 +806,7 @@
     /**
      * Applies invoke-with system properties to the zygote arguments.
      *
-     * @param parsedArgs non-null; zygote args
+     * @param args non-null; zygote args
      */
     public static void applyInvokeWithSystemProperty(Arguments args) {
         if (args.invokeWith == null && args.niceName != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 05c57e8..66cc120 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,7 +32,6 @@
 import android.util.Log;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 4734712..dfdb9ae 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -41,6 +41,7 @@
             out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
             out int[] switches, out List<IBinder> binders);
     void onPanelRevealed();
+    void onPanelHidden();
     void onNotificationClick(String pkg, String tag, int id, int userId);
     void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId);
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index ce4312d..9e8d12b 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -27,4 +27,5 @@
     void onBindMethod(in InputBindResult res);
     void onUnbindMethod(int sequence);
     void setActive(boolean active);
+    void setCursorAnchorMonitorMode(int monitorMode);
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 45ca7fc..5336174 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -78,4 +78,5 @@
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
     int getInputMethodWindowVisibleHeight();
     oneway void notifyTextCommitted();
+    void setCursorAnchorMonitorMode(in IBinder token, int monitorMode);
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 3cceebe..891baea 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -282,11 +282,6 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
-            // Fill all available height.
-            heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                    MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);
-        }
         final boolean textVisible = hasText();
         if (textVisible && mSavedPaddingLeft >= 0) {
             super.setPadding(mSavedPaddingLeft, getPaddingTop(),
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index c2d22dd..ed07514 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -43,6 +43,7 @@
     private Drawable mSplitBackground;
     private boolean mIsSplit;
     private boolean mIsStacked;
+    private int mHeight;
 
     public ActionBarContainer(Context context) {
         this(context, null);
@@ -59,6 +60,7 @@
         mBackground = a.getDrawable(com.android.internal.R.styleable.ActionBar_background);
         mStackedBackground = a.getDrawable(
                 com.android.internal.R.styleable.ActionBar_backgroundStacked);
+        mHeight = a.getDimensionPixelSize(com.android.internal.R.styleable.ActionBar_height, -1);
 
         if (getId() == com.android.internal.R.id.split_action_bar) {
             mIsSplit = true;
@@ -251,6 +253,11 @@
 
     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mActionBarView == null &&
+                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST && mHeight >= 0) {
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                    Math.min(mHeight, MeasureSpec.getSize(heightMeasureSpec)), MeasureSpec.AT_MOST);
+        }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
         if (mActionBarView == null) return;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index adb9bf8..c9dff1a 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -21,7 +21,7 @@
 import android.os.Build;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
-import com.android.internal.app.ActionBarImpl;
+import com.android.internal.app.WindowDecorActionBar;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -38,7 +38,7 @@
     private static final String TAG = "ActionBarOverlayLayout";
 
     private int mActionBarHeight;
-    private ActionBarImpl mActionBar;
+    private WindowDecorActionBar mActionBar;
     private int mWindowVisibility = View.VISIBLE;
 
     // The main UI elements that we handle the layout of.
@@ -88,7 +88,7 @@
                 Build.VERSION_CODES.KITKAT;
     }
 
-    public void setActionBar(ActionBarImpl impl) {
+    public void setActionBar(WindowDecorActionBar impl) {
         mActionBar = impl;
         if (getWindowToken() != null) {
             // This is being initialized after being added to a window;
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 1273c4d..60631b9 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -430,7 +430,7 @@
             mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
             // Span the whole width
             layoutParams.width = LayoutParams.MATCH_PARENT;
-            layoutParams.height = mContentHeight;
+            layoutParams.height = LayoutParams.WRAP_CONTENT;
             configPresenters(builder);
             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
             if (mSplitView != null) {
diff --git a/core/java/com/android/internal/widget/AutoScrollHelper.java b/core/java/com/android/internal/widget/AutoScrollHelper.java
index 7a294aa..0d468ca 100644
--- a/core/java/com/android/internal/widget/AutoScrollHelper.java
+++ b/core/java/com/android/internal/widget/AutoScrollHelper.java
@@ -892,6 +892,10 @@
         public boolean canTargetScrollVertically(int direction) {
             final AbsListView target = mTarget;
             final int itemCount = target.getCount();
+            if (itemCount == 0) {
+                return false;
+            }
+
             final int childCount = target.getChildCount();
             final int firstPosition = target.getFirstVisiblePosition();
             final int lastPosition = firstPosition + childCount;
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 91056f1..9501f92 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -28,6 +28,7 @@
     boolean checkPattern(in String pattern, int userId);
     void setLockPassword(in String password, int userId);
     boolean checkPassword(in String password, int userId);
+    boolean checkVoldPassword(int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
     void removeUser(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2d79491..4504910 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -19,11 +19,14 @@
 import android.Manifest;
 import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
 import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -46,6 +49,8 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -145,6 +150,8 @@
     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
 
+    private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
+
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private DevicePolicyManager mDevicePolicyManager;
@@ -167,6 +174,15 @@
         return mDevicePolicyManager;
     }
 
+    private TrustManager getTrustManager() {
+        TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+        if (trust == null) {
+            Log.e(TAG, "Can't get TrustManagerService: is it running?",
+                    new IllegalStateException("Stack trace:"));
+        }
+        return trust;
+    }
+
     /**
      * @param contentResolver Used to look up and save settings.
      */
@@ -242,10 +258,14 @@
      */
     public void reportFailedPasswordAttempt() {
         getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId());
+        getTrustManager().reportUnlockAttempt(false /* authenticated */,
+                getCurrentOrCallingUserId());
     }
 
     public void reportSuccessfulPasswordAttempt() {
         getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
+        getTrustManager().reportUnlockAttempt(true /* authenticated */,
+                getCurrentOrCallingUserId());
     }
 
     public void setCurrentUser(int userId) {
@@ -313,6 +333,20 @@
     }
 
     /**
+     * Check to see if vold already has the password.
+     * Note that this also clears vold's copy of the password.
+     * @return Whether the vold password matches or not.
+     */
+    public boolean checkVoldPassword() {
+        final int userId = getCurrentOrCallingUserId();
+        try {
+            return getLockSettings().checkVoldPassword(userId);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+    /**
      * Check to see if a password matches any of the passwords stored in the
      * password history.
      *
@@ -496,11 +530,12 @@
      */
     public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
         try {
-            getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId());
+            int userId = getCurrentOrCallingUserId();
+            getLockSettings().setLockPattern(patternToString(pattern), userId);
             DevicePolicyManager dpm = getDevicePolicyManager();
             if (pattern != null) {
 
-                int userHandle = getCurrentOrCallingUserId();
+                int userHandle = userId;
                 if (userHandle == UserHandle.USER_OWNER) {
                     String stringPattern = patternToString(pattern);
                     updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
@@ -511,30 +546,55 @@
                     deleteGallery();
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
-                            pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+                            pattern.size(), 0, 0, 0, 0, 0, 0, userId);
                 } else {
                     setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
                     setLong(PASSWORD_TYPE_ALTERNATE_KEY,
                             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
                     finishBiometricWeak();
                     dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
-                            0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+                            0, 0, 0, 0, 0, 0, 0, userId);
                 }
             } else {
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
-                        0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+                        0, 0, 0, 0, 0, userId);
             }
         } catch (RemoteException re) {
             Log.e(TAG, "Couldn't save lock pattern " + re);
         }
     }
 
+    private void updateCryptoUserInfo() {
+        int userId = getCurrentOrCallingUserId();
+        if (userId != UserHandle.USER_OWNER) {
+            return;
+        }
+
+        final String ownerInfo = isOwnerInfoEnabled() ? getOwnerInfo(userId) : "";
+
+        IBinder service = ServiceManager.getService("mount");
+        if (service == null) {
+            Log.e(TAG, "Could not find the mount service to update the user info");
+            return;
+        }
+
+        IMountService mountService = IMountService.Stub.asInterface(service);
+        try {
+            Log.d(TAG, "Setting owner info");
+            mountService.setField("OwnerInfo", ownerInfo);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error changing user info", e);
+        }
+    }
+
     public void setOwnerInfo(String info, int userId) {
         setString(LOCK_SCREEN_OWNER_INFO, info, userId);
+        updateCryptoUserInfo();
     }
 
     public void setOwnerInfoEnabled(boolean enabled) {
         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled);
+        updateCryptoUserInfo();
     }
 
     public String getOwnerInfo(int userId) {
@@ -1374,4 +1434,38 @@
         setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId);
     }
 
+    public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents) {
+        setEnabledTrustAgents(activeTrustAgents, getCurrentOrCallingUserId());
+    }
+
+    public List<ComponentName> getEnabledTrustAgents() {
+        return getEnabledTrustAgents(getCurrentOrCallingUserId());
+    }
+
+    public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
+        StringBuilder sb = new StringBuilder();
+        for (ComponentName cn : activeTrustAgents) {
+            if (sb.length() > 0) {
+                sb.append(',');
+            }
+            sb.append(cn.flattenToShortString());
+        }
+        setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
+        getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
+    }
+
+    public List<ComponentName> getEnabledTrustAgents(int userId) {
+        String serialized = getString(ENABLED_TRUST_AGENTS, userId);
+        if (TextUtils.isEmpty(serialized)) {
+            return null;
+        }
+        String[] split = serialized.split(",");
+        ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
+        for (String s : split) {
+            if (!TextUtils.isEmpty(s)) {
+                activeTrustAgents.add(ComponentName.unflattenFromString(s));
+            }
+        }
+        return activeTrustAgents;
+    }
 }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 26cb4e5..36ed344 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -32,6 +32,7 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
@@ -260,13 +261,23 @@
 
         mPathPaint.setAntiAlias(true);
         mPathPaint.setDither(true);
-        mPathPaint.setColor(Color.WHITE);   // TODO this should be from the style
+
+        int defaultColor = Color.WHITE;
+        TypedValue outValue = new TypedValue();
+        if (context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, outValue, true)) {
+            defaultColor = context.getResources().getColor(outValue.resourceId);
+        }
+
+        final int color = a.getColor(R.styleable.LockPatternView_pathColor, defaultColor);
+        mPathPaint.setColor(color);
+
         mPathPaint.setAlpha(mStrokeAlpha);
         mPathPaint.setStyle(Paint.Style.STROKE);
         mPathPaint.setStrokeJoin(Paint.Join.ROUND);
         mPathPaint.setStrokeCap(Paint.Cap.ROUND);
 
         // lot's of bitmaps!
+        // TODO: those bitmaps are hardcoded to the Holo Theme which should not be the case!
         mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo);
         mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo);
         mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default_holo);
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
deleted file mode 100644
index 4648f39..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * A special widget containing a center and outer ring. Moving the center ring to the outer ring
- * causes an event that can be caught by implementing OnTriggerListener.
- */
-public class MultiWaveView extends View {
-    private static final String TAG = "MultiWaveView";
-    private static final boolean DEBUG = false;
-
-    // Wave state machine
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_START = 1;
-    private static final int STATE_FIRST_TOUCH = 2;
-    private static final int STATE_TRACKING = 3;
-    private static final int STATE_SNAP = 4;
-    private static final int STATE_FINISH = 5;
-
-    // Animation properties.
-    private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
-
-    public interface OnTriggerListener {
-        int NO_HANDLE = 0;
-        int CENTER_HANDLE = 1;
-        public void onGrabbed(View v, int handle);
-        public void onReleased(View v, int handle);
-        public void onTrigger(View v, int target);
-        public void onGrabbedStateChange(View v, int handle);
-        public void onFinishFinalAnimation();
-    }
-
-    // Tuneable parameters for animation
-    private static final int CHEVRON_INCREMENTAL_DELAY = 160;
-    private static final int CHEVRON_ANIMATION_DURATION = 850;
-    private static final int RETURN_TO_HOME_DELAY = 1200;
-    private static final int RETURN_TO_HOME_DURATION = 200;
-    private static final int HIDE_ANIMATION_DELAY = 200;
-    private static final int HIDE_ANIMATION_DURATION = 200;
-    private static final int SHOW_ANIMATION_DURATION = 200;
-    private static final int SHOW_ANIMATION_DELAY = 50;
-    private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
-
-    private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
-    private static final float TARGET_SCALE_EXPANDED = 1.0f;
-    private static final float TARGET_SCALE_COLLAPSED = 0.8f;
-    private static final float RING_SCALE_EXPANDED = 1.0f;
-    private static final float RING_SCALE_COLLAPSED = 0.5f;
-
-    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
-
-    private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
-    private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
-    private AnimationBundle mChevronAnimations = new AnimationBundle();
-    private AnimationBundle mTargetAnimations = new AnimationBundle();
-    private AnimationBundle mHandleAnimations = new AnimationBundle();
-    private ArrayList<String> mTargetDescriptions;
-    private ArrayList<String> mDirectionDescriptions;
-    private OnTriggerListener mOnTriggerListener;
-    private TargetDrawable mHandleDrawable;
-    private TargetDrawable mOuterRing;
-    private Vibrator mVibrator;
-
-    private int mFeedbackCount = 3;
-    private int mVibrationDuration = 0;
-    private int mGrabbedState;
-    private int mActiveTarget = -1;
-    private float mTapRadius;
-    private float mWaveCenterX;
-    private float mWaveCenterY;
-    private int mMaxTargetHeight;
-    private int mMaxTargetWidth;
-
-    private float mOuterRadius = 0.0f;
-    private float mSnapMargin = 0.0f;
-    private boolean mDragging;
-    private int mNewTargetResources;
-
-    private class AnimationBundle extends ArrayList<Tweener> {
-        private static final long serialVersionUID = 0xA84D78726F127468L;
-        private boolean mSuspended;
-
-        public void start() {
-            if (mSuspended) return; // ignore attempts to start animations
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.start();
-            }
-        }
-
-        public void cancel() {
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.cancel();
-            }
-            clear();
-        }
-
-        public void stop() {
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.end();
-            }
-            clear();
-        }
-
-        public void setSuspended(boolean suspend) {
-            mSuspended = suspend;
-        }
-    };
-
-    private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
-            dispatchOnFinishFinalAnimation();
-        }
-    };
-
-    private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            ping();
-            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
-            dispatchOnFinishFinalAnimation();
-        }
-    };
-
-    private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
-        public void onAnimationUpdate(ValueAnimator animation) {
-            invalidateGlobalRegion(mHandleDrawable);
-            invalidate();
-        }
-    };
-
-    private boolean mAnimatingTargets;
-    private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            if (mNewTargetResources != 0) {
-                internalSetTargetResources(mNewTargetResources);
-                mNewTargetResources = 0;
-                hideTargets(false, false);
-            }
-            mAnimatingTargets = false;
-        }
-    };
-    private int mTargetResourceId;
-    private int mTargetDescriptionsResourceId;
-    private int mDirectionDescriptionsResourceId;
-    private boolean mAlwaysTrackFinger;
-    private int mHorizontalInset;
-    private int mVerticalInset;
-    private int mGravity = Gravity.TOP;
-    private boolean mInitialLayout = true;
-    private Tweener mBackgroundAnimator;
-
-    public MultiWaveView(Context context) {
-        this(context, null);
-    }
-
-    public MultiWaveView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        Resources res = context.getResources();
-
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveView);
-        mOuterRadius = a.getDimension(R.styleable.MultiWaveView_outerRadius, mOuterRadius);
-        mSnapMargin = a.getDimension(R.styleable.MultiWaveView_snapMargin, mSnapMargin);
-        mVibrationDuration = a.getInt(R.styleable.MultiWaveView_vibrationDuration,
-                mVibrationDuration);
-        mFeedbackCount = a.getInt(R.styleable.MultiWaveView_feedbackCount,
-                mFeedbackCount);
-        mHandleDrawable = new TargetDrawable(res,
-                a.peekValue(R.styleable.MultiWaveView_handleDrawable).resourceId);
-        mTapRadius = mHandleDrawable.getWidth()/2;
-        mOuterRing = new TargetDrawable(res,
-                a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
-        mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
-
-        // Read array of chevron drawables
-        TypedValue outValue = new TypedValue();
-        if (a.getValue(R.styleable.MultiWaveView_chevronDrawables, outValue)) {
-            ArrayList<TargetDrawable> chevrons = loadDrawableArray(outValue.resourceId);
-            for (int i = 0; i < chevrons.size(); i++) {
-                final TargetDrawable chevron = chevrons.get(i);
-                for (int k = 0; k < mFeedbackCount; k++) {
-                    mChevronDrawables.add(chevron == null ? null : new TargetDrawable(chevron));
-                }
-            }
-        }
-
-        // Read array of target drawables
-        if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
-            internalSetTargetResources(outValue.resourceId);
-        }
-        if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
-            throw new IllegalStateException("Must specify at least one target drawable");
-        }
-
-        // Read array of target descriptions
-        if (a.getValue(R.styleable.MultiWaveView_targetDescriptions, outValue)) {
-            final int resourceId = outValue.resourceId;
-            if (resourceId == 0) {
-                throw new IllegalStateException("Must specify target descriptions");
-            }
-            setTargetDescriptionsResourceId(resourceId);
-        }
-
-        // Read array of direction descriptions
-        if (a.getValue(R.styleable.MultiWaveView_directionDescriptions, outValue)) {
-            final int resourceId = outValue.resourceId;
-            if (resourceId == 0) {
-                throw new IllegalStateException("Must specify direction descriptions");
-            }
-            setDirectionDescriptionsResourceId(resourceId);
-        }
-
-        a.recycle();
-
-        // Use gravity attribute from LinearLayout
-        a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
-        mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
-        a.recycle();
-
-        setVibrateEnabled(mVibrationDuration > 0);
-        assignDefaultsIfNeeded();
-    }
-
-    private void dump() {
-        Log.v(TAG, "Outer Radius = " + mOuterRadius);
-        Log.v(TAG, "SnapMargin = " + mSnapMargin);
-        Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
-        Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
-        Log.v(TAG, "TapRadius = " + mTapRadius);
-        Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
-        Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
-    }
-
-    public void suspendAnimations() {
-        mChevronAnimations.setSuspended(true);
-        mTargetAnimations.setSuspended(true);
-        mHandleAnimations.setSuspended(true);
-    }
-
-    public void resumeAnimations() {
-        mChevronAnimations.setSuspended(false);
-        mTargetAnimations.setSuspended(false);
-        mHandleAnimations.setSuspended(false);
-        mChevronAnimations.start();
-        mTargetAnimations.start();
-        mHandleAnimations.start();
-    }
-
-    @Override
-    protected int getSuggestedMinimumWidth() {
-        // View should be large enough to contain the background + handle and
-        // target drawable on either edge.
-        return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
-    }
-
-    @Override
-    protected int getSuggestedMinimumHeight() {
-        // View should be large enough to contain the unlock ring + target and
-        // target drawable on either edge
-        return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
-    }
-
-    private int resolveMeasured(int measureSpec, int desired)
-    {
-        int result = 0;
-        int specSize = MeasureSpec.getSize(measureSpec);
-        switch (MeasureSpec.getMode(measureSpec)) {
-            case MeasureSpec.UNSPECIFIED:
-                result = desired;
-                break;
-            case MeasureSpec.AT_MOST:
-                result = Math.min(specSize, desired);
-                break;
-            case MeasureSpec.EXACTLY:
-            default:
-                result = specSize;
-        }
-        return result;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int minimumWidth = getSuggestedMinimumWidth();
-        final int minimumHeight = getSuggestedMinimumHeight();
-        int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
-        int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-        computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
-        setMeasuredDimension(computedWidth, computedHeight);
-    }
-
-    private void switchToState(int state, float x, float y) {
-        switch (state) {
-            case STATE_IDLE:
-                deactivateTargets();
-                hideTargets(true, false);
-                startBackgroundAnimation(0, 0.0f);
-                mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
-                break;
-
-            case STATE_START:
-                deactivateHandle(0, 0, 1.0f, null);
-                startBackgroundAnimation(0, 0.0f);
-                break;
-
-            case STATE_FIRST_TOUCH:
-                deactivateTargets();
-                showTargets(true);
-                mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
-                startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
-                setGrabbedState(OnTriggerListener.CENTER_HANDLE);
-                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                    announceTargets();
-                }
-                break;
-
-            case STATE_TRACKING:
-                break;
-
-            case STATE_SNAP:
-                break;
-
-            case STATE_FINISH:
-                doFinish();
-                break;
-        }
-    }
-
-    private void activateHandle(int duration, int delay, float finalAlpha,
-            AnimatorListener finishListener) {
-        mHandleAnimations.cancel();
-        mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
-                "ease", Ease.Cubic.easeIn,
-                "delay", delay,
-                "alpha", finalAlpha,
-                "onUpdate", mUpdateListener,
-                "onComplete", finishListener));
-        mHandleAnimations.start();
-    }
-
-    private void deactivateHandle(int duration, int delay, float finalAlpha,
-            AnimatorListener finishListener) {
-        mHandleAnimations.cancel();
-        mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
-            "ease", Ease.Quart.easeOut,
-            "delay", delay,
-            "alpha", finalAlpha,
-            "x", 0,
-            "y", 0,
-            "onUpdate", mUpdateListener,
-            "onComplete", finishListener));
-        mHandleAnimations.start();
-    }
-
-    /**
-     * Animation used to attract user's attention to the target button.
-     * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
-     * mFeedbackCount items in the order: left, right, top, bottom.
-     */
-    private void startChevronAnimation() {
-        final float chevronStartDistance = mHandleDrawable.getWidth() * 0.8f;
-        final float chevronStopDistance = mOuterRadius * 0.9f / 2.0f;
-        final float startScale = 0.5f;
-        final float endScale = 2.0f;
-        final int directionCount = mFeedbackCount > 0 ? mChevronDrawables.size()/mFeedbackCount : 0;
-
-        mChevronAnimations.stop();
-
-        // Add an animation for all chevron drawables.  There are mFeedbackCount drawables
-        // in each direction and directionCount directions.
-        for (int direction = 0; direction < directionCount; direction++) {
-            double angle = 2.0 * Math.PI * direction / directionCount;
-            final float sx = (float) Math.cos(angle);
-            final float sy = 0.0f - (float) Math.sin(angle);
-            final float[] xrange = new float[]
-                 {sx * chevronStartDistance, sx * chevronStopDistance};
-            final float[] yrange = new float[]
-                 {sy * chevronStartDistance, sy * chevronStopDistance};
-            for (int count = 0; count < mFeedbackCount; count++) {
-                int delay = count * CHEVRON_INCREMENTAL_DELAY;
-                final TargetDrawable icon = mChevronDrawables.get(direction*mFeedbackCount + count);
-                if (icon == null) {
-                    continue;
-                }
-                mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
-                        "ease", mChevronAnimationInterpolator,
-                        "delay", delay,
-                        "x", xrange,
-                        "y", yrange,
-                        "alpha", new float[] {1.0f, 0.0f},
-                        "scaleX", new float[] {startScale, endScale},
-                        "scaleY", new float[] {startScale, endScale},
-                        "onUpdate", mUpdateListener));
-            }
-        }
-        mChevronAnimations.start();
-    }
-
-    private void deactivateTargets() {
-        final int count = mTargetDrawables.size();
-        for (int i = 0; i < count; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-        }
-        mActiveTarget = -1;
-    }
-
-    void invalidateGlobalRegion(TargetDrawable drawable) {
-        int width = drawable.getWidth();
-        int height = drawable.getHeight();
-        RectF childBounds = new RectF(0, 0, width, height);
-        childBounds.offset(drawable.getX() - width/2, drawable.getY() - height/2);
-        View view = this;
-        while (view.getParent() != null && view.getParent() instanceof View) {
-            view = (View) view.getParent();
-            view.getMatrix().mapRect(childBounds);
-            view.invalidate((int) Math.floor(childBounds.left),
-                    (int) Math.floor(childBounds.top),
-                    (int) Math.ceil(childBounds.right),
-                    (int) Math.ceil(childBounds.bottom));
-        }
-    }
-
-    /**
-     * Dispatches a trigger event to listener. Ignored if a listener is not set.
-     * @param whichTarget the target that was triggered.
-     */
-    private void dispatchTriggerEvent(int whichTarget) {
-        vibrate();
-        if (mOnTriggerListener != null) {
-            mOnTriggerListener.onTrigger(this, whichTarget);
-        }
-    }
-
-    private void dispatchOnFinishFinalAnimation() {
-        if (mOnTriggerListener != null) {
-            mOnTriggerListener.onFinishFinalAnimation();
-        }
-    }
-
-    private void doFinish() {
-        final int activeTarget = mActiveTarget;
-        final boolean targetHit =  activeTarget != -1;
-
-        if (targetHit) {
-            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
-
-            highlightSelected(activeTarget);
-
-            // Inform listener of any active targets.  Typically only one will be active.
-            deactivateHandle(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
-            dispatchTriggerEvent(activeTarget);
-            if (!mAlwaysTrackFinger) {
-                // Force ring and targets to finish animation to final expanded state
-                mTargetAnimations.stop();
-            }
-        } else {
-            // Animate handle back to the center based on current state.
-            deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
-                    mResetListenerWithPing);
-            hideTargets(true, false);
-        }
-
-        setGrabbedState(OnTriggerListener.NO_HANDLE);
-    }
-
-    private void highlightSelected(int activeTarget) {
-        // Highlight the given target and fade others
-        mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
-        hideUnselected(activeTarget);
-    }
-
-    private void hideUnselected(int active) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            if (i != active) {
-                mTargetDrawables.get(i).setAlpha(0.0f);
-            }
-        }
-    }
-
-    private void hideTargets(boolean animate, boolean expanded) {
-        mTargetAnimations.cancel();
-        // Note: these animations should complete at the same time so that we can swap out
-        // the target assets asynchronously from the setTargetResources() call.
-        mAnimatingTargets = animate;
-        final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
-        final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
-
-        final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
-        final int length = mTargetDrawables.size();
-        for (int i = 0; i < length; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, duration,
-                    "ease", Ease.Cubic.easeOut,
-                    "alpha", 0.0f,
-                    "scaleX", targetScale,
-                    "scaleY", targetScale,
-                    "delay", delay,
-                    "onUpdate", mUpdateListener));
-        }
-
-        final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
-        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
-                "ease", Ease.Cubic.easeOut,
-                "alpha", 0.0f,
-                "scaleX", ringScaleTarget,
-                "scaleY", ringScaleTarget,
-                "delay", delay,
-                "onUpdate", mUpdateListener,
-                "onComplete", mTargetUpdateListener));
-
-        mTargetAnimations.start();
-    }
-
-    private void showTargets(boolean animate) {
-        mTargetAnimations.stop();
-        mAnimatingTargets = animate;
-        final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
-        final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
-        final int length = mTargetDrawables.size();
-        for (int i = 0; i < length; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, duration,
-                    "ease", Ease.Cubic.easeOut,
-                    "alpha", 1.0f,
-                    "scaleX", 1.0f,
-                    "scaleY", 1.0f,
-                    "delay", delay,
-                    "onUpdate", mUpdateListener));
-        }
-        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
-                "ease", Ease.Cubic.easeOut,
-                "alpha", 1.0f,
-                "scaleX", 1.0f,
-                "scaleY", 1.0f,
-                "delay", delay,
-                "onUpdate", mUpdateListener,
-                "onComplete", mTargetUpdateListener));
-
-        mTargetAnimations.start();
-    }
-
-    private void vibrate() {
-        final boolean hapticEnabled = Settings.System.getIntForUser(
-                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
-                UserHandle.USER_CURRENT) != 0;
-        if (mVibrator != null && hapticEnabled) {
-            mVibrator.vibrate(mVibrationDuration, AudioManager.STREAM_SYSTEM);
-        }
-    }
-
-    private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
-        Resources res = getContext().getResources();
-        TypedArray array = res.obtainTypedArray(resourceId);
-        final int count = array.length();
-        ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
-        for (int i = 0; i < count; i++) {
-            TypedValue value = array.peekValue(i);
-            TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
-            drawables.add(target);
-        }
-        array.recycle();
-        return drawables;
-    }
-
-    private void internalSetTargetResources(int resourceId) {
-        mTargetDrawables = loadDrawableArray(resourceId);
-        mTargetResourceId = resourceId;
-        final int count = mTargetDrawables.size();
-        int maxWidth = mHandleDrawable.getWidth();
-        int maxHeight = mHandleDrawable.getHeight();
-        for (int i = 0; i < count; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            maxWidth = Math.max(maxWidth, target.getWidth());
-            maxHeight = Math.max(maxHeight, target.getHeight());
-        }
-        if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
-            mMaxTargetWidth = maxWidth;
-            mMaxTargetHeight = maxHeight;
-            requestLayout(); // required to resize layout and call updateTargetPositions()
-        } else {
-            updateTargetPositions(mWaveCenterX, mWaveCenterY);
-            updateChevronPositions(mWaveCenterX, mWaveCenterY);
-        }
-    }
-
-    /**
-     * Loads an array of drawables from the given resourceId.
-     *
-     * @param resourceId
-     */
-    public void setTargetResources(int resourceId) {
-        if (mAnimatingTargets) {
-            // postpone this change until we return to the initial state
-            mNewTargetResources = resourceId;
-        } else {
-            internalSetTargetResources(resourceId);
-        }
-    }
-
-    public int getTargetResourceId() {
-        return mTargetResourceId;
-    }
-
-    /**
-     * Sets the resource id specifying the target descriptions for accessibility.
-     *
-     * @param resourceId The resource id.
-     */
-    public void setTargetDescriptionsResourceId(int resourceId) {
-        mTargetDescriptionsResourceId = resourceId;
-        if (mTargetDescriptions != null) {
-            mTargetDescriptions.clear();
-        }
-    }
-
-    /**
-     * Gets the resource id specifying the target descriptions for accessibility.
-     *
-     * @return The resource id.
-     */
-    public int getTargetDescriptionsResourceId() {
-        return mTargetDescriptionsResourceId;
-    }
-
-    /**
-     * Sets the resource id specifying the target direction descriptions for accessibility.
-     *
-     * @param resourceId The resource id.
-     */
-    public void setDirectionDescriptionsResourceId(int resourceId) {
-        mDirectionDescriptionsResourceId = resourceId;
-        if (mDirectionDescriptions != null) {
-            mDirectionDescriptions.clear();
-        }
-    }
-
-    /**
-     * Gets the resource id specifying the target direction descriptions.
-     *
-     * @return The resource id.
-     */
-    public int getDirectionDescriptionsResourceId() {
-        return mDirectionDescriptionsResourceId;
-    }
-
-    /**
-     * Enable or disable vibrate on touch.
-     *
-     * @param enabled
-     */
-    public void setVibrateEnabled(boolean enabled) {
-        if (enabled && mVibrator == null) {
-            mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
-        } else {
-            mVibrator = null;
-        }
-    }
-
-    /**
-     * Starts chevron animation. Example use case: show chevron animation whenever the phone rings
-     * or the user touches the screen.
-     *
-     */
-    public void ping() {
-        startChevronAnimation();
-    }
-
-    /**
-     * Resets the widget to default state and cancels all animation. If animate is 'true', will
-     * animate objects into place. Otherwise, objects will snap back to place.
-     *
-     * @param animate
-     */
-    public void reset(boolean animate) {
-        mChevronAnimations.stop();
-        mHandleAnimations.stop();
-        mTargetAnimations.stop();
-        startBackgroundAnimation(0, 0.0f);
-        hideChevrons();
-        hideTargets(animate, false);
-        deactivateHandle(0, 0, 1.0f, null);
-        Tweener.reset();
-    }
-
-    private void startBackgroundAnimation(int duration, float alpha) {
-        Drawable background = getBackground();
-        if (mAlwaysTrackFinger && background != null) {
-            if (mBackgroundAnimator != null) {
-                mBackgroundAnimator.animator.end();
-            }
-            mBackgroundAnimator = Tweener.to(background, duration,
-                    "ease", Ease.Cubic.easeIn,
-                    "alpha", new int[] {0, (int)(255.0f * alpha)},
-                    "delay", SHOW_ANIMATION_DELAY);
-            mBackgroundAnimator.animator.start();
-        }
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        final int action = event.getAction();
-        boolean handled = false;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                if (DEBUG) Log.v(TAG, "*** DOWN ***");
-                handleDown(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (DEBUG) Log.v(TAG, "*** MOVE ***");
-                handleMove(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_UP:
-                if (DEBUG) Log.v(TAG, "*** UP ***");
-                handleMove(event);
-                handleUp(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_CANCEL:
-                if (DEBUG) Log.v(TAG, "*** CANCEL ***");
-                handleMove(event);
-                handleCancel(event);
-                handled = true;
-                break;
-        }
-        invalidate();
-        return handled ? true : super.onTouchEvent(event);
-    }
-
-    private void moveHandleTo(float x, float y, boolean animate) {
-        mHandleDrawable.setX(x);
-        mHandleDrawable.setY(y);
-    }
-
-    private void handleDown(MotionEvent event) {
-        float eventX = event.getX();
-        float eventY = event.getY();
-        switchToState(STATE_START, eventX, eventY);
-        if (!trySwitchToFirstTouchState(eventX, eventY)) {
-            mDragging = false;
-            ping();
-        }
-    }
-
-    private void handleUp(MotionEvent event) {
-        if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
-        switchToState(STATE_FINISH, event.getX(), event.getY());
-    }
-
-    private void handleCancel(MotionEvent event) {
-        if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
-
-        // We should drop the active target here but it interferes with
-        // moving off the screen in the direction of the navigation bar. At some point we may
-        // want to revisit how we handle this. For now we'll allow a canceled event to
-        // activate the current target.
-
-        // mActiveTarget = -1; // Drop the active target if canceled.
-
-        switchToState(STATE_FINISH, event.getX(), event.getY());
-    }
-
-    private void handleMove(MotionEvent event) {
-        int activeTarget = -1;
-        final int historySize = event.getHistorySize();
-        ArrayList<TargetDrawable> targets = mTargetDrawables;
-        int ntargets = targets.size();
-        float x = 0.0f;
-        float y = 0.0f;
-        for (int k = 0; k < historySize + 1; k++) {
-            float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
-            float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
-            // tx and ty are relative to wave center
-            float tx = eventX - mWaveCenterX;
-            float ty = eventY - mWaveCenterY;
-            float touchRadius = (float) Math.sqrt(dist2(tx, ty));
-            final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
-            float limitX = tx * scale;
-            float limitY = ty * scale;
-            double angleRad = Math.atan2(-ty, tx);
-
-            if (!mDragging) {
-                trySwitchToFirstTouchState(eventX, eventY);
-            }
-
-            if (mDragging) {
-                // For multiple targets, snap to the one that matches
-                final float snapRadius = mOuterRadius - mSnapMargin;
-                final float snapDistance2 = snapRadius * snapRadius;
-                // Find first target in range
-                for (int i = 0; i < ntargets; i++) {
-                    TargetDrawable target = targets.get(i);
-
-                    double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
-                    double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
-                    if (target.isEnabled()) {
-                        boolean angleMatches =
-                            (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
-                            (angleRad + 2 * Math.PI > targetMinRad &&
-                             angleRad + 2 * Math.PI <= targetMaxRad);
-                        if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
-                            activeTarget = i;
-                        }
-                    }
-                }
-            }
-            x = limitX;
-            y = limitY;
-        }
-
-        if (!mDragging) {
-            return;
-        }
-
-        if (activeTarget != -1) {
-            switchToState(STATE_SNAP, x,y);
-            moveHandleTo(x, y, false);
-        } else {
-            switchToState(STATE_TRACKING, x, y);
-            moveHandleTo(x, y, false);
-        }
-
-        // Draw handle outside parent's bounds
-        invalidateGlobalRegion(mHandleDrawable);
-
-        if (mActiveTarget != activeTarget) {
-            // Defocus the old target
-            if (mActiveTarget != -1) {
-                TargetDrawable target = targets.get(mActiveTarget);
-                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
-                    target.setState(TargetDrawable.STATE_INACTIVE);
-                }
-            }
-            // Focus the new target
-            if (activeTarget != -1) {
-                TargetDrawable target = targets.get(activeTarget);
-                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
-                    target.setState(TargetDrawable.STATE_FOCUSED);
-                }
-                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                    String targetContentDescription = getTargetDescription(activeTarget);
-                    announceText(targetContentDescription);
-                }
-                activateHandle(0, 0, 0.0f, null);
-            } else {
-                activateHandle(0, 0, 1.0f, null);
-            }
-        }
-        mActiveTarget = activeTarget;
-    }
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
-            final int action = event.getAction();
-            switch (action) {
-                case MotionEvent.ACTION_HOVER_ENTER:
-                    event.setAction(MotionEvent.ACTION_DOWN);
-                    break;
-                case MotionEvent.ACTION_HOVER_MOVE:
-                    event.setAction(MotionEvent.ACTION_MOVE);
-                    break;
-                case MotionEvent.ACTION_HOVER_EXIT:
-                    event.setAction(MotionEvent.ACTION_UP);
-                    break;
-            }
-            onTouchEvent(event);
-            event.setAction(action);
-        }
-        return super.onHoverEvent(event);
-    }
-
-    /**
-     * Sets the current grabbed state, and dispatches a grabbed state change
-     * event to our listener.
-     */
-    private void setGrabbedState(int newState) {
-        if (newState != mGrabbedState) {
-            if (newState != OnTriggerListener.NO_HANDLE) {
-                vibrate();
-            }
-            mGrabbedState = newState;
-            if (mOnTriggerListener != null) {
-                if (newState == OnTriggerListener.NO_HANDLE) {
-                    mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
-                } else {
-                    mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
-                }
-                mOnTriggerListener.onGrabbedStateChange(this, newState);
-            }
-        }
-    }
-
-    private boolean trySwitchToFirstTouchState(float x, float y) {
-        final float tx = x - mWaveCenterX;
-        final float ty = y - mWaveCenterY;
-        if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledTapRadiusSquared()) {
-            if (DEBUG) Log.v(TAG, "** Handle HIT");
-            switchToState(STATE_FIRST_TOUCH, x, y);
-            moveHandleTo(tx, ty, false);
-            mDragging = true;
-            return true;
-        }
-        return false;
-    }
-
-    private void assignDefaultsIfNeeded() {
-        if (mOuterRadius == 0.0f) {
-            mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
-        }
-        if (mSnapMargin == 0.0f) {
-            mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
-        }
-    }
-
-    private void computeInsets(int dx, int dy) {
-        final int layoutDirection = getLayoutDirection();
-        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
-        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-            case Gravity.LEFT:
-                mHorizontalInset = 0;
-                break;
-            case Gravity.RIGHT:
-                mHorizontalInset = dx;
-                break;
-            case Gravity.CENTER_HORIZONTAL:
-            default:
-                mHorizontalInset = dx / 2;
-                break;
-        }
-        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
-            case Gravity.TOP:
-                mVerticalInset = 0;
-                break;
-            case Gravity.BOTTOM:
-                mVerticalInset = dy;
-                break;
-            case Gravity.CENTER_VERTICAL:
-            default:
-                mVerticalInset = dy / 2;
-                break;
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        final int width = right - left;
-        final int height = bottom - top;
-
-        // Target placement width/height. This puts the targets on the greater of the ring
-        // width or the specified outer radius.
-        final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
-        final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
-        float newWaveCenterX = mHorizontalInset
-                + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
-        float newWaveCenterY = mVerticalInset
-                + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
-
-        if (mInitialLayout) {
-            hideChevrons();
-            hideTargets(false, false);
-            moveHandleTo(0, 0, false);
-            mInitialLayout = false;
-        }
-
-        mOuterRing.setPositionX(newWaveCenterX);
-        mOuterRing.setPositionY(newWaveCenterY);
-
-        mHandleDrawable.setPositionX(newWaveCenterX);
-        mHandleDrawable.setPositionY(newWaveCenterY);
-
-        updateTargetPositions(newWaveCenterX, newWaveCenterY);
-        updateChevronPositions(newWaveCenterX, newWaveCenterY);
-
-        mWaveCenterX = newWaveCenterX;
-        mWaveCenterY = newWaveCenterY;
-
-        if (DEBUG) dump();
-    }
-
-    private void updateTargetPositions(float centerX, float centerY) {
-        // Reposition the target drawables if the view changed.
-        ArrayList<TargetDrawable> targets = mTargetDrawables;
-        final int size = targets.size();
-        final float alpha = (float) (-2.0f * Math.PI / size);
-        for (int i = 0; i < size; i++) {
-            final TargetDrawable targetIcon = targets.get(i);
-            final float angle = alpha * i;
-            targetIcon.setPositionX(centerX);
-            targetIcon.setPositionY(centerY);
-            targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
-            targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
-        }
-    }
-
-    private void updateChevronPositions(float centerX, float centerY) {
-        ArrayList<TargetDrawable> chevrons = mChevronDrawables;
-        final int size = chevrons.size();
-        for (int i = 0; i < size; i++) {
-            TargetDrawable target = chevrons.get(i);
-            if (target != null) {
-                target.setPositionX(centerX);
-                target.setPositionY(centerY);
-            }
-        }
-    }
-
-    private void hideChevrons() {
-        ArrayList<TargetDrawable> chevrons = mChevronDrawables;
-        final int size = chevrons.size();
-        for (int i = 0; i < size; i++) {
-            TargetDrawable chevron = chevrons.get(i);
-            if (chevron != null) {
-                chevron.setAlpha(0.0f);
-            }
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        mOuterRing.draw(canvas);
-        final int ntargets = mTargetDrawables.size();
-        for (int i = 0; i < ntargets; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            if (target != null) {
-                target.draw(canvas);
-            }
-        }
-        final int nchevrons = mChevronDrawables.size();
-        for (int i = 0; i < nchevrons; i++) {
-            TargetDrawable chevron = mChevronDrawables.get(i);
-            if (chevron != null) {
-                chevron.draw(canvas);
-            }
-        }
-        mHandleDrawable.draw(canvas);
-    }
-
-    public void setOnTriggerListener(OnTriggerListener listener) {
-        mOnTriggerListener = listener;
-    }
-
-    private float square(float d) {
-        return d * d;
-    }
-
-    private float dist2(float dx, float dy) {
-        return dx*dx + dy*dy;
-    }
-
-    private float getScaledTapRadiusSquared() {
-        final float scaledTapRadius;
-        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-            scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mTapRadius;
-        } else {
-            scaledTapRadius = mTapRadius;
-        }
-        return square(scaledTapRadius);
-    }
-
-    private void announceTargets() {
-        StringBuilder utterance = new StringBuilder();
-        final int targetCount = mTargetDrawables.size();
-        for (int i = 0; i < targetCount; i++) {
-            String targetDescription = getTargetDescription(i);
-            String directionDescription = getDirectionDescription(i);
-            if (!TextUtils.isEmpty(targetDescription)
-                    && !TextUtils.isEmpty(directionDescription)) {
-                String text = String.format(directionDescription, targetDescription);
-                utterance.append(text);
-            }
-            if (utterance.length() > 0) {
-                announceText(utterance.toString());
-            }
-        }
-    }
-
-    private void announceText(String text) {
-        setContentDescription(text);
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
-        setContentDescription(null);
-    }
-
-    private String getTargetDescription(int index) {
-        if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
-            mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
-            if (mTargetDrawables.size() != mTargetDescriptions.size()) {
-                Log.w(TAG, "The number of target drawables must be"
-                        + " euqal to the number of target descriptions.");
-                return null;
-            }
-        }
-        return mTargetDescriptions.get(index);
-    }
-
-    private String getDirectionDescription(int index) {
-        if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
-            mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
-            if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
-                Log.w(TAG, "The number of target drawables must be"
-                        + " euqal to the number of direction descriptions.");
-                return null;
-            }
-        }
-        return mDirectionDescriptions.get(index);
-    }
-
-    private ArrayList<String> loadDescriptions(int resourceId) {
-        TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
-        final int count = array.length();
-        ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
-        for (int i = 0; i < count; i++) {
-            String contentDescription = array.getString(i);
-            targetContentDescriptions.add(contentDescription);
-        }
-        array.recycle();
-        return targetContentDescriptions;
-    }
-
-    public int getResourceIdForTarget(int index) {
-        final TargetDrawable drawable = mTargetDrawables.get(index);
-        return drawable == null ? 0 : drawable.getResourceId();
-    }
-
-    public void setEnableTarget(int resourceId, boolean enabled) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            final TargetDrawable target = mTargetDrawables.get(i);
-            if (target.getResourceId() == resourceId) {
-                target.setEnabled(enabled);
-                break; // should never be more than one match
-            }
-        }
-    }
-
-    /**
-     * Gets the position of a target in the array that matches the given resource.
-     * @param resourceId
-     * @return the index or -1 if not found
-     */
-    public int getTargetPosition(int resourceId) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            final TargetDrawable target = mTargetDrawables.get(i);
-            if (target.getResourceId() == resourceId) {
-                return i; // should never be more than one match
-            }
-        }
-        return -1;
-    }
-
-    private boolean replaceTargetDrawables(Resources res, int existingResourceId,
-            int newResourceId) {
-        if (existingResourceId == 0 || newResourceId == 0) {
-            return false;
-        }
-
-        boolean result = false;
-        final ArrayList<TargetDrawable> drawables = mTargetDrawables;
-        final int size = drawables.size();
-        for (int i = 0; i < size; i++) {
-            final TargetDrawable target = drawables.get(i);
-            if (target != null && target.getResourceId() == existingResourceId) {
-                target.setDrawable(res, newResourceId);
-                result = true;
-            }
-        }
-
-        if (result) {
-            requestLayout(); // in case any given drawable's size changes
-        }
-
-        return result;
-    }
-
-    /**
-     * Searches the given package for a resource to use to replace the Drawable on the
-     * target with the given resource id
-     * @param component of the .apk that contains the resource
-     * @param name of the metadata in the .apk
-     * @param existingResId the resource id of the target to search for
-     * @return true if found in the given package and replaced at least one target Drawables
-     */
-    public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
-                int existingResId) {
-        if (existingResId == 0) return false;
-
-        try {
-            PackageManager packageManager = mContext.getPackageManager();
-            // Look for the search icon specified in the activity meta-data
-            Bundle metaData = packageManager.getActivityInfo(
-                    component, PackageManager.GET_META_DATA).metaData;
-            if (metaData != null) {
-                int iconResId = metaData.getInt(name);
-                if (iconResId != 0) {
-                    Resources res = packageManager.getResourcesForActivity(component);
-                    return replaceTargetDrawables(res, existingResId, iconResId);
-                }
-            }
-        } catch (NameNotFoundException e) {
-            Log.w(TAG, "Failed to swap drawable; "
-                    + component.flattenToShortString() + " not found", e);
-        } catch (Resources.NotFoundException nfe) {
-            Log.w(TAG, "Failed to swap drawable from "
-                    + component.flattenToShortString(), nfe);
-        }
-        return false;
-    }
-}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 51c5a86..711f28a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -151,7 +151,8 @@
 	android_content_res_ObbScanner.cpp \
 	android_content_res_Configuration.cpp \
 	android_animation_PropertyValuesHolder.cpp \
-	com_android_internal_net_NetworkStatsFactory.cpp
+	com_android_internal_net_NetworkStatsFactory.cpp \
+	com_android_internal_os_Zygote.cpp
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
@@ -177,7 +178,8 @@
 	external/harfbuzz_ng/src \
 	external/zlib \
 	frameworks/opt/emoji \
-	libcore/include
+	libcore/include \
+	$(call include-path-for, audio-utils) \
 
 LOCAL_SHARED_LIBRARIES := \
 	libmemtrack \
@@ -213,7 +215,8 @@
 	libjpeg \
 	libusbhost \
 	libharfbuzz_ng \
-	libz
+	libz \
+	libaudioutils \
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9a7a5f9..4759451 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -178,6 +178,7 @@
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
 extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_Zygote(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -228,9 +229,10 @@
 
 /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
 
-
-AndroidRuntime::AndroidRuntime() :
-        mExitWithoutCleanup(false)
+AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
+        mExitWithoutCleanup(false),
+        mArgBlockStart(argBlockStart),
+        mArgBlockLength(argBlockLength)
 {
     SkGraphics::Init();
     // this sets our preference for 16bit images during decode
@@ -265,6 +267,10 @@
     return jniRegisterNativeMethods(env, className, gMethods, numMethods);
 }
 
+void AndroidRuntime::setArgv0(const char* argv0) {
+    strlcpy(mArgBlockStart, argv0, mArgBlockLength);
+}
+
 status_t AndroidRuntime::callMain(const char* className,
     jclass clazz, int argc, const char* const argv[])
 {
@@ -1244,6 +1250,7 @@
     REG_JNI(register_android_net_TrafficStats),
     REG_JNI(register_android_os_MemoryFile),
     REG_JNI(register_com_android_internal_os_ZygoteInit),
+    REG_JNI(register_com_android_internal_os_Zygote),
     REG_JNI(register_android_hardware_Camera),
     REG_JNI(register_android_hardware_camera2_CameraMetadata),
     REG_JNI(register_android_hardware_SensorManager),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 310966c..e0fa9ba4 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -329,7 +329,7 @@
     SkBitmap            result;

     JavaPixelAllocator  allocator(env);

 

-    if (!src->copyTo(&result, dstConfig, &allocator)) {

+    if (!src->copyTo(&result, SkBitmapConfigToColorType(dstConfig), &allocator)) {
         return NULL;

     }

     return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),

diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index b89dced..7aa241a 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -151,7 +151,7 @@
     switch (colorType) {
         case kUnknown_SkColorType:
         case kIndex_8_SkColorType:
-            return kPMColor_SkColorType;
+            return kNative_8888_SkColorType;
         default:
             break;
     }
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 098643b..ead2de3 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -62,7 +62,7 @@
     bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect,
                       SkBitmap::Config pref, int sampleSize) {
         fDecoder->setSampleSize(sampleSize);
-        return fDecoder->decodeRegion(bitmap, rect, pref);
+        return fDecoder->decodeSubset(bitmap, rect, pref);
     }
 
     SkImageDecoder* getDecoder() const { return fDecoder; }
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 54d448e..ef57e3d 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -32,39 +32,39 @@
                              jfloat dx, jfloat dy, jfloat dz) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->translate(SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(dz));
+    v->translate(dx, dy, dz);
 }
 
 static void Camera_rotateX(JNIEnv* env, jobject obj, jfloat degrees) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->rotateX(SkFloatToScalar(degrees));
+    v->rotateX(degrees);
 }
 
 static void Camera_rotateY(JNIEnv* env, jobject obj, jfloat degrees) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->rotateY(SkFloatToScalar(degrees));
+    v->rotateY(degrees);
 }
 
 static void Camera_rotateZ(JNIEnv* env, jobject obj, jfloat degrees) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->rotateZ(SkFloatToScalar(degrees));
+    v->rotateZ(degrees);
 }
 
 static void Camera_rotate(JNIEnv* env, jobject obj, jfloat x, jfloat y, jfloat z) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->rotateX(SkFloatToScalar(x));
-    v->rotateY(SkFloatToScalar(y));
-    v->rotateZ(SkFloatToScalar(z));
+    v->rotateX(x);
+    v->rotateY(y);
+    v->rotateZ(z);
 }
 
 static void Camera_setLocation(JNIEnv* env, jobject obj, jfloat x, jfloat y, jfloat z) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    v->setCameraLocation(SkFloatToScalar(x), SkFloatToScalar(y), SkFloatToScalar(z));
+    v->setCameraLocation(x, y, z);
 }
 
 static jfloat Camera_getLocationX(JNIEnv* env, jobject obj) {
@@ -103,8 +103,7 @@
                                   jfloat x, jfloat y, jfloat z) {
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
-    SkScalar dot = v->dotWithNormal(SkFloatToScalar(x), SkFloatToScalar(y),
-                                    SkFloatToScalar(z));
+    SkScalar dot = v->dotWithNormal(x, y, z);
     return SkScalarToFloat(dot);
 }
 
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 946b898..5148266 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -65,6 +65,9 @@
     virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
         m_dstCanvas->clipRect(rect, op, antialias);
     }
+    virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+        m_dstCanvas->clipRRect(rrect, op, antialias);
+    }
     virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
         m_dstCanvas->clipPath(path, op, antialias);
     }
@@ -73,6 +76,12 @@
     SkCanvas* m_dstCanvas;
 };
 
+// Returns true if the SkCanvas's clip is non-empty.
+static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
+    bool emptyClip = canvas.isClipEmpty();
+    return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
 class SkCanvasGlue {
 public:
 
@@ -170,8 +179,7 @@
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkPaint* paint  = reinterpret_cast<SkPaint*>(paintHandle);
         SkRect bounds;
-        bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
-                   SkFloatToScalar(b));
+        bounds.set(l, t, r, b);
         int result = canvas->saveLayer(&bounds, paint,
                                       static_cast<SkCanvas::SaveFlags>(flags));
         return static_cast<jint>(result);
@@ -196,8 +204,7 @@
                                 jint alpha, jint flags) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkRect  bounds;
-        bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
-                   SkFloatToScalar(b));
+        bounds.set(l, t, r, b);
         int result = canvas->saveLayerAlpha(&bounds, alpha,
                                       static_cast<SkCanvas::SaveFlags>(flags));
         return static_cast<jint>(result);
@@ -231,29 +238,22 @@
 
     static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
         NPE_CHECK_RETURN_VOID(env, jcanvas);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
+        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx, dy);
     }
 
     static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
         NPE_CHECK_RETURN_VOID(env, jcanvas);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
+        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx, sy);
     }
 
     static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
         NPE_CHECK_RETURN_VOID(env, jcanvas);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
+        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees);
     }
 
     static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
         NPE_CHECK_RETURN_VOID(env, jcanvas);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
+        (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx, sy);
     }
 
     static void concat(JNIEnv* env, jobject, jlong canvasHandle,
@@ -278,11 +278,10 @@
                                   jfloat top, jfloat right, jfloat bottom) {
         NPE_CHECK_RETURN_ZERO(env, jcanvas);
         SkRect  r;
-        r.set(SkFloatToScalar(left), SkFloatToScalar(top),
-              SkFloatToScalar(right), SkFloatToScalar(bottom));
+        r.set(left, top, right, bottom);
         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
-        bool result = c->clipRect(r);
-        return result ? JNI_TRUE : JNI_FALSE;
+        c->clipRect(r);
+        return hasNonEmptyClip(*c);
     }
 
     static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
@@ -291,8 +290,9 @@
         SkRect  r;
         r.set(SkIntToScalar(left), SkIntToScalar(top),
               SkIntToScalar(right), SkIntToScalar(bottom));
-        bool result = GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
-        return result ? JNI_TRUE : JNI_FALSE;
+        SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
+        c->clipRect(r);
+        return hasNonEmptyClip(*c);
     }
 
     static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
@@ -300,8 +300,8 @@
         NPE_CHECK_RETURN_ZERO(env, rectf);
         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
         SkRect tmp;
-        bool result = c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
-        return result ? JNI_TRUE : JNI_FALSE;
+        c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
+        return hasNonEmptyClip(*c);
     }
 
     static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
@@ -309,8 +309,8 @@
         NPE_CHECK_RETURN_ZERO(env, rect);
         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
         SkRect tmp;
-        bool result = c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
-        return result ? JNI_TRUE : JNI_FALSE;
+        c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
+        return hasNonEmptyClip(*c);
 
     }
 
@@ -319,27 +319,25 @@
                              jint op) {
         SkRect rect;
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
-                 SkFloatToScalar(right), SkFloatToScalar(bottom));
-        bool result = canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
-        return result ? JNI_TRUE : JNI_FALSE;
-
+        rect.set(left, top, right, bottom);
+        canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
+        return hasNonEmptyClip(*canvas);
     }
 
     static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
                              jlong pathHandle, jint op) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
-                                       static_cast<SkRegion::Op>(op));
-        return result ? JNI_TRUE : JNI_FALSE;
+        canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+                static_cast<SkRegion::Op>(op));
+        return hasNonEmptyClip(*canvas);
     }
 
     static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
                                jlong deviceRgnHandle, jint op) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
-        bool result = canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
-        return result ? JNI_TRUE : JNI_FALSE;
+        canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
+        return hasNonEmptyClip(*canvas);
     }
 
     static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
@@ -353,7 +351,8 @@
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkRect rect_;
         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
-        return canvas->quickReject(rect_);
+        bool result = canvas->quickReject(rect_);
+        return result ? JNI_TRUE : JNI_FALSE;
     }
 
     static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
@@ -368,8 +367,7 @@
                                        jfloat bottom) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkRect r;
-        r.set(SkFloatToScalar(left), SkFloatToScalar(top),
-              SkFloatToScalar(right), SkFloatToScalar(bottom));
+        r.set(left, top, right, bottom);
         bool result = canvas->quickReject(r);
         return result ? JNI_TRUE : JNI_FALSE;
     }
@@ -431,7 +429,7 @@
         SkPoint* pts = storage.get();
         const float* src = floats + offset;
         for (int i = 0; i < count; i++) {
-            pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
+            pts[i].set(src[0], src[1]);
             src += 2;
         }
         canvas->drawPoints(mode, count, pts, paint);
@@ -456,7 +454,7 @@
         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
         const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
 
-        canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
+        canvas->drawPoint(x, y, paint);
     }
 
     static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
@@ -464,9 +462,7 @@
                                     jfloat stopY, jlong paintHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
-                         SkFloatToScalar(stopX), SkFloatToScalar(stopY),
-                         *paint);
+        canvas->drawLine(startX, startY, stopX, stopY, *paint);
     }
 
     static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
@@ -483,11 +479,7 @@
                                     jfloat bottom, jlong paintHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        SkScalar left_ = SkFloatToScalar(left);
-        SkScalar top_ = SkFloatToScalar(top);
-        SkScalar right_ = SkFloatToScalar(right);
-        SkScalar bottom_ = SkFloatToScalar(bottom);
-        canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
+        canvas->drawRectCoords(left, top, right, bottom, *paint);
     }
 
     static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
@@ -503,8 +495,7 @@
                            jfloat cy, jfloat radius, jlong paintHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
-                           SkFloatToScalar(radius), *paint);
+        canvas->drawCircle(cx, cy, radius, *paint);
     }
 
     static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
@@ -514,8 +505,7 @@
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         SkRect oval;
         GraphicsJNI::jrectf_to_rect(env, joval, &oval);
-        canvas->drawArc(oval, SkFloatToScalar(startAngle),
-                        SkFloatToScalar(sweepAngle), useCenter, *paint);
+        canvas->drawArc(oval, startAngle, sweepAngle, useCenter, *paint);
     }
 
     static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
@@ -525,8 +515,7 @@
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         SkRect rect;
         GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
-        canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
-                              *paint);
+        canvas->drawRoundRect(rect, rx, ry, *paint);
     }
 
     static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
@@ -545,8 +534,6 @@
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        SkScalar left_ = SkFloatToScalar(left);
-        SkScalar top_ = SkFloatToScalar(top);
 
         if (canvasDensity == bitmapDensity || canvasDensity == 0
                 || bitmapDensity == 0) {
@@ -556,14 +543,14 @@
                     filteredPaint = *paint;
                 }
                 filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
-                canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
+                canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
             } else {
-                canvas->drawBitmap(*bitmap, left_, top_, paint);
+                canvas->drawBitmap(*bitmap, left, top, paint);
             }
         } else {
             canvas->save();
-            SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
-            canvas->translate(left_, top_);
+            SkScalar scale = canvasDensity / (float)bitmapDensity;
+            canvas->translate(left, top);
             canvas->scale(scale, scale);
 
             SkPaint filteredPaint;
@@ -645,8 +632,7 @@
             return;
         }
 
-        canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
-                           paint);
+        canvas->drawBitmap(bitmap, x, y, paint);
     }
 
     static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
@@ -848,8 +834,8 @@
             MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
             skFace = mfs->GetSkTypeface();
             glyphs[i] = layout->getGlyphId(i);
-            pos[i].fX = SkFloatToScalar(x + layout->getX(i));
-            pos[i].fY = SkFloatToScalar(y + layout->getY(i));
+            pos[i].fX = x + layout->getX(i);
+            pos[i].fY = y + layout->getY(i);
             if (i > 0 && skFace != lastFace) {
                 paint->setTypeface(lastFace);
                 canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
@@ -926,22 +912,18 @@
         flags = paint->getFlags();
     }
     if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
-        SkScalar left = SkFloatToScalar(x);
-        SkScalar right = SkFloatToScalar(x + length);
+        SkScalar left = x;
+        SkScalar right = x + length;
         float textSize = paint->getTextSize();
         float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
         if (flags & SkPaint::kUnderlineText_Flag) {
-            SkScalar top = SkFloatToScalar(y + textSize * kStdUnderline_Offset
-                    - 0.5f * strokeWidth);
-            SkScalar bottom = SkFloatToScalar(y + textSize * kStdUnderline_Offset
-                    + 0.5f * strokeWidth);
+            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
             canvas->drawRectCoords(left, top, right, bottom, *paint);
         }
         if (flags & SkPaint::kStrikeThruText_Flag) {
-            SkScalar top = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
-                    - 0.5f * strokeWidth);
-            SkScalar bottom = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
-                    + 0.5f * strokeWidth);
+            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
             canvas->drawRectCoords(left, top, right, bottom, *paint);
         }
     }
@@ -957,8 +939,8 @@
             int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
         SkPoint* posPtr = new SkPoint[count];
         for (int indx = 0; indx < count; indx++) {
-            posPtr[indx].fX = SkFloatToScalar(x + posArray[indx * 2]);
-            posPtr[indx].fY = SkFloatToScalar(y + posArray[indx * 2 + 1]);
+            posPtr[indx].fX = x + posArray[indx * 2];
+            posPtr[indx].fY = y + posArray[indx * 2 + 1];
         }
         canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
         delete[] posPtr;
@@ -1006,8 +988,8 @@
         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
         int indx;
         for (indx = 0; indx < posCount; indx++) {
-            posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
-            posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
+            posPtr[indx].fX = posArray[indx << 1];
+            posPtr[indx].fY = posArray[(indx << 1) + 1];
         }
 
         SkPaint::TextEncoding encoding = paint->getTextEncoding();
@@ -1037,8 +1019,8 @@
         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
 
         for (int indx = 0; indx < posCount; indx++) {
-            posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
-            posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
+            posPtr[indx].fX = posArray[indx << 1];
+            posPtr[indx].fY = posArray[(indx << 1) + 1];
         }
 
         SkPaint::TextEncoding encoding = paint->getTextEncoding();
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index a59ed19..c66c844 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -51,7 +51,7 @@
         const float* src = autoArray.ptr();
 
 #ifdef SK_SCALAR_IS_FLOAT
-        return reinterpret_cast<jlong>(new SkColorMatrixFilter(src));
+        return reinterpret_cast<jlong>(SkColorMatrixFilter::Create(src));
 #else
         SkASSERT(false);
 #endif
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index 2cb1015..b64ab0d 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -175,10 +175,14 @@
 class SkJavaOutputStream : public SkWStream {
 public:
     SkJavaOutputStream(JNIEnv* env, jobject stream, jbyteArray storage)
-        : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage) {
+        : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage), fBytesWritten(0) {
         fCapacity = env->GetArrayLength(storage);
     }
 
+    virtual size_t bytesWritten() const {
+        return fBytesWritten;
+    }
+
     virtual bool write(const void* buffer, size_t size) {
         JNIEnv* env = fEnv;
         jbyteArray storage = fJavaByteArray;
@@ -213,6 +217,7 @@
 
             buffer = (void*)((char*)buffer + requested);
             size -= requested;
+            fBytesWritten += requested;
         }
         return true;
     }
@@ -226,6 +231,7 @@
     jobject     fJavaOutputStream;  // the caller owns this object
     jbyteArray  fJavaByteArray;     // the caller owns this object
     jint        fCapacity;
+    size_t      fBytesWritten;
 };
 
 SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 2883be9..e4c74b2 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -228,10 +228,10 @@
 {
     SkASSERT(env->IsInstanceOf(obj, gRectF_class));
 
-    r->set(SkFloatToScalar(env->GetFloatField(obj, gRectF_leftFieldID)),
-           SkFloatToScalar(env->GetFloatField(obj, gRectF_topFieldID)),
-           SkFloatToScalar(env->GetFloatField(obj, gRectF_rightFieldID)),
-           SkFloatToScalar(env->GetFloatField(obj, gRectF_bottomFieldID)));
+    r->set(env->GetFloatField(obj, gRectF_leftFieldID),
+           env->GetFloatField(obj, gRectF_topFieldID),
+           env->GetFloatField(obj, gRectF_rightFieldID),
+           env->GetFloatField(obj, gRectF_bottomFieldID));
     return r;
 }
 
@@ -277,8 +277,8 @@
 {
     SkASSERT(env->IsInstanceOf(obj, gPointF_class));
 
-    point->set(SkFloatToScalar(env->GetIntField(obj, gPointF_xFieldID)),
-               SkFloatToScalar(env->GetIntField(obj, gPointF_yFieldID)));
+    point->set(env->GetIntField(obj, gPointF_xFieldID),
+               env->GetIntField(obj, gPointF_yFieldID));
     return point;
 }
 
diff --git a/core/jni/android/graphics/Interpolator.cpp b/core/jni/android/graphics/Interpolator.cpp
index ca04dfe..455f867 100644
--- a/core/jni/android/graphics/Interpolator.cpp
+++ b/core/jni/android/graphics/Interpolator.cpp
@@ -25,26 +25,15 @@
 static void Interpolator_setKeyFrame(JNIEnv* env, jobject clazz, jlong interpHandle, jint index, jint msec, jfloatArray valueArray, jfloatArray blendArray)
 {
     SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
-    SkScalar    blendStorage[4];
-    SkScalar*   blend = NULL;
 
-    AutoJavaFloatArray  autoValues(env, valueArray);
-    float* values = autoValues.ptr();
-    int i, n = autoValues.length();
-
-    SkAutoSTMalloc<16, SkScalar>  storage(n);
-    SkScalar*                     scalars = storage.get();
-
-    for (i = 0; i < n; i++)
-        scalars[i] = SkFloatToScalar(values[i]);
-
-    if (blendArray != NULL) {
-        AutoJavaFloatArray autoBlend(env, blendArray, 4);
-        values = autoBlend.ptr();
-        for (i = 0; i < 4; i++)
-            blendStorage[i] = SkFloatToScalar(values[i]);
-        blend = blendStorage;
-    }
+    AutoJavaFloatArray autoValues(env, valueArray);
+    AutoJavaFloatArray autoBlend(env, blendArray, 4);
+#ifdef SK_SCALAR_IS_FLOAT
+    SkScalar* scalars = autoValues.ptr();
+    SkScalar* blend = autoBlend.ptr();
+#else
+    #error Need to convert float array to SkScalar array before calling the following function.
+#endif
 
     interp->setKeyFrame(index, msec, scalars, blend);
 }
@@ -55,7 +44,7 @@
     if (repeatCount > 32000)
         repeatCount = 32000;
 
-    interp->setRepeatCount(SkFloatToScalar(repeatCount));
+    interp->setRepeatCount(repeatCount);
     interp->setMirror(mirror != 0);
 }
 
diff --git a/core/jni/android/graphics/LayerRasterizer.cpp b/core/jni/android/graphics/LayerRasterizer.cpp
index 29e7db1..79dc275 100644
--- a/core/jni/android/graphics/LayerRasterizer.cpp
+++ b/core/jni/android/graphics/LayerRasterizer.cpp
@@ -12,7 +12,7 @@
         const SkPaint* paint = reinterpret_cast<SkPaint *>(paintHandle);
         SkASSERT(layer);
         SkASSERT(paint);
-        layer->addLayer(*paint, SkFloatToScalar(dx), SkFloatToScalar(dy));
+        layer->addLayer(*paint, dx, dy);
     }
 };
 
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index 5573366..2113330 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -20,7 +20,7 @@
     }
 
     static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkFloatToScalar(radius));
+        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
         SkMaskFilter* filter = SkBlurMaskFilter::Create(
                 (SkBlurMaskFilter::BlurStyle)blurStyle, sigma);
         ThrowIAE_IfNull(env, filter);
@@ -33,19 +33,19 @@
         AutoJavaFloatArray autoDir(env, dirArray, 3);
         float* values = autoDir.ptr();
         for (int i = 0; i < 3; i++) {
-            direction[i] = SkFloatToScalar(values[i]);
+            direction[i] = values[i];
         }
 
-        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkFloatToScalar(radius));
+        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
         SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(sigma,
-                direction, SkFloatToScalar(ambient), SkFloatToScalar(specular));
+                direction, ambient, specular);
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
     }
 
     static jlong createTable(JNIEnv* env, jobject, jbyteArray jtable) {
         AutoJavaByteArray autoTable(env, jtable, 256);
-        SkMaskFilter* filter = new SkTableMaskFilter((const uint8_t*)autoTable.ptr());
+        SkMaskFilter* filter = SkTableMaskFilter::Create((const uint8_t*)autoTable.ptr());
         return reinterpret_cast<jlong>(filter);
     }
 
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index c400c57..23af860 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -65,187 +65,127 @@
     }
      static void setTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->setTranslate(dx_, dy_);
+        obj->setTranslate(dx, dy);
     }
      static void setScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        obj->setScale(sx_, sy_, px_, py_);
+        obj->setScale(sx, sy, px, py);
     }
      static void setScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        obj->setScale(sx_, sy_);
+        obj->setScale(sx, sy);
     }
      static void setRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        obj->setRotate(degrees_, px_, py_);
+        obj->setRotate(degrees, px, py);
     }
      static void setRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        obj->setRotate(degrees_);
+        obj->setRotate(degrees);
     }
      static void setSinCos__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sinValue, jfloat cosValue, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sinValue_ = SkFloatToScalar(sinValue);
-        SkScalar cosValue_ = SkFloatToScalar(cosValue);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        obj->setSinCos(sinValue_, cosValue_, px_, py_);
+        obj->setSinCos(sinValue, cosValue, px, py);
     }
      static void setSinCos__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sinValue, jfloat cosValue) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sinValue_ = SkFloatToScalar(sinValue);
-        SkScalar cosValue_ = SkFloatToScalar(cosValue);
-        obj->setSinCos(sinValue_, cosValue_);
+        obj->setSinCos(sinValue, cosValue);
     }
      static void setSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        obj->setSkew(kx_, ky_, px_, py_);
+        obj->setSkew(kx, ky, px, py);
     }
      static void setSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        obj->setSkew(kx_, ky_);
+        obj->setSkew(kx, ky);
     }
-     static jboolean setConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong aHandle, jlong bHandle) {
+     static void setConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong aHandle, jlong bHandle) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
         SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle);
         SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle);
-        return obj->setConcat(*a, *b) ? JNI_TRUE : JNI_FALSE;
+        obj->setConcat(*a, *b);
     }
 
-    static jboolean preTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void preTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        return obj->preTranslate(dx_, dy_) ? JNI_TRUE : JNI_FALSE;
+        obj->preTranslate(dx, dy);
     }
 
-    static jboolean preScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
+    static void preScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->preScale(sx_, sy_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->preScale(sx, sy, px, py);
     }
 
-    static jboolean preScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
+    static void preScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        return obj->preScale(sx_, sy_) ? JNI_TRUE : JNI_FALSE;
+        obj->preScale(sx, sy);
     }
 
-    static jboolean preRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
+    static void preRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->preRotate(degrees_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->preRotate(degrees, px, py);
     }
 
-    static jboolean preRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
+    static void preRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        return obj->preRotate(degrees_) ? JNI_TRUE : JNI_FALSE;
+        obj->preRotate(degrees);
     }
 
-    static jboolean preSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
+    static void preSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->preSkew(kx_, ky_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->preSkew(kx, ky, px, py);
     }
 
-    static jboolean preSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
+    static void preSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        return obj->preSkew(kx_, ky_) ? JNI_TRUE : JNI_FALSE;
+        obj->preSkew(kx, ky);
     }
 
-    static jboolean preConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
+    static void preConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
         SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
-        return obj->preConcat(*other) ? JNI_TRUE : JNI_FALSE;
+        obj->preConcat(*other);
     }
 
-    static jboolean postTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void postTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        return obj->postTranslate(dx_, dy_) ? JNI_TRUE : JNI_FALSE;
+        obj->postTranslate(dx, dy);
     }
 
-    static jboolean postScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
+    static void postScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->postScale(sx_, sy_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->postScale(sx, sy, px, py);
     }
 
-    static jboolean postScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
+    static void postScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar sx_ = SkFloatToScalar(sx);
-        SkScalar sy_ = SkFloatToScalar(sy);
-        return obj->postScale(sx_, sy_) ? JNI_TRUE : JNI_FALSE;
+        obj->postScale(sx, sy);
     }
 
-    static jboolean postRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
+    static void postRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->postRotate(degrees_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->postRotate(degrees, px, py);
     }
 
-    static jboolean postRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
+    static void postRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar degrees_ = SkFloatToScalar(degrees);
-        return obj->postRotate(degrees_) ? JNI_TRUE : JNI_FALSE;
+        obj->postRotate(degrees);
     }
 
-    static jboolean postSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
+    static void postSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        SkScalar px_ = SkFloatToScalar(px);
-        SkScalar py_ = SkFloatToScalar(py);
-        return obj->postSkew(kx_, ky_, px_, py_) ? JNI_TRUE : JNI_FALSE;
+        obj->postSkew(kx, ky, px, py);
     }
 
-    static jboolean postSkew__FF(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat kx, jfloat ky) {
+    static void postSkew__FF(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat kx, jfloat ky) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        SkScalar kx_ = SkFloatToScalar(kx);
-        SkScalar ky_ = SkFloatToScalar(ky);
-        return matrix->postSkew(kx_, ky_) ? JNI_TRUE : JNI_FALSE;
+        matrix->postSkew(kx, ky);
     }
 
-    static jboolean postConcat(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong otherHandle) {
+    static void postConcat(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong otherHandle) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
-        return matrix->postConcat(*other) ? JNI_TRUE : JNI_FALSE;
+        matrix->postConcat(*other);
     }
 
     static jboolean setRectToRect(JNIEnv* env, jobject clazz, jlong matrixHandle, jobject src, jobject dst, jint stfHandle) {
@@ -321,7 +261,7 @@
     static jfloat mapRadius(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat radius) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         float result;
-        result = SkScalarToFloat(matrix->mapRadius(SkFloatToScalar(radius)));
+        result = SkScalarToFloat(matrix->mapRadius(radius));
         return static_cast<jfloat>(result);
     }
     static void getValues(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloatArray values) {
@@ -374,23 +314,23 @@
     {"native_setSinCos","(JFF)V", (void*) SkMatrixGlue::setSinCos__FF},
     {"native_setSkew","(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF},
     {"native_setSkew","(JFF)V", (void*) SkMatrixGlue::setSkew__FF},
-    {"native_setConcat","(JJJ)Z", (void*) SkMatrixGlue::setConcat},
-    {"native_preTranslate","(JFF)Z", (void*) SkMatrixGlue::preTranslate},
-    {"native_preScale","(JFFFF)Z", (void*) SkMatrixGlue::preScale__FFFF},
-    {"native_preScale","(JFF)Z", (void*) SkMatrixGlue::preScale__FF},
-    {"native_preRotate","(JFFF)Z", (void*) SkMatrixGlue::preRotate__FFF},
-    {"native_preRotate","(JF)Z", (void*) SkMatrixGlue::preRotate__F},
-    {"native_preSkew","(JFFFF)Z", (void*) SkMatrixGlue::preSkew__FFFF},
-    {"native_preSkew","(JFF)Z", (void*) SkMatrixGlue::preSkew__FF},
-    {"native_preConcat","(JJ)Z", (void*) SkMatrixGlue::preConcat},
-    {"native_postTranslate","(JFF)Z", (void*) SkMatrixGlue::postTranslate},
-    {"native_postScale","(JFFFF)Z", (void*) SkMatrixGlue::postScale__FFFF},
-    {"native_postScale","(JFF)Z", (void*) SkMatrixGlue::postScale__FF},
-    {"native_postRotate","(JFFF)Z", (void*) SkMatrixGlue::postRotate__FFF},
-    {"native_postRotate","(JF)Z", (void*) SkMatrixGlue::postRotate__F},
-    {"native_postSkew","(JFFFF)Z", (void*) SkMatrixGlue::postSkew__FFFF},
-    {"native_postSkew","(JFF)Z", (void*) SkMatrixGlue::postSkew__FF},
-    {"native_postConcat","(JJ)Z", (void*) SkMatrixGlue::postConcat},
+    {"native_setConcat","(JJJ)V", (void*) SkMatrixGlue::setConcat},
+    {"native_preTranslate","(JFF)V", (void*) SkMatrixGlue::preTranslate},
+    {"native_preScale","(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF},
+    {"native_preScale","(JFF)V", (void*) SkMatrixGlue::preScale__FF},
+    {"native_preRotate","(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF},
+    {"native_preRotate","(JF)V", (void*) SkMatrixGlue::preRotate__F},
+    {"native_preSkew","(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF},
+    {"native_preSkew","(JFF)V", (void*) SkMatrixGlue::preSkew__FF},
+    {"native_preConcat","(JJ)V", (void*) SkMatrixGlue::preConcat},
+    {"native_postTranslate","(JFF)V", (void*) SkMatrixGlue::postTranslate},
+    {"native_postScale","(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF},
+    {"native_postScale","(JFF)V", (void*) SkMatrixGlue::postScale__FF},
+    {"native_postRotate","(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF},
+    {"native_postRotate","(JF)V", (void*) SkMatrixGlue::postRotate__F},
+    {"native_postSkew","(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF},
+    {"native_postSkew","(JFF)V", (void*) SkMatrixGlue::postSkew__FF},
+    {"native_postConcat","(JJ)V", (void*) SkMatrixGlue::postConcat},
     {"native_setRectToRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect},
     {"native_setPolyToPoly","(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly},
     {"native_invert","(JJ)Z", (void*) SkMatrixGlue::invert},
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 461f723..5f9a9b7 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -74,12 +74,10 @@
 
     SkMovie* m = J2Movie(env, movie);
     SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
-    SkScalar sx = SkFloatToScalar(fx);
-    SkScalar sy = SkFloatToScalar(fy);
     const SkBitmap& b = m->bitmap();
     const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL;
 
-    c->drawBitmap(b, sx, sy, p);
+    c->drawBitmap(b, fx, fy, p);
 }
 
 static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 871e24d..855d267 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -97,7 +97,7 @@
         } else {
             canvas->save();
 
-            SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
+            SkScalar scale = destDensity / (float)srcDensity;
             canvas->translate(bounds.fLeft, bounds.fTop);
             canvas->scale(scale, scale);
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 1167bfe..f77a389 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -206,7 +206,7 @@
 
     static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(SkFloatToScalar(width));
+        GraphicsJNI::getNativePaint(env, paint)->setStrokeWidth(width);
     }
 
     static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
@@ -216,7 +216,7 @@
 
     static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(SkFloatToScalar(miter));
+        GraphicsJNI::getNativePaint(env, paint)->setStrokeMiter(miter);
     }
 
     static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
@@ -364,7 +364,7 @@
 
     static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setTextSize(SkFloatToScalar(textSize));
+        GraphicsJNI::getNativePaint(env, paint)->setTextSize(textSize);
     }
 
     static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
@@ -374,7 +374,7 @@
 
     static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(SkFloatToScalar(scaleX));
+        GraphicsJNI::getNativePaint(env, paint)->setTextScaleX(scaleX);
     }
 
     static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
@@ -384,7 +384,7 @@
 
     static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(SkFloatToScalar(skewX));
+        GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(skewX);
     }
 
     static jfloat ascent(JNIEnv* env, jobject paint) {
@@ -747,10 +747,7 @@
             paint->setLooper(NULL);
         }
         else {
-            paint->setLooper(new SkBlurDrawLooper(SkFloatToScalar(radius),
-                                                  SkFloatToScalar(dx),
-                                                  SkFloatToScalar(dy),
-                                                  (SkColor)color))->unref();
+            paint->setLooper(new SkBlurDrawLooper(radius, dx, dy, (SkColor)color))->unref();
         }
     }
 
@@ -764,7 +761,7 @@
         }
         SkScalar     measured;
         size_t       bytes = paint.breakText(value->getGlyphs(), value->getGlyphsCount() << 1,
-                                   SkFloatToScalar(maxWidth), &measured, tbd);
+                maxWidth, &measured, tbd);
         SkASSERT((bytes & 1) == 0);
 
         if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index e580d36..1ad1a8a 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -93,18 +93,18 @@
         return obj->isEmpty();
     }
  
-    static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject rect) {
-        SkRect rect_;
+    static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) {
+        SkRect rect;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        jboolean result = obj->isRect(&rect_);
-        GraphicsJNI::rect_to_jrectf(rect_, env, rect);
+        jboolean result = obj->isRect(&rect);
+        GraphicsJNI::rect_to_jrectf(rect, env, jrect);
         return result;
     }
  
-    static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject bounds) {
+    static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        const SkRect& bounds_ = obj->getBounds();
-        GraphicsJNI::rect_to_jrectf(bounds_, env, bounds);
+        const SkRect& bounds = obj->getBounds();
+        GraphicsJNI::rect_to_jrectf(bounds, env, jbounds);
     }
  
     static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) {
@@ -114,79 +114,49 @@
  
     static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar x_ = SkFloatToScalar(x);
-        SkScalar y_ = SkFloatToScalar(y);
-        obj->moveTo(x_, y_);
+        obj->moveTo(x, y);
     }
  
     static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->rMoveTo(dx_, dy_);
+        obj->rMoveTo(dx, dy);
     }
  
     static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar x_ = SkFloatToScalar(x);
-        SkScalar y_ = SkFloatToScalar(y);
-        obj->lineTo(x_, y_);
+        obj->lineTo(x, y);
     }
  
     static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->rLineTo(dx_, dy_);
+        obj->rLineTo(dx, dy);
     }
  
     static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar x1_ = SkFloatToScalar(x1);
-        SkScalar y1_ = SkFloatToScalar(y1);
-        SkScalar x2_ = SkFloatToScalar(x2);
-        SkScalar y2_ = SkFloatToScalar(y2);
-        obj->quadTo(x1_, y1_, x2_, y2_);
+        obj->quadTo(x1, y1, x2, y2);
     }
  
     static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar dx1_ = SkFloatToScalar(dx1);
-        SkScalar dy1_ = SkFloatToScalar(dy1);
-        SkScalar dx2_ = SkFloatToScalar(dx2);
-        SkScalar dy2_ = SkFloatToScalar(dy2);
-        obj->rQuadTo(dx1_, dy1_, dx2_, dy2_);
+        obj->rQuadTo(dx1, dy1, dx2, dy2);
     }
  
     static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar x1_ = SkFloatToScalar(x1);
-        SkScalar y1_ = SkFloatToScalar(y1);
-        SkScalar x2_ = SkFloatToScalar(x2);
-        SkScalar y2_ = SkFloatToScalar(y2);
-        SkScalar x3_ = SkFloatToScalar(x3);
-        SkScalar y3_ = SkFloatToScalar(y3);
-        obj->cubicTo(x1_, y1_, x2_, y2_, x3_, y3_);
+        obj->cubicTo(x1, y1, x2, y2, x3, y3);
     }
  
     static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar x1_ = SkFloatToScalar(x1);
-        SkScalar y1_ = SkFloatToScalar(y1);
-        SkScalar x2_ = SkFloatToScalar(x2);
-        SkScalar y2_ = SkFloatToScalar(y2);
-        SkScalar x3_ = SkFloatToScalar(x3);
-        SkScalar y3_ = SkFloatToScalar(y3);
-        obj->rCubicTo(x1_, y1_, x2_, y2_, x3_, y3_);
+        obj->rCubicTo(x1, y1, x2, y2, x3, y3);
     }
  
     static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkRect oval_;
         GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
-        SkScalar startAngle_ = SkFloatToScalar(startAngle);
-        SkScalar sweepAngle_ = SkFloatToScalar(sweepAngle);
-        obj->arcTo(oval_, startAngle_, sweepAngle_, forceMoveTo);
+        obj->arcTo(oval_, startAngle, sweepAngle, forceMoveTo);
     }
  
     static void close(JNIEnv* env, jobject clazz, jlong objHandle) {
@@ -194,22 +164,18 @@
         obj->close();
     }
  
-    static void addRect__RectFI(JNIEnv* env, jobject clazz, jlong objHandle, jobject rect, jint dirHandle) {
-        SkRect rect_;
+    static void addRect__RectFI(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect, jint dirHandle) {
+        SkRect rect;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
-        obj->addRect(rect_, dir);
+        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
+        obj->addRect(rect, dir);
     }
  
     static void addRect__FFFFI(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        SkScalar left_ = SkFloatToScalar(left);
-        SkScalar top_ = SkFloatToScalar(top);
-        SkScalar right_ = SkFloatToScalar(right);
-        SkScalar bottom_ = SkFloatToScalar(bottom);
-        obj->addRect(left_, top_, right_, bottom_, dir);
+        obj->addRect(left, top, right, bottom, dir);
     }
  
     static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jint dirHandle) {
@@ -223,54 +189,44 @@
     static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        SkScalar x_ = SkFloatToScalar(x);
-        SkScalar y_ = SkFloatToScalar(y);
-        SkScalar radius_ = SkFloatToScalar(radius);
-        obj->addCircle(x_, y_, radius_, dir);
+        obj->addCircle(x, y, radius, dir);
     }
  
     static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle) {
         SkRect oval_;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
-        SkScalar startAngle_ = SkFloatToScalar(startAngle);
-        SkScalar sweepAngle_ = SkFloatToScalar(sweepAngle);
-        obj->addArc(oval_, startAngle_, sweepAngle_);
+        obj->addArc(oval_, startAngle, sweepAngle);
     }
  
-    static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject rect,
+    static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect,
             jfloat rx, jfloat ry, jint dirHandle) {
-        SkRect rect_;
+        SkRect rect;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
-        SkScalar rx_ = SkFloatToScalar(rx);
-        SkScalar ry_ = SkFloatToScalar(ry);
-        obj->addRoundRect(rect_, rx_, ry_, dir);
+        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
+        obj->addRoundRect(rect, rx, ry, dir);
     }
     
-    static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jobject rect,
+    static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jobject jrect,
             jfloatArray array, jint dirHandle) {
-        SkRect rect_;
+        SkRect rect;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
+        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
         AutoJavaFloatArray  afa(env, array, 8);
+#ifdef SK_SCALAR_IS_FLOAT
         const float* src = afa.ptr();
-        SkScalar dst[8];
-        
-        for (int i = 0; i < 8; i++) {
-            dst[i] = SkFloatToScalar(src[i]);
-        }
-        obj->addRoundRect(rect_, dst, dir);
+#else
+        #error Need to convert float array to SkScalar array before calling the following function.
+#endif
+        obj->addRoundRect(rect, src, dir);
     }
     
     static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->addPath(*src, dx_, dy_);
+        obj->addPath(*src, dx, dy);
     }
  
     static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) {
@@ -289,23 +245,17 @@
     static void offset__FFPath(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy, jlong dstHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->offset(dx_, dy_, dst);
+        obj->offset(dx, dy, dst);
     }
  
     static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->offset(dx_, dy_);
+        obj->offset(dx, dy);
     }
 
     static void setLastPoint(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkScalar dx_ = SkFloatToScalar(dx);
-        SkScalar dy_ = SkFloatToScalar(dy);
-        obj->setLastPt(dx_, dy_);
+        obj->setLastPt(dx, dy);
     }
  
     static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) {
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index 2803758..28d881d 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,7 @@
                                      jlong outerHandle, jlong innerHandle) {
         SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
         SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
-        SkPathEffect* effect = new SkComposePathEffect(outer, inner);
+        SkPathEffect* effect = SkComposePathEffect::Create(outer, inner);
         return reinterpret_cast<jlong>(effect);
     }
 
@@ -28,22 +28,20 @@
                                  jlong firstHandle, jlong secondHandle) {
         SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
         SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
-        SkPathEffect* effect = new SkSumPathEffect(first, second);
+        SkPathEffect* effect = SkSumPathEffect::Create(first, second);
         return reinterpret_cast<jlong>(effect);
     }
 
     static jlong Dash_constructor(JNIEnv* env, jobject,
                                       jfloatArray intervalArray, jfloat phase) {
         AutoJavaFloatArray autoInterval(env, intervalArray);
-        int     count = autoInterval.length() & ~1;  // even number
-        float*  values = autoInterval.ptr();
-
-        SkAutoSTMalloc<32, SkScalar>    storage(count);
-        SkScalar*                       intervals = storage.get();
-        for (int i = 0; i < count; i++) {
-            intervals[i] = SkFloatToScalar(values[i]);
-        }
-        SkPathEffect* effect = new SkDashPathEffect(intervals, count, SkFloatToScalar(phase));
+        int         count = autoInterval.length() & ~1;  // even number
+#ifdef SK_SCALAR_IS_FLOAT
+        SkScalar*   intervals = autoInterval.ptr();
+#else
+        #error Need to convert float array to SkScalar array before calling the following function.
+#endif
+        SkPathEffect* effect = SkDashPathEffect::Create(intervals, count, phase);
         return reinterpret_cast<jlong>(effect);
     }
 
@@ -51,20 +49,19 @@
                   jlong shapeHandle, jfloat advance, jfloat phase, jint style) {
         const SkPath* shape = reinterpret_cast<SkPath*>(shapeHandle);
         SkASSERT(shape != NULL);
-        SkPathEffect* effect = new SkPath1DPathEffect(*shape, SkFloatToScalar(advance),
-                     SkFloatToScalar(phase), (SkPath1DPathEffect::Style)style);
+        SkPathEffect* effect = SkPath1DPathEffect::Create(*shape, advance, phase,
+                (SkPath1DPathEffect::Style)style);
         return reinterpret_cast<jlong>(effect);
     }
 
     static jlong Corner_constructor(JNIEnv* env, jobject, jfloat radius){
-        SkPathEffect* effect = new SkCornerPathEffect(SkFloatToScalar(radius));
+        SkPathEffect* effect = SkCornerPathEffect::Create(radius);
         return reinterpret_cast<jlong>(effect);
     }
 
     static jlong Discrete_constructor(JNIEnv* env, jobject,
                                       jfloat length, jfloat deviation) {
-        SkPathEffect* effect = new SkDiscretePathEffect(SkFloatToScalar(length),
-                                        SkFloatToScalar(deviation));
+        SkPathEffect* effect = SkDiscretePathEffect::Create(length, deviation);
         return reinterpret_cast<jlong>(effect);
     }
 
diff --git a/core/jni/android/graphics/PathMeasure.cpp b/core/jni/android/graphics/PathMeasure.cpp
index 8478a02..13f68a9 100644
--- a/core/jni/android/graphics/PathMeasure.cpp
+++ b/core/jni/android/graphics/PathMeasure.cpp
@@ -96,7 +96,7 @@
         SkScalar*   posPtr = pos ? tmpPos : NULL;
         SkScalar*   tanPtr = tan ? tmpTan : NULL;
         
-        if (!pair->fMeasure.getPosTan(SkFloatToScalar(dist), (SkPoint*)posPtr, (SkVector*)tanPtr)) {
+        if (!pair->fMeasure.getPosTan(dist, (SkPoint*)posPtr, (SkVector*)tanPtr)) {
             return JNI_FALSE;
         }
     
@@ -113,7 +113,7 @@
                           jlong matrixHandle, jint flags) {
         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        bool result = pair->fMeasure.getMatrix(SkFloatToScalar(dist), matrix, (SkPathMeasure::MatrixFlags)flags);
+        bool result = pair->fMeasure.getMatrix(dist, matrix, (SkPathMeasure::MatrixFlags)flags);
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
@@ -121,7 +121,7 @@
                                jfloat stopF, jlong dstHandle, jboolean startWithMoveTo) {
         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
-        bool result = pair->fMeasure.getSegment(SkFloatToScalar(startF), SkFloatToScalar(stopF), dst, startWithMoveTo);
+        bool result = pair->fMeasure.getSegment(startF, stopF, dst, startWithMoveTo);
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 1fe6358..c5e6053 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -39,12 +39,11 @@
 static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
 {
     AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
-    float*      values = autoHSV.ptr();;
-    SkScalar    hsv[3];
-
-    for (int i = 0; i < 3; i++) {
-        hsv[i] = SkFloatToScalar(values[i]);
-    }
+#ifdef SK_SCALAR_IS_FLOAT
+    SkScalar*   hsv = autoHSV.ptr();
+#else
+    #error Need to convert float array to SkScalar array before calling the following function.
+#endif
 
     return static_cast<jint>(SkHSVToColor(alpha, hsv));
 }
@@ -120,28 +119,22 @@
                                     jintArray colorArray, jfloatArray posArray, jint tileMode)
 {
     SkPoint pts[2];
-    pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
-    pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
+    pts[0].set(x0, y0);
+    pts[1].set(x1, y1);
 
     size_t count = env->GetArrayLength(colorArray);
     const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
 
-    SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
-    SkScalar* pos = NULL;
-
-    if (posArray) {
-        AutoJavaFloatArray autoPos(env, posArray, count);
-        const float* posValues = autoPos.ptr();
-        pos = (SkScalar*)storage.get();
-        for (size_t i = 0; i < count; i++) {
-            pos[i] = SkFloatToScalar(posValues[i]);
-        }
-    }
+    AutoJavaFloatArray autoPos(env, posArray, count);
+#ifdef SK_SCALAR_IS_FLOAT
+    SkScalar* pos = autoPos.ptr();
+#else
+    #error Need to convert float array to SkScalar array before calling the following function.
+#endif
 
     SkShader* shader = SkGradientShader::CreateLinear(pts,
-                                reinterpret_cast<const SkColor*>(colorValues),
-                                pos, count,
-                                static_cast<SkShader::TileMode>(tileMode));
+            reinterpret_cast<const SkColor*>(colorValues), pos, count,
+            static_cast<SkShader::TileMode>(tileMode));
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -252,8 +245,8 @@
                                     jint color0, jint color1, jint tileMode)
 {
     SkPoint pts[2];
-    pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
-    pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
+    pts[0].set(x0, y0);
+    pts[1].set(x1, y1);
 
     SkColor colors[2];
     colors[0] = color0;
@@ -270,27 +263,21 @@
 static jlong RadialGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
         jintArray colorArray, jfloatArray posArray, jint tileMode) {
     SkPoint center;
-    center.set(SkFloatToScalar(x), SkFloatToScalar(y));
+    center.set(x, y);
 
     size_t      count = env->GetArrayLength(colorArray);
     const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
 
-    SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
-    SkScalar*                   pos = NULL;
+    AutoJavaFloatArray autoPos(env, posArray, count);
+#ifdef SK_SCALAR_IS_FLOAT
+    SkScalar* pos = autoPos.ptr();
+#else
+    #error Need to convert float array to SkScalar array before calling the following function.
+#endif
 
-    if (posArray) {
-        AutoJavaFloatArray autoPos(env, posArray, count);
-        const float* posValues = autoPos.ptr();
-        pos = (SkScalar*)storage.get();
-        for (size_t i = 0; i < count; i++)
-            pos[i] = SkFloatToScalar(posValues[i]);
-    }
-
-    SkShader* shader = SkGradientShader::CreateRadial(center,
-                                SkFloatToScalar(radius),
-                                reinterpret_cast<const SkColor*>(colorValues),
-                                pos, count,
-                                static_cast<SkShader::TileMode>(tileMode));
+    SkShader* shader = SkGradientShader::CreateRadial(center, radius,
+            reinterpret_cast<const SkColor*>(colorValues), pos, count,
+            static_cast<SkShader::TileMode>(tileMode));
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
                                  JNI_ABORT);
 
@@ -301,14 +288,14 @@
 static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius,
         jint color0, jint color1, jint tileMode) {
     SkPoint center;
-    center.set(SkFloatToScalar(x), SkFloatToScalar(y));
+    center.set(x, y);
 
     SkColor colors[2];
     colors[0] = color0;
     colors[1] = color1;
 
-    SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL,
-                                          2, (SkShader::TileMode)tileMode);
+    SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2,
+            (SkShader::TileMode)tileMode);
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
@@ -381,22 +368,15 @@
     size_t      count = env->GetArrayLength(jcolors);
     const jint* colors = env->GetIntArrayElements(jcolors, NULL);
 
-    SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0);
-    SkScalar*                   pos = NULL;
+    AutoJavaFloatArray autoPos(env, jpositions, count);
+#ifdef SK_SCALAR_IS_FLOAT
+    SkScalar* pos = autoPos.ptr();
+#else
+    #error Need to convert float array to SkScalar array before calling the following function.
+#endif
 
-    if (NULL != jpositions) {
-        AutoJavaFloatArray autoPos(env, jpositions, count);
-        const float* posValues = autoPos.ptr();
-        pos = (SkScalar*)storage.get();
-        for (size_t i = 0; i < count; i++) {
-            pos[i] = SkFloatToScalar(posValues[i]);
-        }
-    }
-
-    SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x),
-                                     SkFloatToScalar(y),
-                                     reinterpret_cast<const SkColor*>(colors),
-                                     pos, count);
+    SkShader* shader = SkGradientShader::CreateSweep(x, y,
+            reinterpret_cast<const SkColor*>(colors), pos, count);
     env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
                                  JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -408,8 +388,7 @@
     SkColor colors[2];
     colors[0] = color0;
     colors[1] = color1;
-    SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y),
-                                         colors, NULL, 2);
+    SkShader* s = SkGradientShader::CreateSweep(x, y, colors, NULL, 2);
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index 34dc3e8..d0b6f7c 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -58,10 +58,8 @@
     if (value == NULL) {
         return ;
     }
-    SkScalar x_ = SkFloatToScalar(x);
-    SkScalar y_ = SkFloatToScalar(y);
     // Beware: this needs Glyph encoding (already done on the Paint constructor)
-    paint->getTextPath(value->getGlyphs(), value->getGlyphsCount() * 2, x_, y_, path);
+    paint->getTextPath(value->getGlyphs(), value->getGlyphsCount() * 2, x, y, path);
 }
 
 void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
@@ -90,9 +88,6 @@
                                 int bidiFlags, jfloat hOffset, jfloat vOffset,
                                 SkPath* path, SkCanvas* canvas) {
 
-    SkScalar h_ = SkFloatToScalar(hOffset);
-    SkScalar v_ = SkFloatToScalar(vOffset);
-
     sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
             text, 0, count, count, bidiFlags);
     if (value == NULL) {
@@ -100,7 +95,8 @@
     }
 
     // Beware: this needs Glyph encoding (already done on the Paint constructor)
-    canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path, h_, v_, *paint);
+    canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path,
+            hOffset, vOffset, *paint);
 }
 
 }
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index eedceb7..6bf6f8a 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -36,12 +36,12 @@
                                 jint tolerance, jint modeHandle)
     {
         SkAvoidXfermode::Mode mode = static_cast<SkAvoidXfermode::Mode>(modeHandle);
-        return reinterpret_cast<jlong>(new SkAvoidXfermode(opColor, tolerance, mode));
+        return reinterpret_cast<jlong>(SkAvoidXfermode::Create(opColor, tolerance, mode));
     }
 
     static jlong pixelxor_create(JNIEnv* env, jobject, jint opColor)
     {
-        return reinterpret_cast<jlong>(new SkPixelXorXfermode(opColor));
+        return reinterpret_cast<jlong>(SkPixelXorXfermode::Create(opColor));
     }
 };
 
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 58b61ba..307293f 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -230,7 +230,7 @@
         ssize_t offset;
         size_t size;
         sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
-        ALOGV("copyAndPost: off=%ld, size=%d", offset, size);
+        ALOGV("copyAndPost: off=%zd, size=%zu", offset, size);
         uint8_t *heapBase = (uint8_t*)heap->base();
 
         if (heapBase != NULL) {
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 0132b5f..d8faaf3 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -166,7 +166,7 @@
         ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask);
         return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
     }
-    uint32_t nbChannels = popcount(channelMask);
+    uint32_t channelCount = popcount(channelMask);
 
     // compare the format against the Java constants
     audio_format_t format = audioFormatToNative(audioFormat);
@@ -181,7 +181,7 @@
          ALOGE("Error creating AudioRecord: frameCount is 0.");
         return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
     }
-    size_t frameSize = nbChannels * bytesPerSample;
+    size_t frameSize = channelCount * bytesPerSample;
     size_t frameCount = buffSizeInBytes / frameSize;
 
     if ((uint32_t(source) >= AUDIO_SOURCE_CNT) && (uint32_t(source) != AUDIO_SOURCE_HOTWORD)) {
@@ -220,7 +220,7 @@
     lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
     lpCallbackData->busy = false;
 
-    lpRecorder->set((audio_source_t) source,
+    const status_t status = lpRecorder->set((audio_source_t) source,
         sampleRateInHertz,
         format,        // word length, PCM
         channelMask,
@@ -231,7 +231,6 @@
         true,          // threadCanCallJava
         sessionId);
 
-    const status_t status = lpRecorder->initCheck();
     if (status != NO_ERROR) {
         ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
                 status);
@@ -312,7 +311,7 @@
     if (lpRecorder == NULL) {
         return;
     }
-    ALOGV("About to delete lpRecorder: %" PRIxPTR "\n", lpRecorder.get());
+    ALOGV("About to delete lpRecorder: %p", lpRecorder.get());
     lpRecorder->stop();
 
     audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField(
@@ -325,7 +324,7 @@
     // delete the callback information
     if (lpCookie) {
         Mutex::Autolock l(sLock);
-        ALOGV("deleting lpCookie: %" PRIxPTR "\n", lpCookie);
+        ALOGV("deleting lpCookie: %p", lpCookie);
         while (lpCookie->busy) {
             if (lpCookie->cond.waitRelative(sLock,
                                             milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
@@ -501,17 +500,17 @@
 // returns 0 if the parameter combination is not supported.
 // return -1 if there was an error querying the buffer size.
 static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env,  jobject thiz,
-    jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
+    jint sampleRateInHertz, jint channelCount, jint audioFormat) {
 
     ALOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)",
-          sampleRateInHertz, nbChannels, audioFormat);
+          sampleRateInHertz, channelCount, audioFormat);
 
     size_t frameCount = 0;
     audio_format_t format = audioFormatToNative(audioFormat);
     status_t result = AudioRecord::getMinFrameCount(&frameCount,
             sampleRateInHertz,
             format,
-            audio_channel_in_mask_from_count(nbChannels));
+            audio_channel_in_mask_from_count(channelCount));
 
     if (result == BAD_VALUE) {
         return 0;
@@ -519,7 +518,7 @@
     if (result != NO_ERROR) {
         return -1;
     }
-    return frameCount * nbChannels * audio_bytes_per_sample(format);
+    return frameCount * channelCount * audio_bytes_per_sample(format);
 }
 
 
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 3a5b566..162d0c4 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -26,6 +26,7 @@
 #include <utils/Log.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
+#include <audio_utils/primitives.h>
 
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
@@ -203,25 +204,30 @@
     uint32_t afSampleRate;
     size_t afFrameCount;
 
-    if (AudioSystem::getOutputFrameCount(&afFrameCount, (audio_stream_type_t) streamType) != NO_ERROR) {
-        ALOGE("Error creating AudioTrack: Could not get AudioSystem frame count.");
+    status_t status = AudioSystem::getOutputFrameCount(&afFrameCount,
+            (audio_stream_type_t) streamType);
+    if (status != NO_ERROR) {
+        ALOGE("Error %d creating AudioTrack: Could not get AudioSystem frame count "
+              "for stream type %d.", status, streamType);
         return (jint) AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate, (audio_stream_type_t) streamType) != NO_ERROR) {
-        ALOGE("Error creating AudioTrack: Could not get AudioSystem sampling rate.");
+    status = AudioSystem::getOutputSamplingRate(&afSampleRate, (audio_stream_type_t) streamType);
+    if (status != NO_ERROR) {
+        ALOGE("Error %d creating AudioTrack: Could not get AudioSystem sampling rate "
+              "for stream type %d.", status, streamType);
         return (jint) AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
 
     // Java channel masks don't map directly to the native definition, but it's a simple shift
     // to skip the two deprecated channel configurations "default" and "mono".
-    uint32_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
+    audio_channel_mask_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
 
     if (!audio_is_output_channel(nativeChannelMask)) {
         ALOGE("Error creating AudioTrack: invalid channel mask %#x.", javaChannelMask);
         return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
     }
 
-    int nbChannels = popcount(nativeChannelMask);
+    uint32_t channelCount = popcount(nativeChannelMask);
 
     // check the stream type
     audio_stream_type_t atStreamType;
@@ -237,7 +243,7 @@
         atStreamType = (audio_stream_type_t) streamType;
         break;
     default:
-        ALOGE("Error creating AudioTrack: unknown stream type.");
+        ALOGE("Error creating AudioTrack: unknown stream type %d.", streamType);
         return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE;
     }
 
@@ -245,8 +251,7 @@
     // This function was called from Java, so we compare the format against the Java constants
     audio_format_t format = audioFormatToNative(audioFormat);
     if (format == AUDIO_FORMAT_INVALID) {
-
-        ALOGE("Error creating AudioTrack: unsupported audio format.");
+        ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
         return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
     }
 
@@ -265,7 +270,7 @@
 
     // compute the frame count
     const size_t bytesPerSample = audio_bytes_per_sample(format);
-    size_t frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
+    size_t frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
 
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
@@ -303,7 +308,7 @@
     switch (memoryMode) {
     case MODE_STREAM:
 
-        lpTrack->set(
+        status = lpTrack->set(
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
@@ -325,7 +330,7 @@
             goto native_init_failure;
         }
 
-        lpTrack->set(
+        status = lpTrack->set(
             atStreamType,// stream type
             sampleRateInHertz,
             format,// word length, PCM
@@ -344,8 +349,8 @@
         goto native_init_failure;
     }
 
-    if (lpTrack->initCheck() != NO_ERROR) {
-        ALOGE("Error initializing AudioTrack");
+    if (status != NO_ERROR) {
+        ALOGE("Error %d initializing AudioTrack", status);
         goto native_init_failure;
     }
 
@@ -546,10 +551,8 @@
             }
             int count = sizeInBytes;
             int16_t *dst = (int16_t *)track->sharedBuffer()->pointer();
-            const int8_t *src = (const int8_t *)(data + offsetInBytes);
-            while (count--) {
-                *dst++ = (int16_t)(*src++^0x80) << 8;
-            }
+            const uint8_t *src = (const uint8_t *)(data + offsetInBytes);
+            memcpy_to_i16_from_u8(dst, src, count);
             // even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide
             // the 8bit mixer restriction from the user of this function
             written = sizeInBytes;
@@ -853,9 +856,10 @@
         break;
     }
 
-    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType) != NO_ERROR) {
-        ALOGE("AudioSystem::getOutputSamplingRate() for stream type %d failed in AudioTrack JNI",
-            nativeStreamType);
+    status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType);
+    if (status != NO_ERROR) {
+        ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d "
+              "in AudioTrack JNI", status, nativeStreamType);
         return DEFAULT_OUTPUT_SAMPLE_RATE;
     } else {
         return afSamplingRate;
@@ -867,7 +871,7 @@
 // returns the minimum required size for the successful creation of a streaming AudioTrack
 // returns -1 if there was an error querying the hardware.
 static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env,  jobject thiz,
-    jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
+    jint sampleRateInHertz, jint channelCount, jint audioFormat) {
 
     size_t frameCount;
     const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
@@ -879,21 +883,26 @@
     }
     const audio_format_t format = audioFormatToNative(audioFormat);
     const size_t bytesPerSample = audio_bytes_per_sample(format);
-    return frameCount * nbChannels * bytesPerSample;
+    return frameCount * channelCount * bytesPerSample;
 }
 
 // ----------------------------------------------------------------------------
-static void
+static jint
 android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
 {
     sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
     if (lpTrack == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
-        return;
+        return -1;
     }
 
-    lpTrack->setAuxEffectSendLevel(level);
+    status_t status = lpTrack->setAuxEffectSendLevel(level);
+    if (status != NO_ERROR) {
+        ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d",
+                level, status);
+    }
+    return (jint) status;
 }
 
 // ----------------------------------------------------------------------------
@@ -949,7 +958,7 @@
     {"native_get_min_buff_size",
                              "(III)I",   (void *)android_media_AudioTrack_get_min_buff_size},
     {"native_setAuxEffectSendLevel",
-                             "(F)V",     (void *)android_media_AudioTrack_setAuxEffectSendLevel},
+                             "(F)I",     (void *)android_media_AudioTrack_setAuxEffectSendLevel},
     {"native_attachAuxEffect",
                              "(I)I",     (void *)android_media_AudioTrack_attachAuxEffect},
 };
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index cbed99f..a4efed7 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -19,8 +19,8 @@
 
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <cutils/process_name.h>
 #include <cutils/sched_policy.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -385,7 +385,9 @@
     }
 
     if (name8.size() > 0) {
-        ProcessState::self()->setArgV0(name8.string());
+        const char* procName = name8.string();
+        set_process_name(procName);
+        AndroidRuntime::getRuntime()->setArgv0(procName);
     }
 }
 
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index e45c1b9..180c625 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -26,6 +26,8 @@
 
 #include <utils/Timers.h>
 
+#include <private/hwui/DrawGlInfo.h>
+
 #include <Caches.h>
 #include <Extensions.h>
 #include <LayerRenderer.h>
@@ -155,6 +157,14 @@
     renderNode->updateProperties();
 }
 
+static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
+        jlong functorPtr, jboolean hasContext) {
+    using namespace android::uirenderer;
+    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
+    DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext;
+    (*functor)(mode, NULL);
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -187,6 +197,7 @@
     { "nDestroyLayer",         "(J)V",  (void*) android_view_GLRenderer_destroyLayer },
     { "nSetDisplayListData",  "(JJ)V", (void*) android_view_GLRenderer_setDisplayListData },
     { "nUpdateRenderNodeProperties", "(J)V", (void*) android_view_GLRenderer_updateRenderNodeProperties },
+    { "nInvokeFunctor",        "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
 #endif
 
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 3e359d4..cf95657 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -59,17 +59,18 @@
 
 static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz) {
     RenderNode* displayList = new RenderNode();
+    displayList->incStrong(0);
     return reinterpret_cast<jlong>(displayList);
 }
 
 static void android_view_RenderNode_destroyDisplayList(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    RenderNode::destroyDisplayListDeferred(displayList);
+    displayList->decStrong(0);
 }
 
 // ----------------------------------------------------------------------------
-// RenderProperties
+// RenderProperties - setters
 // ----------------------------------------------------------------------------
 
 static void android_view_RenderNode_setCaching(JNIEnv* env,
@@ -209,22 +210,6 @@
     displayList->mutateStagingProperties().setScaleY(sy);
 }
 
-static void android_view_RenderNode_setTransformationInfo(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float alpha,
-        float translationX, float translationY, float translationZ,
-        float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setAlpha(alpha);
-    displayList->mutateStagingProperties().setTranslationX(translationX);
-    displayList->mutateStagingProperties().setTranslationY(translationY);
-    displayList->mutateStagingProperties().setTranslationZ(translationZ);
-    displayList->mutateStagingProperties().setRotation(rotation);
-    displayList->mutateStagingProperties().setRotationX(rotationX);
-    displayList->mutateStagingProperties().setRotationY(rotationY);
-    displayList->mutateStagingProperties().setScaleX(scaleX);
-    displayList->mutateStagingProperties().setScaleY(scaleY);
-}
-
 static void android_view_RenderNode_setPivotX(JNIEnv* env,
         jobject clazz, jlong displayListPtr, float px) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -286,6 +271,10 @@
     displayList->mutateStagingProperties().offsetTopBottom(offset);
 }
 
+// ----------------------------------------------------------------------------
+// RenderProperties - getters
+// ----------------------------------------------------------------------------
+
 static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -352,6 +341,12 @@
     return displayList->stagingProperties().getTranslationY();
 }
 
+static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env,
+        jobject clazz, jlong displayListPtr) {
+    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+    return displayList->stagingProperties().getTranslationZ();
+}
+
 static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -370,6 +365,53 @@
     return displayList->stagingProperties().getRotationY();
 }
 
+static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env,
+        jobject clazz, jlong displayListPtr) {
+    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+    return displayList->stagingProperties().isPivotExplicitlySet();
+}
+
+static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env,
+        jobject clazz, jlong displayListPtr) {
+    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+    return displayList->stagingProperties().getMatrixFlags() == 0;
+}
+
+// ----------------------------------------------------------------------------
+// RenderProperties - computed getters
+// ----------------------------------------------------------------------------
+
+static void android_view_RenderNode_getTransformMatrix(JNIEnv* env,
+        jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
+    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
+
+    displayList->mutateStagingProperties().updateMatrix();
+    const SkMatrix* transformMatrix = displayList->stagingProperties().getTransformMatrix();
+
+    if (displayList->stagingProperties().getMatrixFlags() == TRANSLATION) {
+        outMatrix->setTranslate(displayList->stagingProperties().getTranslationX(),
+                displayList->stagingProperties().getTranslationY());
+    } else if (transformMatrix) {
+        *outMatrix = *transformMatrix;
+    } else {
+        outMatrix->setIdentity();
+    }
+}
+
+static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
+        jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
+    // load transform matrix
+    android_view_RenderNode_getTransformMatrix(env, clazz, displayListPtr, outMatrixPtr);
+    SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
+
+    // return it inverted
+    if (!outMatrix->invert(outMatrix)) {
+        // failed to load inverse, pass back identity
+        outMatrix->setIdentity();
+    }
+}
+
 static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -424,8 +466,6 @@
     { "nSetRotationY",         "(JF)V",  (void*) android_view_RenderNode_setRotationY },
     { "nSetScaleX",            "(JF)V",  (void*) android_view_RenderNode_setScaleX },
     { "nSetScaleY",            "(JF)V",  (void*) android_view_RenderNode_setScaleY },
-    { "nSetTransformationInfo","(JFFFFFFFFF)V",
-            (void*) android_view_RenderNode_setTransformationInfo },
     { "nSetPivotX",            "(JF)V",  (void*) android_view_RenderNode_setPivotX },
     { "nSetPivotY",            "(JF)V",  (void*) android_view_RenderNode_setPivotY },
     { "nSetCameraDistance",    "(JF)V",  (void*) android_view_RenderNode_setCameraDistance },
@@ -448,11 +488,18 @@
     { "nGetScaleY",               "(J)F",  (void*) android_view_RenderNode_getScaleY },
     { "nGetTranslationX",         "(J)F",  (void*) android_view_RenderNode_getTranslationX },
     { "nGetTranslationY",         "(J)F",  (void*) android_view_RenderNode_getTranslationY },
+    { "nGetTranslationZ",         "(J)F",  (void*) android_view_RenderNode_getTranslationZ },
     { "nGetRotation",             "(J)F",  (void*) android_view_RenderNode_getRotation },
     { "nGetRotationX",            "(J)F",  (void*) android_view_RenderNode_getRotationX },
     { "nGetRotationY",            "(J)F",  (void*) android_view_RenderNode_getRotationY },
-    { "nGetPivotX",               "(J)F",  (void*) android_view_RenderNode_getPivotX },
-    { "nGetPivotY",               "(J)F",  (void*) android_view_RenderNode_getPivotY },
+    { "nIsPivotExplicitlySet",    "(J)Z",  (void*) android_view_RenderNode_isPivotExplicitlySet },
+    { "nHasIdentityMatrix",       "(J)Z",  (void*) android_view_RenderNode_hasIdentityMatrix },
+
+    { "nGetTransformMatrix",       "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
+    { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
+
+    { "nGetPivotX",                "(J)F",  (void*) android_view_RenderNode_getPivotX },
+    { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
 #endif
 };
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 28cee4b..32890cf 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -139,6 +139,13 @@
     proxy->detachFunctor(functor);
 }
 
+static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
+    proxy->invokeFunctor(functor, waitForCompletion);
+}
+
 static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jrunnable) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -175,6 +182,12 @@
     proxy->destroyLayer(layer);
 }
 
+static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->fence();
+}
+
 #endif
 
 // ----------------------------------------------------------------------------
@@ -196,11 +209,13 @@
     { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
     { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
     { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor },
+    { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
     { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
     { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
+    { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
 #endif
 };
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
new file mode 100644
index 0000000..a61fa87
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android_runtime/AndroidRuntime.h"
+
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
+#include <grp.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cutils/fs.h"
+#include "cutils/multiuser.h"
+#include "cutils/sched_policy.h"
+#include "utils/String8.h"
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+#include <selinux/android.h>
+
+#if defined(__linux__)
+#include <sys/personality.h>
+#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
+#include <sys/capability.h>
+#endif
+#endif
+
+namespace {
+
+using android::String8;
+
+static pid_t gSystemServerPid = 0;
+
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+static jclass gZygoteClass;
+static jmethodID gCallPostForkChildHooks;
+
+// Must match values in com.android.internal.os.Zygote.
+enum MountExternalKind {
+  MOUNT_EXTERNAL_NONE = 0,
+  MOUNT_EXTERNAL_SINGLEUSER = 1,
+  MOUNT_EXTERNAL_MULTIUSER = 2,
+  MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
+static void RuntimeAbort(JNIEnv* env) {
+  env->FatalError("RuntimeAbort");
+}
+
+// This signal handler is for zygote mode, since the zygote must reap its children
+static void SigChldHandler(int /*signal_number*/) {
+  pid_t pid;
+  int status;
+
+  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+     // Log process-death status that we care about.  In general it is
+     // not safe to call LOG(...) from a signal handler because of
+     // possible reentrancy.  However, we know a priori that the
+     // current implementation of LOG() is safe to call from a SIGCHLD
+     // handler in the zygote process.  If the LOG() implementation
+     // changes its locking strategy or its use of syscalls within the
+     // lazy-init critical section, its use here may become unsafe.
+    if (WIFEXITED(status)) {
+      if (WEXITSTATUS(status)) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      }
+    } else if (WIFSIGNALED(status)) {
+      if (WTERMSIG(status) != SIGKILL) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      }
+#ifdef WCOREDUMP
+      if (WCOREDUMP(status)) {
+        ALOGI("Process %d dumped core.", pid);
+      }
+#endif /* ifdef WCOREDUMP */
+    }
+
+    // If the just-crashed process is the system_server, bring down zygote
+    // so that it is restarted by init and system server will be restarted
+    // from there.
+    if (pid == gSystemServerPid) {
+      ALOGE("Exit zygote because system server (%d) has terminated");
+      kill(getpid(), SIGKILL);
+    }
+  }
+
+  if (pid < 0) {
+    ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+  }
+}
+
+// Configures the SIGCHLD handler for the zygote process. This is configured
+// very late, because earlier in the runtime we may fork() and exec()
+// other processes, and we want to waitpid() for those rather than
+// have them be harvested immediately.
+//
+// This ends up being called repeatedly before each fork(), but there's
+// no real harm in that.
+static void SetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SigChldHandler;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error setting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Sets the SIGCHLD handler back to default behavior in zygote children.
+static void UnsetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SIG_DFL;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error unsetting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Calls POSIX setgroups() using the int[] object as an argument.
+// A NULL argument is tolerated.
+static void SetGids(JNIEnv* env, jintArray javaGids) {
+  if (javaGids == NULL) {
+    return;
+  }
+
+  ScopedIntArrayRO gids(env, javaGids);
+  if (gids.get() == NULL) {
+      RuntimeAbort(env);
+  }
+  int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
+  if (rc == -1) {
+    ALOGE("setgroups failed");
+    RuntimeAbort(env);
+  }
+}
+
+// Sets the resource limits via setrlimit(2) for the values in the
+// two-dimensional array of integers that's passed in. The second dimension
+// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
+// treated as an empty array.
+static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+  if (javaRlimits == NULL) {
+    return;
+  }
+
+  rlimit rlim;
+  memset(&rlim, 0, sizeof(rlim));
+
+  for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
+    ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
+    ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
+    if (javaRlimit.size() != 3) {
+      ALOGE("rlimits array must have a second dimension of size 3");
+      RuntimeAbort(env);
+    }
+
+    rlim.rlim_cur = javaRlimit[1];
+    rlim.rlim_max = javaRlimit[2];
+
+    int rc = setrlimit(javaRlimit[0], &rlim);
+    if (rc == -1) {
+      ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
+      RuntimeAbort(env);
+    }
+  }
+}
+
+#if defined(HAVE_ANDROID_OS)
+
+// The debug malloc library needs to know whether it's the zygote or a child.
+extern "C" int gMallocLeakZygoteChild;
+
+static void EnableKeepCapabilities(JNIEnv* env) {
+  int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+  if (rc == -1) {
+    ALOGE("prctl(PR_SET_KEEPCAPS) failed");
+    RuntimeAbort(env);
+  }
+}
+
+static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+  for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+    int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+    if (rc == -1) {
+      if (errno == EINVAL) {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
+              "your kernel is compiled with file capabilities support");
+      } else {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed");
+        RuntimeAbort(env);
+      }
+    }
+  }
+}
+
+static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+  __user_cap_header_struct capheader;
+  memset(&capheader, 0, sizeof(capheader));
+  capheader.version = _LINUX_CAPABILITY_VERSION_3;
+  capheader.pid = 0;
+
+  __user_cap_data_struct capdata[2];
+  memset(&capdata, 0, sizeof(capdata));
+  capdata[0].effective = effective;
+  capdata[1].effective = effective >> 32;
+  capdata[0].permitted = permitted;
+  capdata[1].permitted = permitted >> 32;
+
+  if (capset(&capheader, &capdata[0]) == -1) {
+    ALOGE("capset(%lld, %lld) failed", permitted, effective);
+    RuntimeAbort(env);
+  }
+}
+
+static void SetSchedulerPolicy(JNIEnv* env) {
+  errno = -set_sched_policy(0, SP_DEFAULT);
+  if (errno != 0) {
+    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
+    RuntimeAbort(env);
+  }
+}
+
+#else
+
+static int gMallocLeakZygoteChild = 0;
+
+static void EnableKeepCapabilities(JNIEnv*) {}
+static void DropCapabilitiesBoundingSet(JNIEnv*) {}
+static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
+static void SetSchedulerPolicy(JNIEnv*) {}
+
+#endif
+
+// Create a private mount namespace and bind mount appropriate emulated
+// storage for the given user.
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
+  if (mount_mode == MOUNT_EXTERNAL_NONE) {
+    return true;
+  }
+
+  // See storage config details at http://source.android.com/tech/storage/
+  userid_t user_id = multiuser_get_user_id(uid);
+
+  // Create a second private mount namespace for our process
+  if (unshare(CLONE_NEWNS) == -1) {
+      ALOGW("Failed to unshare(): %d", errno);
+      return false;
+  }
+
+  // Create bind mounts to expose external storage
+  if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+    // These paths must already be created by init.rc
+    const char* source = getenv("EMULATED_STORAGE_SOURCE");
+    const char* target = getenv("EMULATED_STORAGE_TARGET");
+    const char* legacy = getenv("EXTERNAL_STORAGE");
+    if (source == NULL || target == NULL || legacy == NULL) {
+      ALOGW("Storage environment undefined; unable to provide external storage");
+      return false;
+    }
+
+    // Prepare source paths
+
+    // /mnt/shell/emulated/0
+    const String8 source_user(String8::format("%s/%d", source, user_id));
+    // /storage/emulated/0
+    const String8 target_user(String8::format("%s/%d", target, user_id));
+
+    if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
+        || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
+      return false;
+    }
+
+    if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+      // Mount entire external storage tree for all users
+      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s :%d", source, target, errno);
+        return false;
+      }
+    } else {
+      // Only mount user-specific external storage
+      if (TEMP_FAILURE_RETRY(
+              mount(source_user.string(), target_user.string(), NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s: %d", source_user.string(), target_user.string(), errno);
+        return false;
+      }
+    }
+
+    if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+        return false;
+    }
+
+    // Finally, mount user-specific path into place for legacy users
+    if (TEMP_FAILURE_RETRY(
+            mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
+      ALOGW("Failed to mount %s to %s: %d", target_user.string(), legacy, errno);
+      return false;
+    }
+  } else {
+    ALOGW("Mount mode %d unsupported", mount_mode);
+    return false;
+  }
+
+  return true;
+}
+
+#if defined(__linux__)
+static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+    return false;
+#else
+    int major;
+    int minor;
+    struct utsname uts;
+    if (uname(&uts) == -1) {
+        return false;
+    }
+
+    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+        return false;
+    }
+
+    // Kernels before 3.4.* need the workaround.
+    return (major < 3) || ((major == 3) && (minor < 4));
+#endif
+}
+#endif
+
+// Utility to close down the Zygote socket file descriptors while
+// the child is still running as root with Zygote's privileges.  Each
+// descriptor (if any) is closed via dup2(), replacing it with a valid
+// (open) descriptor to /dev/null.
+
+static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+  if (!fdsToClose) {
+    return;
+  }
+  jsize count = env->GetArrayLength(fdsToClose);
+  jint *ar = env->GetIntArrayElements(fdsToClose, 0);
+  if (!ar) {
+      ALOGE("Bad fd array");
+      RuntimeAbort(env);
+  }
+  jsize i;
+  int devnull;
+  for (i = 0; i < count; i++) {
+    devnull = open("/dev/null", O_RDWR);
+    if (devnull < 0) {
+      ALOGE("Failed to open /dev/null");
+      RuntimeAbort(env);
+      continue;
+    }
+    ALOGV("Switching descriptor %d to /dev/null: %d", ar[i], errno);
+    if (dup2(devnull, ar[i]) < 0) {
+      ALOGE("Failed dup2() on descriptor %d", ar[i]);
+      RuntimeAbort(env);
+    }
+    close(devnull);
+  }
+}
+
+void SetThreadName(const char* thread_name) {
+  bool hasAt = false;
+  bool hasDot = false;
+  const char* s = thread_name;
+  while (*s) {
+    if (*s == '.') {
+      hasDot = true;
+    } else if (*s == '@') {
+      hasAt = true;
+    }
+    s++;
+  }
+  const int len = s - thread_name;
+  if (len < 15 || hasAt || !hasDot) {
+    s = thread_name;
+  } else {
+    s = thread_name + len - 15;
+  }
+  // pthread_setname_np fails rather than truncating long strings.
+  char buf[16];       // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
+  strlcpy(buf, s, sizeof(buf)-1);
+  errno = pthread_setname_np(pthread_self(), buf);
+  if (errno != 0) {
+    ALOGW("Unable to set the name of current thread to '%s'", buf);
+  }
+}
+
+// Utility routine to fork zygote and specialize the child process.
+static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
+                                     jint debug_flags, jobjectArray javaRlimits,
+                                     jlong permittedCapabilities, jlong effectiveCapabilities,
+                                     jint mount_external,
+                                     jstring java_se_info, jstring java_se_name,
+                                     bool is_system_server, jintArray fdsToClose) {
+  SetSigChldHandler();
+
+  pid_t pid = fork();
+
+  if (pid == 0) {
+    // The child process.
+    gMallocLeakZygoteChild = 1;
+
+    // Clean up any descriptors which must be closed immediately
+    DetachDescriptors(env, fdsToClose);
+
+    // Keep capabilities across UID change, unless we're staying root.
+    if (uid != 0) {
+      EnableKeepCapabilities(env);
+    }
+
+    DropCapabilitiesBoundingSet(env);
+
+    if (!MountEmulatedStorage(uid, mount_external)) {
+      ALOGW("Failed to mount emulated storage: %d", errno);
+      if (errno == ENOTCONN || errno == EROFS) {
+        // When device is actively encrypting, we get ENOTCONN here
+        // since FUSE was mounted before the framework restarted.
+        // When encrypted device is booting, we get EROFS since
+        // FUSE hasn't been created yet by init.
+        // In either case, continue without external storage.
+      } else {
+        ALOGE("Cannot continue without emulated storage");
+        RuntimeAbort(env);
+      }
+    }
+
+    SetGids(env, javaGids);
+
+    SetRLimits(env, javaRlimits);
+
+    int rc = setresgid(gid, gid, gid);
+    if (rc == -1) {
+      ALOGE("setresgid(%d) failed", gid);
+      RuntimeAbort(env);
+    }
+
+    rc = setresuid(uid, uid, uid);
+    if (rc == -1) {
+      ALOGE("setresuid(%d) failed", uid);
+      RuntimeAbort(env);
+    }
+
+#if defined(__linux__)
+    if (NeedsNoRandomizeWorkaround()) {
+        // Work around ARM kernel ASLR lossage (http://b/5817320).
+        int old_personality = personality(0xffffffff);
+        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+        if (new_personality == -1) {
+            ALOGW("personality(%d) failed", new_personality);
+        }
+    }
+#endif
+
+    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+
+    SetSchedulerPolicy(env);
+
+#if defined(HAVE_ANDROID_OS)
+    {  // NOLINT(whitespace/braces)
+      const char* se_info_c_str = NULL;
+      ScopedUtfChars* se_info = NULL;
+      if (java_se_info != NULL) {
+          se_info = new ScopedUtfChars(env, java_se_info);
+          se_info_c_str = se_info->c_str();
+          if (se_info_c_str == NULL) {
+            ALOGE("se_info_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      const char* se_name_c_str = NULL;
+      ScopedUtfChars* se_name = NULL;
+      if (java_se_name != NULL) {
+          se_name = new ScopedUtfChars(env, java_se_name);
+          se_name_c_str = se_name->c_str();
+          if (se_name_c_str == NULL) {
+            ALOGE("se_name_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+      if (rc == -1) {
+        ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+              is_system_server, se_info_c_str, se_name_c_str);
+        RuntimeAbort(env);
+      }
+
+      // Make it easier to debug audit logs by setting the main thread's name to the
+      // nice name rather than "app_process".
+      if (se_info_c_str == NULL && is_system_server) {
+        se_name_c_str = "system_server";
+      }
+      if (se_info_c_str != NULL) {
+        SetThreadName(se_name_c_str);
+      }
+
+      delete se_info;
+      delete se_name;
+    }
+#else
+    UNUSED(is_system_server);
+    UNUSED(java_se_info);
+    UNUSED(java_se_name);
+#endif
+
+    UnsetSigChldHandler();
+
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+    if (env->ExceptionCheck()) {
+      ALOGE("Error calling post fork hooks.");
+      RuntimeAbort(env);
+    }
+  } else if (pid > 0) {
+    // the parent process
+  }
+  return pid;
+}
+}  // anonymous namespace
+
+namespace android {
+
+static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
+        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits,
+        jint mount_external, jstring se_info, jstring se_name,
+        jintArray fdsToClose) {
+    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
+            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+}
+
+static jint com_android_internal_os_Zygote_nativeForkSystemServer(
+        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
+        jlong effectiveCapabilities) {
+  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
+                                      debug_flags, rlimits,
+                                      permittedCapabilities, effectiveCapabilities,
+                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+  if (pid > 0) {
+      // The zygote process checks whether the child process has died or not.
+      ALOGI("System server process %d has been created", pid);
+      gSystemServerPid = pid;
+      // There is a slight window that the system server process has crashed
+      // but it went unnoticed because we haven't published its pid yet. So
+      // we recheck here just to make sure that all is well.
+      int status;
+      if (waitpid(pid, &status, WNOHANG) == pid) {
+          ALOGE("System server process %d has died. Restarting Zygote!", pid);
+          RuntimeAbort(env);
+      }
+  }
+  return pid;
+}
+
+static JNINativeMethod gMethods[] = {
+    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
+    { "nativeForkSystemServer", "(II[II[[IJJ)I",
+      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+};
+
+int register_com_android_internal_os_Zygote(JNIEnv* env) {
+  gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
+  if (gZygoteClass == NULL) {
+    RuntimeAbort(env);
+  }
+  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+
+  return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
+      gMethods, NELEM(gMethods));
+}
+}  // namespace android
+
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2168bd1..0f772f1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2036,6 +2036,13 @@
         android:description="@string/permdesc_bindRemoteDisplay"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a {@link android.tv.TvInputService}
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_TV_INPUT"
+        android:label="@string/permlab_bindTvInput"
+        android:description="@string/permdesc_bindTvInput"
+        android:protectionLevel="signature|system" />
+
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it. -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
@@ -2547,6 +2554,21 @@
         android:label="@string/permlab_control_keyguard"
         android:description="@string/permdesc_control_keyguard" />
 
+    <!-- Allows an application to listen to trust changes.  Only allowed for system processes.
+        @hide -->
+    <permission android:name="android.permission.TRUST_LISTENER"
+                android:protectionLevel="signature"
+                android:label="@string/permlab_trust_listener"
+                android:description="@string/permdesc_trust_listener" />
+
+    <!-- Must be required by an {@link
+         android.service.trust.TrustAgentService},
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_TRUST_AGENT_SERVICE"
+                android:protectionLevel="signature"
+                android:label="@string/permlab_bind_trust_agent_service"
+                android:description="@string/permdesc_bind_trust_agent_service" />
+
     <!-- Must be required by an {@link
          android.service.notification.NotificationListenerService},
          to ensure that only the system can bind to it. -->
@@ -2570,6 +2592,13 @@
         android:description="@string/permdesc_accessNetworkConditions"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to provision and access DRM certificates
+         @hide This is not a third-party API (intended for system apps). -->
+    <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
+        android:label="@string/permlab_accessDrmCertificates"
+        android:description="@string/permdesc_accessDrmCertificates"
+        android:protectionLevel="signature|system" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..b07da0c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 717ec1a..0000000
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e49ad54
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index 5fa4ec4..0000000
--- a/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..992a8ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..51a895d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..2f59488
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm.png b/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_alarm.png
rename to core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_alarm_mute.png
rename to core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_bt.png b/core/res/res/drawable-hdpi/ic_audio_bt_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_bt.png
rename to core/res/res/drawable-hdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_bt_mute.png b/core/res/res/drawable-hdpi/ic_audio_bt_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_bt_mute.png
rename to core/res/res/drawable-hdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_am.png b/core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_notification_am.png
rename to core/res/res/drawable-hdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_notification_mute_am.png
rename to core/res/res/drawable-hdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_phone_am.png b/core/res/res/drawable-hdpi/ic_audio_phone_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_phone_am.png
rename to core/res/res/drawable-hdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_ring_notif_am.png
rename to core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am.png
rename to core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am.png
rename to core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_am.png b/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_vol_am.png
rename to core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_audio_vol_mute_am.png
rename to core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_corp_badge.png b/core/res/res/drawable-hdpi/ic_corp_badge.png
new file mode 100644
index 0000000..f647375
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_corp_badge.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_airplane_mode.png
rename to core/res/res/drawable-hdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am.png
rename to core/res/res/drawable-hdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 0000000..ba5bd01
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
rename to core/res/res/drawable-hdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_lock.png b/core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_lock.png
rename to core/res/res/drawable-hdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_power_off.png b/core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_power_off.png
rename to core/res/res/drawable-hdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_off.png b/core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_ringer_off.png
rename to core/res/res/drawable-hdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_ringer_on.png b/core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_lock_ringer_on.png
rename to core/res/res/drawable-hdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..e0a2ba1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..d37e8ee
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..0c604d9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..2c3f4ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..991c50e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..05fb919
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_airplane_mode.png
rename to core/res/res/drawable-ldpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am.png
rename to core/res/res/drawable-ldpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_idle_alarm.png b/core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_idle_alarm.png
rename to core/res/res/drawable-ldpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_lock.png b/core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_lock.png
rename to core/res/res/drawable-ldpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_power_off.png b/core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_power_off.png
rename to core/res/res/drawable-ldpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_off.png b/core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_ringer_off.png
rename to core/res/res/drawable-ldpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_lock_ringer_on.png b/core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
similarity index 100%
rename from core/res/res/drawable-ldpi/ic_lock_ringer_on.png
rename to core/res/res/drawable-ldpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..f31730d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index c00c545..0000000
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..ebdea00
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index 2e42386..0000000
--- a/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..5903856d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..d38aed2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..87dade3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm.png b/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_alarm.png
rename to core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_alarm_mute.png
rename to core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_bt.png b/core/res/res/drawable-mdpi/ic_audio_bt_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_bt.png
rename to core/res/res/drawable-mdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_bt_mute.png b/core/res/res/drawable-mdpi/ic_audio_bt_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_bt_mute.png
rename to core/res/res/drawable-mdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_am.png b/core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_notification_am.png
rename to core/res/res/drawable-mdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_notification_mute_am.png
rename to core/res/res/drawable-mdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_phone_am.png b/core/res/res/drawable-mdpi/ic_audio_phone_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_phone_am.png
rename to core/res/res/drawable-mdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_ring_notif_am.png
rename to core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am.png
rename to core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am.png
rename to core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_am.png b/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_vol_am.png
rename to core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_audio_vol_mute_am.png
rename to core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_airplane_mode.png
rename to core/res/res/drawable-mdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am.png
rename to core/res/res/drawable-mdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 0000000..4e2612d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
rename to core/res/res/drawable-mdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_lock.png b/core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_lock.png
rename to core/res/res/drawable-mdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_power_off.png b/core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_power_off.png
rename to core/res/res/drawable-mdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_off.png b/core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_ringer_off.png
rename to core/res/res/drawable-mdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_ringer_on.png b/core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_lock_ringer_on.png
rename to core/res/res/drawable-mdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..ec43047
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..a652117
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..35d1c56
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..264188b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..06ae6659
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..a69e301
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..8337ffe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 1443b7f..0000000
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..f51af63
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index c37ba9e..0000000
--- a/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..d0d0b1e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..33ec44c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..0166d70
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_alarm.png
rename to core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_alarm_mute.png
rename to core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_bt.png b/core/res/res/drawable-xhdpi/ic_audio_bt_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_bt.png
rename to core/res/res/drawable-xhdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_bt_mute.png b/core/res/res/drawable-xhdpi/ic_audio_bt_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_bt_mute.png
rename to core/res/res/drawable-xhdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_am.png b/core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_notification_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_notification_mute_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_phone_am.png b/core/res/res/drawable-xhdpi/ic_audio_phone_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_phone_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_ring_notif_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_am.png b/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_vol_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_audio_vol_mute_am.png
rename to core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_corp_badge.png b/core/res/res/drawable-xhdpi/ic_corp_badge.png
new file mode 100644
index 0000000..80d848d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_corp_badge.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_airplane_mode.png
rename to core/res/res/drawable-xhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am.png
rename to core/res/res/drawable-xhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 0000000..e6ca1ea
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png
rename to core/res/res/drawable-xhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_lock.png b/core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_lock.png
rename to core/res/res/drawable-xhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_power_off.png b/core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_power_off.png
rename to core/res/res/drawable-xhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_off.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_ringer_off.png
rename to core/res/res/drawable-xhdpi/ic_lock_ringer_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_ringer_on.png b/core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/ic_lock_ringer_on.png
rename to core/res/res/drawable-xhdpi/ic_lock_ringer_on_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..a020d64
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..e75ffb8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..1b9fc12
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..f63d47e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..fe005d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..ea86408
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..469f736
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index e89c9fe..0000000
--- a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e8a94dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
deleted file mode 100644
index f220168..0000000
--- a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..e1c55ad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..4b49faf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..561d9ef
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_alarm.png
rename to core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_alarm_mute.png
rename to core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt.png b/core/res/res/drawable-xxhdpi/ic_audio_bt_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_bt.png
rename to core/res/res/drawable-xxhdpi/ic_audio_bt_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png b/core/res/res/drawable-xxhdpi/ic_audio_bt_mute_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_bt_mute.png
rename to core/res/res/drawable-xxhdpi/ic_audio_bt_mute_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_notification_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_notification_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_phone_am.png b/core/res/res/drawable-xxhdpi/ic_audio_phone_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_phone_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_phone_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_vol_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am.png
rename to core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_corp_badge.png b/core/res/res/drawable-xxhdpi/ic_corp_badge.png
new file mode 100644
index 0000000..885e2ac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_corp_badge.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_lock_airplane_mode.png
rename to core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png b/core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am.png
rename to core/res/res/drawable-xxhdpi/ic_lock_airplane_mode_off_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
new file mode 100644
index 0000000..d6018dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_lock_idle_alarm.png
rename to core/res/res/drawable-xxhdpi/ic_lock_idle_alarm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_lock.png b/core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_lock_lock.png
rename to core/res/res/drawable-xxhdpi/ic_lock_lock_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_power_off.png b/core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/ic_lock_power_off.png
rename to core/res/res/drawable-xxhdpi/ic_lock_power_off_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..6fad4a64
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..44d98d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..c807b50
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..d54f44a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..17c1d99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..906401e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ab_share_pack_quantum.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ab_share_pack_quantum.xml
index 495bfb6..7d33ff4d 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ab_share_pack_quantum.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ab_share_pack_qntm_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ab_solid_shadow_quantum.xml
similarity index 79%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ab_solid_shadow_quantum.xml
index 495bfb6..88e142a 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ab_solid_shadow_quantum.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_solid_shadow_qntm_alpha"
+    android:tint="@color/black" />
diff --git a/core/res/res/drawable/btn_cab_done_quantum.xml b/core/res/res/drawable/btn_cab_done_quantum.xml
new file mode 100644
index 0000000..c03ab0a
--- /dev/null
+++ b/core/res/res/drawable/btn_cab_done_quantum.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true">
+    <item android:state_pressed="true">
+        <color android:color="?attr/colorButtonPressed" />
+    </item>
+    <item android:state_focused="true" android:state_enabled="true">
+        <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+            android:tint="?attr/colorButtonPressed" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+            android:tint="?attr/colorButtonNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_audio_alarm.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_audio_alarm.xml
index 495bfb6..d3e5470 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_audio_alarm.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_audio_alarm_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_audio_alarm_mute.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_audio_alarm_mute.xml
index 495bfb6..7d85872 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_audio_alarm_mute.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_audio_alarm_mute_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_audio_bt.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_audio_bt.xml
index 495bfb6..4f5af3d 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_audio_bt.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_audio_bt_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_audio_bt_mute.xml
similarity index 93%
rename from core/res/res/drawable/ab_transparent_quantum.xml
rename to core/res/res/drawable/ic_audio_bt_mute.xml
index 495bfb6..d2004c0 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_audio_bt_mute.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_audio_bt_mute_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_notification.xml b/core/res/res/drawable/ic_audio_notification.xml
index b87e4c8..65249f5 100644
--- a/core/res/res/drawable/ic_audio_notification.xml
+++ b/core/res/res/drawable/ic_audio_notification.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_notification_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_notification_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_notification_mute.xml b/core/res/res/drawable/ic_audio_notification_mute.xml
index 1caf27c..af6a8e0 100644
--- a/core/res/res/drawable/ic_audio_notification_mute.xml
+++ b/core/res/res/drawable/ic_audio_notification_mute.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_notification_mute_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_notification_mute_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_phone.xml b/core/res/res/drawable/ic_audio_phone.xml
index e6869fd..1bab863 100644
--- a/core/res/res/drawable/ic_audio_phone.xml
+++ b/core/res/res/drawable/ic_audio_phone.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_phone_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_phone_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif.xml b/core/res/res/drawable/ic_audio_ring_notif.xml
index 2f48741..247d1b4 100644
--- a/core/res/res/drawable/ic_audio_ring_notif.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_ring_notif_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_ring_notif_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif_mute.xml b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
index 7549f6d..72aaa9d 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_mute.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_mute.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_ring_notif_mute_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_ring_notif_mute_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
index 3481e27..9e31aba 100644
--- a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
+++ b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_ring_notif_vibrate_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_ring_notif_vibrate_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_vol.xml b/core/res/res/drawable/ic_audio_vol.xml
index 6dd249b..8d07ded 100644
--- a/core/res/res/drawable/ic_audio_vol.xml
+++ b/core/res/res/drawable/ic_audio_vol.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_vol_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_vol_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_audio_vol_mute.xml b/core/res/res/drawable/ic_audio_vol_mute.xml
index b093f5924..edbdb23 100644
--- a/core/res/res/drawable/ic_audio_vol_mute.xml
+++ b/core/res/res/drawable/ic_audio_vol_mute.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_audio_vol_mute_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_audio_vol_mute_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_lock_airplane_mode.xml
similarity index 87%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_lock_airplane_mode.xml
index 495bfb6..4a16922 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_lock_airplane_mode.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+    android:src="@drawable/ic_lock_airplane_mode_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/ic_lock_airplane_mode_off.xml b/core/res/res/drawable/ic_lock_airplane_mode_off.xml
index b344e28..a8cd390 100644
--- a/core/res/res/drawable/ic_lock_airplane_mode_off.xml
+++ b/core/res/res/drawable/ic_lock_airplane_mode_off.xml
@@ -18,6 +18,6 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/ic_lock_airplane_mode_off_am"
-        android:autoMirrored="true">
-</bitmap>
+    android:src="@drawable/ic_lock_airplane_mode_off_am_alpha"
+    android:autoMirrored="true"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_lock_bugreport.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_lock_bugreport.xml
index 495bfb6..a3f82ce 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_lock_bugreport.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_lock_bugreport_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_lock_idle_alarm.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_lock_idle_alarm.xml
index 495bfb6..e8189bd 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_lock_idle_alarm.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_lock_idle_alarm_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_lock_lock.xml
similarity index 87%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_lock_lock.xml
index 495bfb6..39f268a 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_lock_lock.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+    android:src="@drawable/ic_lock_lock_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ic_lock_power_off.xml
similarity index 93%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ic_lock_power_off.xml
index 495bfb6..718f17e 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ic_lock_power_off.xml
@@ -15,5 +15,5 @@
 -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:src="@drawable/ic_lock_power_off_alpha"
     android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_media_route_connecting_quantum.xml b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
new file mode 100644
index 0000000..0029dd4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="false">
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_0_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_2_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:duration="500">
+        <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</animation-list>
diff --git a/core/res/res/drawable/ic_media_route_quantum.xml b/core/res/res/drawable/ic_media_route_quantum.xml
new file mode 100644
index 0000000..16b63d4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true"
+        android:drawable="@android:drawable/ic_media_route_connecting_quantum" />
+    <item android:state_activated="true" android:state_enabled="true">
+        <bitmap android:src="@android:drawable/ic_media_route_on_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_enabled="true">
+        <bitmap android:src="@android:drawable/ic_media_route_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item>
+        <bitmap android:src="@android:drawable/ic_media_route_disabled_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/item_background_quantum.xml b/core/res/res/drawable/item_background_quantum.xml
index f668ca0..11e1f67 100644
--- a/core/res/res/drawable/item_background_quantum.xml
+++ b/core/res/res/drawable/item_background_quantum.xml
@@ -15,4 +15,5 @@
 -->
 
 <touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorButtonPressed" />
+    android:tint="?attr/colorButtonPressed"
+    android:pinned="true" />
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
similarity index 62%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ratingbar_full_empty_quantum.xml
index 495bfb6..e5e4315 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
@@ -14,6 +14,13 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
similarity index 62%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ratingbar_full_filled_quantum.xml
index 495bfb6..ad3aa5d 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
@@ -14,6 +14,13 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/core/res/res/drawable/ratingbar_full_quantum.xml
similarity index 61%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to core/res/res/drawable/ratingbar_full_quantum.xml
index 495bfb6..143e7c2 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/core/res/res/drawable/ratingbar_full_quantum.xml
@@ -14,6 +14,11 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background"
+        android:drawable="@drawable/ratingbar_full_empty_quantum" />
+    <item android:id="@id/secondaryProgress"
+        android:drawable="@drawable/ratingbar_full_empty_quantum" />
+    <item android:id="@id/progress" 
+        android:drawable="@drawable/ratingbar_full_filled_quantum" />
+</layer-list>
diff --git a/core/res/res/layout/alert_dialog_progress_quantum.xml b/core/res/res/layout/alert_dialog_progress_quantum.xml
new file mode 100644
index 0000000..b9d0814
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_progress_quantum.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent">
+    <ProgressBar android:id="@+id/progress"
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="1dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_centerHorizontal="true" />
+    <TextView
+        android:id="@+id/progress_percent"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingBottom="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/progress" />
+    <TextView
+        android:id="@+id/progress_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingBottom="16dip"
+        android:layout_marginStart="16dip"
+        android:layout_marginEnd="16dip"
+        android:layout_alignParentEnd="true"
+        android:layout_below="@id/progress" />
+</RelativeLayout>
diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml
new file mode 100644
index 0000000..98b68797
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_quantum.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout android:id="@+id/topPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <LinearLayout android:id="@+id/title_template"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical|start"
+            android:paddingStart="16dip"
+            android:paddingEnd="16dip"
+            android:paddingTop="16dip">
+            <ImageView android:id="@+id/icon"
+                android:layout_width="32dip"
+                android:layout_height="32dip"
+                android:layout_marginEnd="8dip"
+                android:scaleType="fitCenter"
+                android:src="@null" />
+            <TextView android:id="@+id/alertTitle"
+                style="?android:attr/windowTitleStyle"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textAlignment="viewStart" />
+        </LinearLayout>
+        <!-- If the client uses a customTitle, it will be added here. -->
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/contentPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:minHeight="64dp">
+        <ScrollView android:id="@+id/scrollView"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:clipToPadding="false">
+            <TextView android:id="@+id/message"
+                style="?android:attr/textAppearanceMedium"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingStart="16dip"
+                android:paddingEnd="16dip"
+                android:paddingTop="16dip" />
+        </ScrollView>
+    </LinearLayout>
+
+    <FrameLayout android:id="@+id/customPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:minHeight="64dp">
+        <FrameLayout android:id="@+android:id/custom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </FrameLayout>
+
+    <LinearLayout android:id="@+id/buttonPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/alert_dialog_button_bar_height"
+        android:orientation="vertical"
+        android:padding="16dip">
+        <LinearLayout
+            style="?android:attr/buttonBarStyle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layoutDirection="locale"
+            android:measureWithLargestChild="true">
+            <Button android:id="@+id/button3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="start"
+                android:layout_marginRight="8dip"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle" />
+            <Button android:id="@+id/button2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginRight="8dip"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle" />
+            <Button android:id="@+id/button1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle" />
+        </LinearLayout>
+     </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_custom_title_quantum.xml b/core/res/res/layout/dialog_custom_title_quantum.xml
new file mode 100644
index 0000000..1bb93eb
--- /dev/null
+++ b/core/res/res/layout/dialog_custom_title_quantum.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is a custom layout for a dialog.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+    <FrameLayout android:id="@android:id/title_container"
+        android:layout_width="match_parent"
+        android:layout_weight="0"
+        android:gravity="center_vertical|start"
+        style="?android:attr/windowTitleBackgroundStyle" />
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_icons_quantum.xml b/core/res/res/layout/dialog_title_icons_quantum.xml
new file mode 100644
index 0000000..28e20d9
--- /dev/null
+++ b/core/res/res/layout/dialog_title_icons_quantum.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+
+    <LinearLayout android:id="@+id/title_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
+        android:paddingTop="16dip">
+        <ImageView android:id="@+id/left_icon"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:scaleType="fitCenter"
+            android:layout_marginEnd="8dip" />
+        <TextView android:id="@android:id/title"
+            style="?android:attr/windowTitleStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="0" />
+        <ImageView android:id="@+id/right_icon"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:scaleType="fitCenter"
+            android:layout_marginStart="8dip" />
+    </LinearLayout>
+
+    <FrameLayout
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_quantum.xml b/core/res/res/layout/dialog_title_quantum.xml
new file mode 100644
index 0000000..b92c1e7
--- /dev/null
+++ b/core/res/res/layout/dialog_title_quantum.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+    <TextView android:id="@+id/alertTitle"
+        style="?android:attr/windowTitleStyle"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAlignment="viewStart"
+        android:paddingStart="16dip"
+        android:paddingEnd="16dip"
+        android:paddingTop="16dip" />
+    <FrameLayout
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/preference_holo.xml b/core/res/res/layout/preference_holo.xml
index 1cc803b..1b3ab86 100644
--- a/core/res/res/layout/preference_holo.xml
+++ b/core/res/res/layout/preference_holo.xml
@@ -23,7 +23,8 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:gravity="center_vertical"
     android:paddingStart="@dimen/preference_item_padding_side"
-    android:paddingEnd="?android:attr/scrollbarSize">
+    android:paddingEnd="?android:attr/scrollbarSize"
+    android:background="?android:attr/activatedBackgroundIndicator">
 
     <LinearLayout
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/progress_dialog_quantum.xml b/core/res/res/layout/progress_dialog_quantum.xml
new file mode 100644
index 0000000..84d06b5
--- /dev/null
+++ b/core/res/res/layout/progress_dialog_quantum.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout android:id="@+id/body"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:baselineAligned="false"
+        android:padding="16dip">
+
+        <ProgressBar android:id="@android:id/progress"
+            style="?android:attr/progressBarStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:max="10000"
+            android:layout_marginEnd="16dip" />
+
+        <TextView android:id="@+id/message"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical" />
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 3265736..77f537b 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -33,25 +33,25 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
-        style="?android:attr/actionBarStyle"
+        style="?attr/actionBarStyle"
         android:sharedElementName="android:action_bar"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            style="?android:attr/actionBarStyle" />
+            style="?attr/actionBarStyle" />
         <com.android.internal.widget.ActionBarContextView
             android:id="@+id/action_context_bar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:visibility="gone"
-            style="?android:attr/actionModeStyle" />
+            style="?attr/actionModeStyle" />
     </com.android.internal.widget.ActionBarContainer>
     <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
-                  style="?android:attr/actionBarSplitStyle"
+                  style="?attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
 </com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/layout/select_dialog_item_quantum.xml b/core/res/res/layout/select_dialog_item_quantum.xml
new file mode 100644
index 0000000..59b432e
--- /dev/null
+++ b/core/res/res/layout/select_dialog_item_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+    This layout file is used by the AlertDialog when displaying a list of items.
+    This layout file is inflated and used as the TextView to display individual
+    items.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_multichoice_quantum.xml b/core/res/res/layout/select_dialog_multichoice_quantum.xml
new file mode 100644
index 0000000..8b4c59d
--- /dev/null
+++ b/core/res/res/layout/select_dialog_multichoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_quantum.xml b/core/res/res/layout/select_dialog_quantum.xml
new file mode 100644
index 0000000..ee04039
--- /dev/null
+++ b/core/res/res/layout/select_dialog_quantum.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+    This layout file is used by the AlertDialog when displaying a list of items.
+    This layout file is inflated and used as the ListView to display the items.
+    Assign an ID so its state will be saved/restored.
+-->
+<view class="com.android.internal.app.AlertController$RecycleListView"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+android:id/select_dialog_listview"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:cacheColorHint="@null"
+    android:divider="?android:attr/listDividerAlertDialog"
+    android:scrollbars="vertical"
+    android:overScrollMode="ifContentScrolls"
+    android:textAlignment="viewStart" />
diff --git a/core/res/res/layout/select_dialog_singlechoice_quantum.xml b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
new file mode 100644
index 0000000..27a6648
--- /dev/null
+++ b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textColor="?android:attr/textColorAlertDialogListItem"
+    android:gravity="center_vertical"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:checkMark="?android:attr/listChoiceIndicatorSingle"
+    android:ellipsize="marquee" />
diff --git a/core/res/res/layout/tab_indicator_quantum.xml b/core/res/res/layout/tab_indicator_quantum.xml
new file mode 100644
index 0000000..fcb2d5f
--- /dev/null
+++ b/core/res/res/layout/tab_indicator_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="?android:attr/actionBarSize"
+    android:orientation="horizontal"
+    style="@android:style/Widget.Quantum.Tab">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        style="@android:style/Widget.Quantum.TabText" />
+
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index f8d7fcc..b9bdfb9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Laat \'n program luister vir waarnemings oor netwerktoestande. Behoort nooit nodig te wees vir normale programme nie."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"verander invoertoestelkalibrasie"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Laat die program toe om die kalibrasieparameters van die raakskerm te wysig. Dit behoort nooit vir normale programme nodig te wees nie."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"gaan in by DRM-sertifikate"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Laat \'n program toe om DRM-sertifikate op te stel en te gebruik. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Laat \'n program toe om toegang tot keyguard se veilige berging te kry."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Beheer wys en versteek van keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Laat \'n program toe om keyguard te beheer."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Luister na vertrouenstaatveranderinge."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Laat \'n program toe om vir veranderinge in vertrouenstaat te luister."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Verbind met \'n vertrouensagentdiens"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Laat \'n program toe om met \'n vertrouensagentdiens te verbind."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tree in wisselwerking met opdatering- en terugstellingstelsel"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Laat \'n program met die terugstellingstelsel en stelselopdaterings in wisselwerking tree."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Raak twee keer vir zoembeheer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0d8c1f1..22246c1 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -270,13 +270,13 @@
     <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"የበመልዕክት-በኩል-ምላሽ-ስጥ ክስተቶችን ይላኩ"</string>
     <string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"መተግበሪያው ሌሎች የመልዕክት መላኪያ መተግበሪያዎች ለመጪ ጥሪዎች በመልዕክት-በኩል-ምላሽ-መስጠት ስራን እንዲይዙ ጥያቄዎች እንዲልክላቸው ያስችለዋል።"</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"የጽሑፍ መልዕክቶችዎን ያንብቡ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"መገለጫው በጡባዊ ቱኮህ ወይም በSIM ካርድህ የተከማቹ የኤስ.ኤም.ኤስ. መልእክቶችን እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው ይዘት ወይም ሚስጥራዊነትን ከግምት ሳያስገባ ሁሉንም የኤስ.ኤም.ኤስ. መልእክቶች እንዲያነብ ይፈቅድለታል።"</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"መገለጫው በጡባዊ ተኮዎ ወይም በSIM ካርድዎ የተከማቹ የኤስኤምኤስ. መልዕክቶችን እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው ይዘት ወይም ሚስጥራዊነትን ከግምት ሳያስገባ ሁሉንም የኤስኤምኤስ መልዕክቶች እንዲያነብ ይፈቅድለታል።"</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"መገለጫው በስልክዎ ወይም በSIM ካርድዎ የተከማቹ የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው ይዘት ወይም ሚስጥራዊነትን ከግምት ሳያስገባ ሁሉንም የኤስ.ኤም.ኤስ. መልዕክቶች እንዲያነብ ይፈቅድለታል።"</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"የጽሑፍ መልዕክቶችህን አርትዕ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"በጡባዊ ተኮህ ወይም ሲም ካርድህ ላይ ኤስ ኤም ኤስ መልዕክቶችን ለመፃፍ ለመተግበሪያው ይፈቅዳሉ፡፡መልዕክቶችህን ተንኮል አዘል መተግበሪያዎች ሊሰርዙ ይችላሉ፡፡"</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"በስልክዎ ወይም ሲም ካርድዎ ላይ ኤስ ኤም ኤስ መልዕክቶችን ለመፃፍ ለመተግበሪያው ይፈቅዳሉ። መልዕክቶችዎን ተንኮል አዘል መተግበሪያዎች ሊሰርዙ ይችላሉ።"</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"የፅሁፍ መልዕክቶችን ተቀበል (WAP)"</string>
-    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"መተግበሪያው የWAP መልእክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልህን መልእክቶች ላንተ ሳያሳይህ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።"</string>
+    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"መተግበሪያው የWAP መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልዎን መልዕክቶች ለእርስዎ ሳያሳይዎ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"አሂድ መተግበሪያዎችን ሰርስረው ያውጡ"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"መተግበሪያው በአሁኑ ጊዜና በቅርቡ እየተካሄዱ ስላሉ ተግባሮችን መረጃ ሰርስሮ እንዲያወጣ ይፈቅድለታል። ይህ መተግበሪያው በመሳሪያው ላይ የትኛዎቹ መተግበሪያዎች ጥቅም ላይ ስለመዋላቸው መረጃ እንዲያገኝ ሊፈቅድለት ይችላል።"</string>
     <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር መፍጠር"</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"አንድ መተግበሪያ በአውታረ መረብ ሁኔታዎች ላይ የተስተዋሉ ነገሮችን እንዲያዳምጥ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አስፈላጊ ሊሆን አይገባም።"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"የግቤት መሣሪያ ማስተካከያ ቀይር"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"መተግበሪያው የማያ ንካ የማስተካከያ ልኬቶቹን እንዲቀይር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"የDRM የምስክር ወረቀቶች ላይ ይድረሱ"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -988,7 +990,7 @@
     <string name="search_go" msgid="8298016669822141719">"ፍለጋ"</string>
     <string name="searchview_description_search" msgid="6749826639098512120">"ፍለጋ"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"ጥያቄ ፍለጋ"</string>
-    <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጥራ"</string>
+    <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጽዳ"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"አንድ መተግበሪያ ደህንነቱ በቁልፍ የተጠበቀ ማከማቻ እንዲደርስ ያስችለዋል።"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"የቁልፍ መጠበቂያውን ማሳየት እና መደበቅ ይቆጣጠሩ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"አንድ መተግበሪያ የቁልፍ መጠበቂያውን እንዲቆጣጠር ያስችለዋል።"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"የተአማኒነት ሁኔታ ለውጦችን አዳምጥ።"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"መተግበሪያው በተአማኒነት ሁኔታ ውስጥ ለውጦችን እንዲያዳምጥ ይፈቅዳል።"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ለተአማኒነት ወኪል አገልግሎት ተገዢ አድርግ"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ለመተግበሪያን የተአማኒነት ወኪል አገልግሎትን እንዲያከብር ይፈቅዳል።"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"ከዝማኔዎች እና ከመልሶ ማግኛ ስርዓቶች ጋር ይገናኙ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"መተግበሪያው ከመልሶ ማግኛ ስርዓት እና ከስርዓት ማዘመኛዎች ጋር እንዲገናኝ ይፈቅድለታል።"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index c808135..9efd8eb 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"للسماح للتطبيق بالاستماع إلى ملاحظات حول أحوال الشبكة. لا حاجة إلى هذا مع التطبيقات العادية."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"تغيير معايرة أجهزة الإدخال"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"يتيح للتطبيق إمكانية تعديل معلمات المعايرة في شاشة اللمس. يجب عدم اللجوء إليه مع التطبيقات العادية."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"‏الدخول إلى شهادات DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"‏للسماح لأحد التطبيقات بتقديم شهادات DRM واستخدامها. لا يجب أن يكون ذلك لازمًا مطلقًا مع التطبيقات العادية."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"يمكنك التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء تأمين الشاشة."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"السماح لأحد التطبيقات بالدخول إلى التخزين المحمي بقفل المفاتيح."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"التحكم في عرض وإخفاء قفل المفاتيح"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"للسماح لأحد التطبيقات بالتحكم في قفل المفاتيح."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"معرفة تغييرات حالة الاعتماد."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"للسماح للتطبيق بالتعرف على التغييرات في حالة الاعتماد."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"الالتزام بخدمة الوكيل المعتمد"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"للسماح لأحد التطبيقات بالالتزام بخدمة الوكيل المعتمد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"التفاعل مع نظام التحديث والاسترداد"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"للسماح للتطبيق بالتفاعل مع نظام الاسترداد وتحديثات النظام."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"المس مرتين للتحكم في التكبير/التصغير"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 015bf10..366de7c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Разрешава на приложението да слуша за наблюдения на мрежовите условия. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"промяна на калибрирането на устройството за въвеждане"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Разрешава на приложението да променя параметрите на калибриране на сензорния екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"достъп до сертификатите за управление на цифровите права (DRM)"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Разрешава на приложението да обезпечава и използва сертификатите за управление на цифровите права (DRM). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Позволява на приложението да осъществява достъп до надеждното хранилище, свързано с функцията за защита на клавишите."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Контролиране на показването и скриването на функцията за защита на клавишите"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Разрешава на приложението да контролира функцията за защита на клавишите."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Следене за промени в състоянието на надеждност"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Разрешава на приложението да следи за промени в състоянието на надеждност."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Обвързване с услуга за trust agents"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Разрешава на приложението да се обвърже с услуга за trust agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействие със системата за актуализации и възстановяване"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Разрешава на приложението да взаимодейства със системата за възстановяване и системните актуализации."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Докоснете двукратно за управление на промяната на мащаба"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 94f4b4f..6cba689 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -430,19 +430,19 @@
     <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Permet que una aplicació concedeixi o denegui permisos específics per a aquesta o per a altres aplicacions. És possible que les aplicacions malicioses ho facin servir per accedir a funcions a les quals no has concedit accés."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"defineix les aplicacions preferides"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Permet que l\'aplicació modifiqui les aplicacions preferides. Les aplicacions malicioses poden canviar silenciosament les aplicacions que s\'executen, falsejar les aplicacions existents o recollir dades privades de l\'usuari."</string>
-    <string name="permlab_writeSettings" msgid="2226195290955224730">"modificació de la configuració del sistema"</string>
+    <string name="permlab_writeSettings" msgid="2226195290955224730">"modificar la configuració del sistema"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Permet que l\'aplicació modifiqui les dades de configuració del sistema. Les aplicacions malicioses poden malmetre la configuració del sistema."</string>
     <string name="permlab_writeSecureSettings" msgid="204676251876718288">"modificar la configuració de seguretat del sistema"</string>
     <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"Permet que l\'aplicació modifiqui les dades de la configuració de seguretat del sistema. No indicat per a les aplicacions normals."</string>
     <string name="permlab_writeGservices" msgid="2149426664226152185">"modificar el mapa de serveis de Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"Permet que l\'aplicació modifiqui el mapa dels serveis de Google. No la poden fer servir les aplicacions normals."</string>
-    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"execució en iniciar"</string>
+    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"executar-se a l\'inici"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Permet que l\'aplicació s\'iniciï tan bon punt el sistema hagi acabat d\'arrencar. Això pot fer que es trigui més a iniciar el telèfon i permetre a l\'aplicació alentir-ne el funcionament general en executar-se sempre."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Permet que l\'aplicació s\'iniciï tan bon punt el sistema hagi acabat d\'arrencar. Això pot fer que es trigui més a iniciar el telèfon i permetre a l\'aplicació alentir-ne el funcionament general si s\'executa sempre."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar difusió permanent"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Permet que l\'aplicació enviï emissions permanents, que es conserven després de finalitzar l\'emissió. L\'ús excessiu pot alentir o desestabilitzar la tauleta si li fan utilitzar massa memòria."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permet que l\'aplicació enviï emissions permanents, que es conserven després de finalitzar l\'emissió. L\'ús excessiu pot alentir o desestabilitzar el telèfon si li fan utilitzar massa memòria."</string>
-    <string name="permlab_readContacts" msgid="8348481131899886131">"lectura dels contactes"</string>
+    <string name="permlab_readContacts" msgid="8348481131899886131">"consultar els contactes"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permet que l\'aplicació llegeixi dades sobre els contactes que tinguis emmagatzemats a la tauleta, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb persones concretes. Aquest permís permet que les aplicacions desin les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permet que l\'aplicació llegeixi dades sobre els contactes que tinguis emmagatzemats al telèfon, inclosa la freqüència amb què has trucat, has enviat correus electrònics o t\'has comunicat d\'altres maneres amb persones concretes. Aquest permís permet que les aplicacions desin les dades dels teus contactes, i és possible que les aplicacions malicioses comparteixin dades dels contactes sense el teu coneixement."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modificar els teus contactes"</string>
@@ -504,7 +504,7 @@
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"Permet que l\'aplicació enregistri àudio amb el micròfon. Aquest permís permet que l\'aplicació enregistri àudio en qualsevol moment sense la teva confirmació."</string>
     <string name="permlab_sim_communication" msgid="1180265879464893029">"comunicació SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permet que l\'aplicació enviï ordres a la SIM. Això és molt perillós."</string>
-    <string name="permlab_camera" msgid="3616391919559751192">"fes fotos i vídeos"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fer fotos i vídeos"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"Permet que l\'aplicació faci fotos i vídeos amb la càmera. Aquest permís permet que l\'aplicació utilitzi la càmera en qualsevol moment sense la teva confirmació."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"desactiva la transmissió del LED indicador en fer servir la càmera"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permet que una aplicació dels sistema preinstal·lada desactivi el LED indicador d\'ús de la càmera."</string>
@@ -594,7 +594,7 @@
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permet que l\'aplicació obtingui la llista de comptes coneguts pel telèfon. Això pot incloure tots els comptes que hagin creat les aplicacions que tens instal·lades."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"creació de comptes i definició de contrasenyes"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Permet que l\'aplicació utilitzi les funcions d\'autenticador de comptes del gestor de comptes, incloses la creació de comptes i l\'obtenció i la definició de les seves contrasenyes."</string>
-    <string name="permlab_manageAccounts" msgid="4983126304757177305">"addició o eliminació de comptes"</string>
+    <string name="permlab_manageAccounts" msgid="4983126304757177305">"afegir o eliminar comptes"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Permet que l\'aplicació dugui a terme operacions com ara afegir i eliminar comptes i suprimir-ne la contrasenya."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"fer servir comptes del dispositiu"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Permet que l\'aplicació sol·liciti testimonis d\'autenticació."</string>
@@ -631,13 +631,13 @@
     <string name="permlab_bluetooth" msgid="6127769336339276828">"emparella amb dispositius Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet que l\'aplicació visualitzi la configuració de Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet que una aplicació visualitzi la configuració de Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"controla Near Field Communication (NFC)"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicació de camp proper (NFC)"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permet que l\'aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivació del bloqueig de pantalla"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permet que l\'aplicació desactivi el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Per exemple, el telèfon desactiva el bloqueig del teclat en rebre una trucada telefònica entrant i, a continuació, reactiva el bloqueig del teclat quan finalitza la trucada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Persones estigui sincronitzada amb un compte."</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activació o desactivació de la sincronització"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar o desactivar la sincronització"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Permet que una aplicació modifiqui la configuració de sincronització d\'un compte. Per exemple, aquesta acció es pot fer servir per activar la sincronització de l\'aplicació Persones amb un compte."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"llegir les estadístiques de sincronització"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Permet que una aplicació llegeixi les estadístiques de sincronització d\'un compte, inclòs l\'historial d\'esdeveniments sincronitzats i quantes dades se sincronitzen."</string>
@@ -649,7 +649,7 @@
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Permet que l\'aplicació llegeixi les paraules, els noms i les frases que l\'usuari pot haver emmagatzemat al seu diccionari."</string>
     <string name="permlab_writeDictionary" msgid="2183110402314441106">"afegeix paraules al diccionari definit per l\'usuari"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Permet que l\'aplicació escrigui paraules noves al diccionari de l\'usuari."</string>
-    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"lectura contingut emmagat. USB"</string>
+    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"consultar contingut emmagatzematge USB"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"lectura del contingut de la targeta SD"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Permet que l\'aplicació llegeixi el contingut de l\'emmagatzematge USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Permet que l\'aplicació llegeixi el contingut de la targeta SD."</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet que una aplicació conegui les observacions sobre les condicions de la xarxa. No s\'ha de necessitar mai per a aplicacions normals."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"canviar el calibratge del dispositiu d\'entrada"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet que l\'aplicació modifiqui els paràmetres de calibratge de la pantalla tàctil. No ha de ser mai necessari per a aplicacions normals."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accés als certificats de DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar intents de desbloqueig de pantalla"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet que una aplicació accedeixi a l\'emmagatzematge protegit per contrasenya."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controla si es mostra o s\'amaga el bloqueig de les tecles."</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet que una aplicació controli el bloqueig de les tecles."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Escoltar els canvis de l\'estat de confiança"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet que una aplicació escolti els canvis en l\'estat de confiança."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Enllaçar amb el servei d\'un agent de confiança"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet que una aplicació es vinculi amb el servei d\'un agent de confiança."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interacciona amb el sistema de recuperació i amb les actualitzacions"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet que una aplicació interaccioni amb el sistema de recuperació i amb les actualitzacions del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos cops per controlar el zoom"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b3f482a..b4972ef 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikaci naslouchat informacím o stavu sítě. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"měnit kalibraci vstupního zařízení"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Umožňuje aplikaci měnit parametry kalibrace dotykové obrazovky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"přístup k certifikátům DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Umožňuje aplikaci vydávat a používat certifikáty DRM. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemčení obrazovky a povolené znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Umožňuje aplikaci přístup k bezpečnému úložišti keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Ovládání zobrazování a skrývání zámku obrazovky"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umožňuje aplikaci ovládat zámek obrazovky."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Naslouchat změnám stavu důvěryhodnosti"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Umožňuje aplikaci naslouchat změnám ve stavu důvěryhodnosti."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vázat se na službu zástupce důvěryhodnosti"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikaci vázat se na službu zástupce důvěryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakce se systémem aktualizací a obnovení"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikaci interakci se systémem obnovení a s aktualizacemi systému."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dvojitým dotykem můžete ovládat přiblížení"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a8cf79c..d3469f1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"skift kalibrering for inputenheden"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"få adgang til DRM-certifikater"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillader, at en applikation leverer og anvender DRM-certfikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Tillader, at en applikation får adgang til et nøglebeskyttet lager."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Administrer, om nøglebeskyttelse skal vises eller skjules"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillader, at en applikation styrer nøglebeskyttelsen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Registrere ændringer i trust-tilstand."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Tillader, at en applikation registrerer ændringer i trust-tilstand."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Knytte sig til en trust agent-tjeneste"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillader, at en applikation knytter sig til en trust agent-tjeneste."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interager med opdaterings- og gendannelsessystemet"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Giver en applikation tilladelse til at interagere med gendannelsessystemet og systemopdateringerne."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tryk to gange for zoomstyring"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index a59378f..52ea81c 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -145,7 +145,7 @@
     <string name="silent_mode" msgid="7167703389802618663">"Lautlos-Modus"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Funk einschalten"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"Funk ausschalten"</string>
-    <string name="screen_lock" msgid="799094655496098153">"Display-Sperre"</string>
+    <string name="screen_lock" msgid="799094655496098153">"Displaysperre"</string>
     <string name="power_off" msgid="4266614107412865048">"Ausschalten"</string>
     <string name="silent_mode_silent" msgid="319298163018473078">"Klingelton aus"</string>
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"Klingeltonmodus \"Vibration\""</string>
@@ -160,7 +160,7 @@
     <string name="no_recent_tasks" msgid="8794906658732193473">"Keine kürzlich geöffneten Apps"</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tablet-Optionen"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoptionen"</string>
-    <string name="global_action_lock" msgid="2844945191792119712">"Display-Sperre"</string>
+    <string name="global_action_lock" msgid="2844945191792119712">"Displaysperre"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
@@ -633,7 +633,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
-    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Display-Sperre deaktivieren"</string>
+    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Displaysperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Ermöglicht der App, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. Das Telefon deaktiviert die Tastensperre beispielsweise, wenn ein Anruf eingeht, und aktiviert sie wieder, nachdem das Gespräch beendet wurde."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ermöglicht der App, Informationen zu den Netzwerkbedingungen zu erfassen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"Kalibrierung für Eingabegerät ändern"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ermöglicht der App, die Kalibrierungsparameter des Touchscreens zu ändern. Für normale Apps sollte dies nie erforderlich sein."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Auf DRM-Zertifikate zugreifen"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ermöglicht einer App die Bereitstellung und Nutzung von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ermöglicht einer App den Zugriff auf mit Keyguard geschützten Speicher"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Anzeige und Ausblenden des Keyguard steuern"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Apps können den Keyguard steuern."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Überwachung von Änderungen des Trust-Status"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ermöglicht einer App die Überwachungen von Änderungen des Trust-Status"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"An Trust Agent-Service anbinden"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ermöglicht einer App die Anbindung an einen Trust Agent-Service"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Mit Update- und Wiederherstellungssystem interagieren"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ermöglicht einer App die Interaktion mit dem Wiederherstellungssystem und den Systemupdates"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Für Zoomeinstellung zweimal berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index ddee3106..8b7e618 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Επιτρέπει σε μια εφαρμογή να λαμβάνει παρατηρήσεις σχετικά με την κατάσταση δικτύου. Δεν θα πρέπει να απαιτείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"αλλαγή βαθμονόμησης της συσκευής εισόδου"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Επιτρέπει στην εφαρμογή να τροποποιεί τις παραμέτρους βαθμονόμησης της οθόνης αφής. Δεν απαιτείται για τις κανονικές εφαρμογές."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"πρόσβαση σε πιστοποιητικά DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Επιτρέπει σε μια εφαρμογή να παρέχει και να χρησιμοποιεί πιστοποιητικά DRM. Δεν θα χρειαστεί ποτέ για κανονικές εφαρμογές."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Επιτρέπει σε μια εφαρμογή να αποκτήσει πρόσβαση στον ασφαλή αποθηκευτικό χώρο με κλείδωμα."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Έλεγχος εμφάνισης και απόκρυψης κλειδώματος πληκτρολογίου"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Επιτρέπει σε μια εφαρμογή τον έλεγχο του κλειδώματος πληκτρολογίου."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Αντίληψη αλλαγών καταστάσεων εμπιστοσύνης."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Επιτρέπει σε μια εφαρμογή να αντιλαμβάνεται τις αλλαγές στην κατάσταση εμπιστοσύνης."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Σύνδεση σε υπηρεσία trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Επιτρέπει σε μια εφαρμογή να συνδεθεί σε μια υπηρεσία trust agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Αλληλεπίδραση με το σύστημα ενημέρωσης και ανάκτησης"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Επιτρέπει σε μια εφαρμογή να αλληλεπιδρά με το σύστημα ανάκτησης και ενημερώσεων συστήματος."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Αγγίξτε δύο φορές για έλεγχο εστίασης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 1c815be..179691b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"change input device calibration"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access DRM certificates"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Allows an application to provision and use DRM certficates. Should never be needed for normal apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Allows an application to access keyguard secure storage."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Control displaying and hiding keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Allows an application to control keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Listen to trust state changes."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Allows an application to listen for changes in trust state."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind to a trust agent service"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Allows an application to bind to a trust agent service."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interact with update and recovery system"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Allows an application to interact with the recovery system and system updates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Touch twice for zoom control"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 1c815be..179691b 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"change input device calibration"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access DRM certificates"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Allows an application to provision and use DRM certficates. Should never be needed for normal apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Allows an application to access keyguard secure storage."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Control displaying and hiding keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Allows an application to control keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Listen to trust state changes."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Allows an application to listen for changes in trust state."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind to a trust agent service"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Allows an application to bind to a trust agent service."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interact with update and recovery system"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Allows an application to interact with the recovery system and system updates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Touch twice for zoom control"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 16790eb..dc67e27 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"cambiar la calibración del dispositivo de entrada"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Acceder a certificados DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que una aplicación acceda al almacenamiento seguro de bloqueos."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar cuándo se muestra y se oculta el bloqueo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que una aplicación controle los bloqueos."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectar cambios en estado de confianza"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que una aplicación detecte cambios en el estado de confianza."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vincular con un servicio de agente de confianza"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que una aplicación se vincule con un servicio de agente de confianza."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interaccionar con el sistema de recuperación y las actualizaciones"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que una aplicación interaccione con el sistema de recuperación y las actualizaciones del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos veces para acceder al control de zoom."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d5d9222..8386b02 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. No debe ser necesario para aplicaciones normales."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"cambiar la calibración del dispositivo de entrada"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. No debe ser necesario para las aplicaciones normales."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"acceder a certificados DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que una aplicación acceda al almacenamiento seguro de bloqueos."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar cuándo se muestra y se oculta el bloqueo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que una aplicación controle los bloqueos."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectar cambios en el estado de confianza."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que una aplicación detecte cambios en el estado de confianza."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Enlazar con un servicio de agente de confianza"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite a una aplicación enlazar con un servicio de agente de confianza."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interactuar con el sistema de recuperación y las actualizaciones"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que una aplicación interactúe con el sistema de recuperación y las actualizaciones del sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toca dos veces para acceder al control de zoom."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 12a5ab7..4d15e4a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Lubab rakendusel kuulata võrgutingimuste teavet. Ei ole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"sisendseadme kalibreerimise muutmine"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lubab rakendusel muuta puuteekraani kalibreerimisparameetreid. Ei tohiks kunagi olla vajalik tavaliste rakenduste puhul."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"juurdepääs DRM-i sertifikaatidele"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Lubab rakendusel ette valmistada ja kasutada DRM-i sertifikaate. Tavarakenduste puhul ei tohiks see vajalik olla."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lubab rakendusel hankida juurdepääsu võtmekaitsega turvalisele talletusruumile."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Võtmekaitse kuvamise ja peitmise juhtimine"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Lubab rakendusel võtmekaitset juhtida."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Usaldusväärse oleku muudatuste tuvastamine."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Lubab rakendusel tuvastada muudatusi usaldusväärses olekus."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Usaldusväärse agendi teenusega sidumine"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Lubab rakendusel ennast siduda usaldusväärse agendi teenusega."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Suhtlemine värskenduse ja taastesüsteemiga"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Lubab rakendusel suhelda taastesüsteemi ja süsteemivärskendustega."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Suumi juhtimiseks puudutage kaks korda"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5cc9697..b621d49 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"به برنامه امکان می‌دهد برای بررسی شرایط شبکه گوش دهد. این امکان هرگز نباید برای برنامه‌های معمولی مورد نیاز باشد."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"تغییر کالیبراسیون دستگاه ورودی"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"به برنامه امکان می‌دهد پارامترهای کالیبراسیون صفحه لمسی را تغییر دهد. هرگز نباید برای برنامه‌های عادی مورد نیاز باشد."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"‏دسترسی به گواهی‌های DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"‏به یک برنامه کاربردی اجازه ارائه مجوز و استفاده از گواهی‌های DRM را می‌دهد. هرگز برای برنامه‌های عادی مورد نیاز نیست."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"‏طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"به یک برنامه کاربردی برای دسترسی به فضای ذخیره‌سازی ایمن محافظ کلید اجازه می‌دهد."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"کنترل نمایش و پنهان کردن محافظ کلید"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"اجازه می‌دهد برنامه‌ای محافظ کلید را کنترل کند."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"‏گوش دادن به تغییرات وضعیت trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"‏به یک برنامه کاربردی برای گوش دادن به تغییرات در trust اجازه می‌دهد."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"‏اتصال به یک سرویس trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"‏به یک برنامه کاربردی برای اتصال به یک سرویس trust agent اجازه می‌دهد."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"تعامل با سیستم به‌روزرسانی و بازیابی"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"به یک برنامه کاربردی اجازه می‌دهد با سیستم بازیابی و به‌روزرسانی‌های سیستم تعامل داشته باشد."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"دوبار لمس کنید تا بزرگنمایی کنترل شود"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index db118b4..6dd5e56 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Antaa sovellukselle luvan kuunnella verkon tilahavaintoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"Muuttaa syöttölaitteen kalibrointia."</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Antaa sovelluksen muokata kosketusnäytön kalibrointiparametreja. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-varmenteiden käyttö"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Antaa sovelluksen käyttää DRM-varmenteita ja hallita niiden käyttäjiä. Ei tavallisten sovellusten käyttöön."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Sallii sovelluksen käyttää salasanalla suojattua tallennustilaa."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Hallinnoi näppäinvahdin näyttämistä ja piilottamista"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Antaa sovelluksen hallita näppäinvahtia."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Seuraa luottamuksen tilamuutoksia."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Antaa sovelluksen seurata luottamuksen tilamuutoksia."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Luotettavaan tahoon sitoutuminen"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Antaa sovelluksen sitoutua luotettavaan tahoon."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Vuorovaikutus päivitys- ja palautusjärjestelmän kanssa"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Sallii sovelluksen vuorovaikutuksen palautusjärjestelmän ja järjestelmäpäivitysten kanssa."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ohjaa zoomausta napauttamalla kahdesti"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9cf9a45..7a8c975 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet à une application de détecter les observations sur les conditions du réseau. Ne devrait jamais être nécessaire pour les applications standards."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"modifier le calibrage du périphérique d\'entrée"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accéder aux certificats GDN"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet à une application de fournir et d\'utiliser les certificats de GDN. Cela ne devrait jamais être nécessaire pour les applications normales."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet à une application d\'accéder au stockage sécurisé keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Contrôler l\'affichage et le masquage de la protection des touches"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet à une application de contrôler la protection des touches."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Détecter les modifications de l\'état de confiance"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permet à une application de détecter les modifications de l\'état de confiance."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Lier à un service d\'agent de confiance"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permet à une application de se lier à un service d\'agent de confiance."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet à une application d\'interagir avec le système de récupération et les mises à jour système."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Appuyer deux fois pour régler le zoom"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index b10bd342..a57823f 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet à une application de détecter des observations sur les conditions du réseau. Les applications standards ne devraient pas nécessiter cette autorisation."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"modifier le calibrage du périphérique d\'entrée"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permettre à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accéder aux certificats de GDN"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permettre à une application de fournir et d\'utiliser des certificats de GDN. Ne devrait jamais être nécessaire pour les applications standards."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permet à une application d\'accéder au stockage sécurisé keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Contrôler l\'affichage et le masquage de la protection des touches"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permet à une application de contrôler la protection des touches."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Détecter les modifications de l\'état de confiance"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permettre à une application de détecter les modifications de l\'état de confiance."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"S\'associer à un service d\'agent de confiance"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permettre à une application de s\'associer à un service d\'agent de confiance."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir avec le système de récupération et de mise à jour"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permet à une application d\'interagir avec le système de récupération et les mises à jour du système."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Appuyez deux fois pour régler le zoom."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 62c4576..bdba457 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -641,9 +641,9 @@
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"ऐप्स  को किसी खाते की समन्वयन सेटिंग संशोधित करने देता है. उदाहरण के लिए, इसका उपयोग लोग ऐप्स  का समन्‍वयन किसी खाते से सक्षम करने में हो सकता है."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"समन्वयन आंकड़े पढ़ें"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ऐप्स  को किसी खाते के समन्वयन आंकड़े, साथ ही समन्‍वयित ईवेंट का इतिहास और समन्‍वयित डेटा की मात्रा पढ़ने देता है."</string>
-    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ग्राहकी-प्राप्त फ़ीड पढ़ें"</string>
+    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता-प्राप्त फ़ीड पढ़ें"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ऐप्स को वर्तमान में समन्वयित फ़ीड के बारे में विवरण प्राप्त करने देता है."</string>
-    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"ग्राहकी-प्राप्त फ़ीड लिखें"</string>
+    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"सदस्यता-प्राप्त फ़ीड लिखें"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"ऐप्स  को आपके वर्तमान समन्वयित फ़ीड को संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स  आपके समन्वयित फ़ीड को बदल सकते है."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"शब्दकोश में आपके द्वारा जोड़े गए शब्‍दों को पढ़ें"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"ऐप्स को ऐसे सभी शब्‍दों, नामों और वाक्यांशों को पढ़ने देता है जो संभवत: उपयोगकर्ता द्वारा उपयोगकर्ता ‍शब्दकोश में संग्रहीत किए गए हों."</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ऐप्स  को नेटवर्क स्थितियों के अवलोकनों को सुनने देता है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट उपकरण कैलिब्रेशन बदलें"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ऐप्स को टच स्क्रीन के कैलिब्रेशन पैरामीटर को बदलने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्र एक्सेस करें"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"एप्लिकेशन को DRM प्रमाणपत्रों का प्रावधान और उपयोग करने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होना चाहिए."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"स्‍क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"स्‍क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ऐप्स  को कीगार्ड सुरक्षित संग्रहण एक्सेस करने देती है."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"कीगार्ड दिखाना और छिपाना नियंत्रित करें"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ऐप्स  को कीगार्ड नियंत्रित करने देती है."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ट्रस्ट स्थिति बदलावों को सुनें."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"किसी एप्लिकेशन को ट्रस्ट स्थिति के बदलावों को सुनने की अनुमति देती है."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ट्रस्ट एजेंट सेवा से आबद्ध करना"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"किसी एप्लिकेशन को ट्रस्ट एजेंट सेवा से आबद्ध करने की अनुमति देती है."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"अपडेट और पुनर्प्राप्ति सिस्टम के साथ सहभागिता करें"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"एप्लिकेशन को पुनर्प्राप्ति सिस्टम और सिस्टम अपडेट के साथ सहभागिता करने देती है."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ज़ूम नियंत्रण के लिए दो बार स्पर्श करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fc2601b..fcd51ab 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Omogućuje aplikaciji praćenje motrenja mrežnih uvjeta. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"promjena kalibracije uređaja za unos"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Omogućuje aplikaciji izmjenu parametara kalibracije dodirnog zaslona. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"pristup DRM certifikatima"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Nikad ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Omogućuje aplikaciji pristupanje zaključanoj sigurnoj pohrani."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Upravljanje prikazivanjem i skrivanjem zaključavanja tipkovnice"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Omogućuje aplikaciji upravljanje zaključavanjem tipkovnice."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Prati promjene pouzdanog stanja."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Omogućuje aplikaciji praćenje promjena pouzdanog stanja."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezivanje s uslugom pouzdanog predstavnika"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Omogućuje aplikaciji povezivanje s uslugom pouzdanog predstavnika."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcija s ažuriranjem i sustavom za oporavak"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Omogućuje aplikaciji interakciju sa sustavom za oporavak i ažuriranjima sustava."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dodirnite dvaput za upravljanje zumiranjem"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c0effd2..4932e88 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Lehetővé teszi egy alkalmazás számára, hogy figyelemmel kísérje a hálózati körülményekkel kapcsolatos észrevételeket. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"beviteli eszköz kalibrációjának módosítása"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lehetővé teszi, hogy az alkalmazás módosítsa az érintőképernyő kalibrációs paramétereit. A normál alkalmazásoknál erre elvileg soha nincs szükség."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-tanúsítványokhoz való hozzáférés"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szüksége."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lehetővé teszi egy alkalmazás számára, hogy hozzáférjen a kóddal védett tárhelyhez."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Billentyűzár megjelenítésének és elrejtésének vezérlése"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Lehetővé teszi egy alkalmazás számára a billentyűzár vezérlését."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Trust-állapot változásának figyelése"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Lehetővé teszi, hogy az alkalmazás figyelje a trust-állapot változásait."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Csatlakozás egy trust agent szolgáltatáshoz"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Lehetővé teszi, hogy az alkalmazás egy trust agent szolgáltatáshoz csatlakozzon."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Kapcsolatfelvétel a frissítési és helyreállítási rendszerrel"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Lehetővé teszi egy alkalmazás számára, hogy kapcsolatba lépjen a helyreállítási rendszerrel és a rendszerfrissítésekkel."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Érintse meg kétszer a nagyítás beállításához"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 29a8d07..805f77b 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Հավելվածին թույլ է տալիս լսել դիտարկումներ ցանցային պայմանների վերաբերյալ: Սովորական հավելվածների համար երբեք պետք չի գալիս:"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"փոփոխել մուտքի սարքի չափաբերումը"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Թույլ է տալիս ծրագրին փոփոխել հպէկրանի չափաբերման կարգավորումները: Սովորական ծրագրերի համար երբեք պետք չի գալու:"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM հավաստագրերի մատչում"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ծրագրին թույլ է տալիս տրամադրել և օգտագործել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Վերահսկել էկրանի ապակողպման գաղտնաբառերի թույլատրելի երկարությունն ու գրանշանները:"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Թույլ է տալիս հավելվածին մուտք գործել ստեղնակողպեքով պաշտպանված պահոց:"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Կառավարել ստեղնակողպեքի ցուցադրումը և թաքցնումը"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Թույլ է տալիս հավելվածին կառավարել ստեղնաշարի պաշտպանիչը:"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Լսել վստահության կարգավիճակի ​փոփոխությունները:"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ծրագրին թույլ է տալիս լսել վստահության կարգավիճակի փոփոխությունները:"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Կապվել վստահելի գործակալի ծառայությանը"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ծրագրին թույլ է տալիս կապվել վստահելի գործակալի ծառայությանը:"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Փոխազդել թարմացման և վերականգնման համակարգի հետ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Թույլ է տալիս ծրագրին փոխազդել վերականգնման համակարգի և համակարգի թարմացումների հետ:"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Հպեք երկու անգամ` դիտափոխման կարգավորման համար"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 71fd308..e161466 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Memungkinkan aplikasi mendengar untuk observasi kondisi jaringan. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"mengubah kalibrasi perangkat masukan"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Memungkinkan aplikasi mengubah parameter kalibrasi layar sentuh. Tidak diperlukan oleh aplikasi normal."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"mengakses sertifikat DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Memungkinkan aplikasi menyediakan dan menggunakan sertifikat DRM. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Mengizinkan aplikasi mengakses pengaman penyimpanan aman."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrol untuk menampilkan dan menyembunyikan pengaman"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Izinkan aplikasi untuk mengontrol pengaman."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Dengarkan perubahan status kepercayaan."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Mengizinkan aplikasi mendengarkan perubahan dalam status kepercayaan."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Ikat ke layanan agen kepercayaan"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Mengizinkan aplikasi mengikat ke layanan agen kepercayaan."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan sistem pemulihan dan pembaruan"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Mengizinkan aplikasi berinteraksi dengan sistem pemulihan dan pembaruan sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Sentuh dua kali untuk mengontrol perbesar/perkecil"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 958f34c..740075f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Consente a un\'applicazione di ascoltare le osservazioni sulle condizioni di rete. Da non utilizzare mai con app normali."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"modifica calibrazione del dispositivo di immissione"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Consente all\'app di modificare i parametri di calibrazione del touch screen. Questa opzione non deve essere utilizzata per le app normali."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesso a certificati DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Consente a un\'app di fornire e utilizzare ceritificati DRM. Questa opzione non deve essere utilizzata per app normali."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Impostazione regole password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Controllo tentativi di sblocco dello schermo"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Consente a un\'applicazione di accedere all\'archivio sicuro keguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controllo della visualizzazione e dell\'occultamento di keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Consente a un\'applicazione di controllare keguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Rilevamento modifiche dello stato trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Consente a un\'applicazione di rilevare le modifiche nello stato trust."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Associazione a un servizio trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Consente a un\'applicazione di associarsi a un servizio trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interazione con il sistema di ripristino e aggiornamento"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Consente a un\'applicazione di interagire con il sistema di ripristino e con gli aggiornamenti di sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tocca due volte per il comando dello zoom"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9ecc437..61754c3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"מאפשרת לאפליקציה לקלוט מעקב אחר תנאי רשת. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"שינוי הכיול של מכשיר קלט"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"מאפשרת לאפליקציה לשנות את פרמטרי הכיול של מסך המגע. לעולם לא אמורה להיות נחוצה לאפליקציות רגילות."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"‏גישה אל אישורי DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"‏מאפשרת לאפליקציה לנהל תצורה של אישורי DRM ולהשתמש בהם. לעולם לא אמורה להיות נחוצה עבור אפליקציה רגילה."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"שלוט באורך ובתווים המותרים בסיסמאות לביטול נעילת מסך."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"מאפשר לאפליקציה לגשת לאחסון המוגן באמצעות מפתח."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"שלוט בהצגה והסתרה של מגן המקלדת"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"מאפשר לאפליקציה לשלוט במגן המקלדת."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"חיפוש שינויים במצב אמון."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"מאפשר לאפליקציה לחפש שינויים במצב אמון."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"איגוד אל שירות סוכן אמון"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"מאפשר לאפליקציה לאגוד אל שירות סוכן אמון."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"אינטראקציה עם מערכת שחזור ועדכונים"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"מאפשרת לאפליקציה ליצור אינטראקציה עם מערכת השחזור ועדכוני מערכת."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"גע פעמיים לבקרת מרחק מתצוגה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a75ee90..62ee883 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ネットワーク状況を監視するためリッスンすることをアプリに許可します。通常のアプリで必要になることはありません。"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"入力デバイスの調整を変更"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"タッチスクリーンの調整パラメータの変更をアプリに許可します。通常のアプリでは必要ありません。"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM証明書へのアクセス権"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM証明書のプロビジョニングと使用をアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"画面ロック解除パスワードの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"キーガードセキュアストレージへのアクセスをアプリに許可する"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"キーガードの表示/非表示の制御"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"キーガードの制御をアプリに許可します。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"信頼状態の変更をリッスン"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"信頼状態の変更をリッスンすることをアプリに許可します。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"信頼できるエージェントサービスへのバインド"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"信頼できるエージェントサービスにバインドすることをアプリに許可します。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"アップデートと回復システムへのアクセス"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"回復システムとシステムアップデートへのアクセスをアプリに許可します。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ダブルタップでズームコントロール"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 15abf53..4855f27 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"საშუალებას აძლევს აპლიკაციებს განახორციელოს ქსელის მდგომარეობის მონიტორინგი. ეს ფუნქცია ჩვეულებრივ აპებს არ ჭირდება."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"შეყვანის მოწყობილობის კალიბრაციის ცვლილება"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"საშუალებას აძლევს აპს შეცვალოს სენსორული ეკრანის კალიბრაციის პარამეტრები. ჩვეულებრივ აპებს წესით არ უნდა დაჭირდეს."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM სერთიფიკატებზე წვდომა"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"საშუალებას აძლევს აპლიკაციას დანერგოს და გამოიყენოს DRM სერთიფიკატები. ეს უფლება ჩვეულებრივ აპებს არ ჭირდება."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"გააკონტროლეთ ეკრანის განბლოკვის პაროლში დაშვებული სიმბოლოები და მისი სიგრძე."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ეკრანის განბლოკვის მცდელობების გაკონტროლება"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"აპლიკაციას ღილაკების დამცავის უსაფრთხო საცავზე წვდომის უფლება ექნება."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ღილაკების დამცავის გამოჩენისა და დამალვის მართვა"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"აპლიკაციას შეეძლება ღილაკების დამცავის კონტროლი."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ნდობის მდგომარეობის ცვლილებების მოსმენა."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"საშუალებას აძლევს აპლიკაციას მოუსმინოს ცვლილებებს სანდო მდგომარეობაში."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"სანდო აგენტის სერვისზე მიმაგრება."</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"საშუალებას აძლევს აპლიკაციას მიემაგროს სანდო აგენტის სერვისს."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"განახლებასთან და აღდგენის სისტემასთან ინტერაქცია"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"საშუალებას აძლევს აპლიკაციას მოახდინოს აღდგენის სისტემასთან და სისტემის განახლებასთან ინტერაქცია."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"მასშტაბის მართვისთვის შეეხეთ ორჯერ."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index c2ff0e8..73769fb 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ឲ្យ​កម្មវិធី​សង្កេត​មើល​​លើ​លក្ខខណ្ឌ​បណ្ដាញ​។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ប្ដូរ​​ចំណុច​ឧបករណ៍​បញ្ចូល"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ឲ្យ​​កម្មវិធី​កែ​ប៉ារ៉ាម៉ែត្រ​កែ​ចំណុច​​នៃ​ការ​ប៉ះ​អេក្រង់។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"ចូល​មើល​វិញ្ញាបនបត្រ DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ឲ្យ​កម្មវិធី​ផ្ដល់ និង​ប្រើ​វិញ្ញាបនបត្រ DRM ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"ពិនិត្យ​ប្រវែង និង​តួអក្សរ​ដែល​បាន​អនុញ្ញាត​ក្នុង​ពាក្យ​សម្ងាត់​ចាក់​សោ​អេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ពិនិត្យ​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យ​កម្មវិធី​ចូល​​ការ​ផ្ទុក​មាន​សុវត្ថិភាព keguard ។"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យ​ការ​បង្ហាញ និង​លាក់​ការ​ការពារ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង keguard ។"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ស្ដាប់​ការ​ផ្លាស់ប្ដូរ​ស្ថានភាព​ដែល​ទុកចិត្ត។"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"ឲ្យ​កម្មវិធី​ស្ដាប់​ការ​ផ្លាស់ប្ដូរ​ក្នុង​ស្ថានភាព​ដែល​​ទុកចិត្ត។"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ភ្ជាប់​ទៅ​សេវាកម្ម​ភ្នាក់ងារ​ដែល​ទុកចិត្ត"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"ឲ្យ​កម្មវិធី​ភ្ជាប់​សេវាកម្ម​ភ្នាក់ងារ​ដែល​ទុក​ចិត្ត។"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"អន្តរកម្ម​ជា​មួយ​បច្ចុប្បន្នភាព និង​ប្រព័ន្ធ​សង្គ្រោះ"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ឲ្យ​កម្មវិធី​មាន​អន្តរកម្ម​ជា​មួយ​ប្រព័ន្ធ​សង្គ្រោះ និង​បច្ចុប្បន្នភាព​ប្រព័ន្ធ។"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ប៉ះ​ពីរ​ដង ​​ដើម្បី​គ្រប់គ្រង​ការ​ពង្រីក"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8d8eb88..bb26d4f 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"애플리케이션이 네트워크 상태에 대한 관측 보고를 수신하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"입력 기기 보정 변경"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"앱이 터치 스크린의 보정 매개변수를 수정할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM 인증서에 액세스"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"애플리케이션이 DRM 인증서를 프로비저닝하고 사용하도록 허용합니다. 일반 앱에서는 필요하지 않습니다."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"애플리케이션에서 키가드 보안 저장소에 액세스하도록 허용합니다."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"키가드 표시 및 숨기기 설정"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"애플리케이션에서 키가드를 제어하도록 허용합니다."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Trust 상태 변경사항 수신"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"애플리케이션이 Trust 상태에서의 변경사항을 수신할 수 있도록 허용합니다."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Trust Agent 서비스에 연결"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"애플리케이션이 Trust Agent 서비스에 바인딩할 수 있도록 허용합니다."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"업데이트 및 복구 시스템과 상호작용"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"애플리케이션이 복구 시스템 및 시스템 업데이트와 상호작용할 수 있도록 허용합니다."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"확대/축소하려면 두 번 터치하세요."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 3b31a8e..60b7da4 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັ່ນຕິດຕາມເພື່ອສັງເກດສະພາບຂອງເຄືອຂ່າຍ. ປົກກະຕິແລ້ວແອັບຯທຳມະດາຈະບໍ່ຕ້ອງການໃຊ້."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ປ່ຽນ​ການ​ວັດ​ແທ້​ອຸ​ປະ​ກອນ​ປ້ອນ​ຂໍ້​ມູນ"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ແກ້​ໄຂ​ຄ່າ​ການວັດ​ແທ້​ໜ້າ​ຈ​ໍ​ສຳ​ຜັດ. ​ແອັບຯ​ທຳ​ມະ​ດາບໍ່​ຄວນ​ໃຊ້."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"ເຂົ້າ​ເຖິງ​ໃບຮັບຮອງ DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ອະນຸຍາດ​ໃຫ້​ແອັບພລິເຄຊັນ​ຈັດຫາ ແລະ​ນຳໃຊ້​ໃບຮັບຮອງ DRM. ແອັບຯ​ທຳມະດາ​ບໍ່​ຄວນ​ຕ້ອງ​ການ​ໃຊ້."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"ຄວບຄຸມຄວາມຍາວຂອງໂຕອັກສອນທີ່ສາມາດໃຊ້ກັບລະຫັດປົດລັອກໜ້າຈໍ"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ເຂົ້າເຖິງບ່ອນຈັດເກັບຂໍ້ມູນຄວາມປອດໄພດ້ວຍຄີກາດ."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ຄວບຄຸມການສະແດງ ແລະການເຊື່ອງໂຕລັອກປຸ່ມກົດ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນສາມາດຄວບຄຸມຄີກາດໄດ້."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"​ຕິດ​ຕາມ​ການ​ປ່ຽນ​ແປງ​ສະ​ຖາ​ນະ​ການ​ເຊື່ອ​ຖືກ."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ຕິດ​ຕາມ​​ການ​ປ່ຽນ​ແປງ​ໃນ​ສະ​ຖາ​ນະ​ການ​ເຊື່ອ​ຖື."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"​ເຊື່ອມ​ໂຍງ​ຫາ​ບໍ​ລິ​ການ​ຕົວ​ແທນ​ການ​ເຊື່ອ​ຖື"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນເຊື່ອມ​ໂຍງ​ກັບ​ບໍ​ລິ​ການ​ຕົວ​ແທນ​ທີ່​ເຊື່ອ​ຖື​ໄດ້."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"ຕິດຕໍ່ກັບລະບົບອັບເດດ ແລະລະບົບກູ້ຂໍ້ມູນ."</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຕິດຕໍ່ກັບລະບົບກູ້ຂໍ້ມູນ ແລະການອັບເດດລະບົບ."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"ແຕະສອງເທື່ອສຳລັບການຄວບຄຸມການຊູມ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9c01d99..b40e10b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Leidžiama programai vykdyti tinklo sąlygų stebėjimą. To niekada neturėtų prireikti naudojant įprastas programas."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"keisti įvesties įrenginio kalibravimą"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Leidžiama programai keisti jutiklinio ekrano kalibravimo parametrus. Neturėtų prireikti naudojant įprastas programas."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"gali pasiekti DRM sertifikatus"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Programai leidžiama pasiekti ir naudoti DRM sertifikatus. Neturėtų prireikti naudojant įprastas programas."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Programai leidžiama pasiekti „KeyGuard“ saugyklą."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Valdyti „KeyGuard“ rodymą ir slėpimą"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Programai leidžiama valdyti „KeyGuard“."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Atsižvelgti į patikimos būsenos pakeitimus."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Programai leidžiama atsižvelgti į patikimos būsenos pakeitimus."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Susisaistyti su „trust agent“ paslauga"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Programai leidžiama susisaistyti su „trust agent“ paslauga."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Sąveikauti su naujiniu ir atkūrimo sistema"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Programai leidžiama sąveikauti su atkūrimo sistema ir sistemos naujiniais."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dukart palieskite, kad valdytumėte mastelio keitimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 478c32d..6b91a6d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ļauj lietojumprogrammai iegūt informāciju par tīkla stāvokļa novērojumiem. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"mainīt ievadierīces kalibrēšanu"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ļauj lietotnei pārveidot skārienekrāna kalibrēšanas parametrus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Piekļuve digitālā satura tiesību pārvaldības sertifikātiem"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ļauj lietojumprogrammai nodrošināt un izmantot digitālā satura tiesību pārvaldības sertifikātus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ļauj lietojumprogrammai piekļūt krātuvei, kas aizsargāta ar atslēgu."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Pārvaldīt krātuves rādīšanu un paslēpšanu."</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Ļauj lietojumprogrammai pārvaldīt krātuvi."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Klausīties uzticamības statusa izmaiņas"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ļauj lietojumprogrammai klausīties uzticamības statusa izmaiņas."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Izveidot savienojumu ar uzticamības pārbaudes pakalpojumu"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ļauj lietojumprogrammai izveidot savienojumu ar uzticamības pārbaudes pakalpojumu."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Mijiedarbošanās ar atjauninājumu un atkopšanas sistēmu"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ļauj lietojumprogrammai mijiedarboties ar atkopšanas sistēmu un sistēmas atjauninājumiem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index a587992..ea1baa1 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Аппликешнд сүлжээний байдлын талаар ажиглалтуудыг хүлээн авахыг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"оролтын төхөөрөмжийн калибрешныг өөрчлөх"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Мэдрэгчтэй дэлгэцний калибрешн параметрийг өөрчлөхийг апп-д зөвшөөрнө. Энгийн апп-д шаардлагагүй."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"хандалтын DRM сертификат"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Аппликешнд DRM сертификатыг ашиглах болон нийлүүлэхийг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Дэлгэц түгжих нууц үгэнд зөвшөөрөгдсөн тэмдэгт болон уртыг удирдах"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Дэлгэц тайлах оролдлогыг хянах"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Аппликешн нь хамгаалалттай аюулгүй санд хандах боломжтой."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Түлхүүр хамгаалалтын харуулах болон далдлахыг удирдах"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Аппликешн нь түлхүүр хамгаалагчыг удирдах боломжтой."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Итгэмжлэлд орж буй өөрчлөлтийг мэдэх."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Итгэмжлэлд орж буй өөрчлөлтийг мэдэх боломжийг аппликешнд олгоно."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Итгэмжлэгдсэн төлөөлөгчийн үйлчилгээтэй холбогдох"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Аппликешнд итгэмжлэгдсэн төлөөлөгчтэй холбогдох боломж олгоно."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Шинэчлэлт болон сэргээх системтэй харилцах"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Аппликешнд сэргээх систем болон системийн шинэчлэлтэй харилцах боломж олгоно."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Өсгөх контрол дээр хоёр удаа товшино уу"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index dbf6004..219e47b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Membenarkan aplikasi mendengar pemerhatian tentang keadaan rangkaian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"tukar penentukuran peranti input"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Membenarkan apl mengubah suai parameter penentukuran skrin sentuh. Ini tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"akses sijil DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Membenarkan aplikasi memperuntuk dan menggunakan sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Membenarkan aplikasi mengakses storan selamat pengawal kekunci."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kawal paparkan dan sembunyikan pengawal kekunci"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Membenarkan aplikasi untuk mengawal pengawal kekunci."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Dengar perubahan keadaan amanah."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Membenarkan aplikasi mendengar perubahan dalam keadaan amanah."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Mengikat kepada perkhidmatan ejen amanah"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Membenarkan aplikasi terikat kepada perkhidmatan ejen amanah."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan kemas kini dan sistem pemulihan"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Membenarkan aplikasi berinteraksi dengan sistem pemulihan dan kemas kini sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Sentuh dua kali untuk mendapatkan kawalan zum"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 12d18e0..593d260 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -164,7 +164,7 @@
     <string name="global_action_power_off" msgid="4471879440839879722">"Slå av"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Feilrapport"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Utfør feilrapport"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"Informasjon om den nåværende tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
+    <string name="bugreport_message" msgid="398447048750350456">"Informasjon om tilstanden til enheten din samles inn og sendes som en e-post. Det tar litt tid fra du starter feilrapporten til e-posten er klar, så vær tålmodig."</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Stillemodus"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Lyden er av"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Lyden er på"</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Gir appen tillatelse til å lytte etter observasjoner om nettverksforhold. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"endre kalibreringen av inndataenheter"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lar appen endre kalibrasjonsparametrene for berøringsskjermen. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tilgang til DRM-sertifikater"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Lar en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Lar en app bruke sikker lagring via keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrollér om tastelåsen er skjult eller vist"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillater at en app kontrollerer tastelåsen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Oppdag endringer i tillitsstatusen."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Gir appen tillatelse til å oppdage endringer i tillitsstatusen."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Tilknytt en tillitsagent-tjeneste."</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Gir appen tillatelse til å knyttes til en tillitsagent-tjeneste."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Samhandling med oppdateringer og gjenopprettingssystem"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Tillater en app å samhandle med gjenopprettingsssystemet og systemoppdateringer."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Trykk to ganger for zoomkontroll"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2c02916..9225c23 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Hiermee kan een app controleren op waarnemingen met betrekking tot netwerkomstandigheden. Nooit vereist voor normale apps."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"kalibratie van invoerapparaat wijzigen"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Hiermee kan de app de kalibratieparameters van het aanraakscherm aanpassen. Nooit vereist voor normale apps."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"toegang tot DRM-certificaten"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Toestaan dat een app DRM-certificaten registreert en gebruikt. Nooit vereist voor normale apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Hiermee krijgt een app toegang tot opslag met toetsbeveiliging."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Weergeven en verbergen van toetsbeveiliging beheren"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Staat toe dat een app de toetsbeveiliging beheert."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Controleren op wijzigingen in de trust-status."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Toestaan dat een app controleert op wijzigingen in de trust-status."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Binden aan een trust-agentservice"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Toestaan dat een app wordt gebonden aan een trust-agentservice."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interactie met update- en herstelsysteem"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Hiermee kan een app interactie hebben met het herstelsysteem en systeemupdates."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Raak twee keer aan voor zoomregeling"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b2a9184..931c24c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Pozwala aplikacji śledzić stan sieci. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"zmiana kalibracji urządzenia wejściwego"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Zezwala aplikacji na modyfikowanie parametrów kalibracji ekranu dotykowego. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"dostęp do certyfikatów DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Zezwala aplikacji na dodanie i używanie certyfikatów DRM. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <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>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Zezwala aplikacji na dostęp do bezpiecznego magazynu kluczy."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontroluj wyświetlanie i ukrywanie zabezpieczenia kluczami"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umożliwia aplikacji kontrolowanie zabezpieczenia kluczami."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Monitoruj zmiany w stanie zaufania."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Zezwala aplikacji na monitorowanie zmian w stanie zaufania."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Powiąż z usługą agenta zaufania"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Zezwala aplikacji na powiązanie z usługą agenta zaufania."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcja z systemem odzyskiwania i aktualizacjami"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Zezwala aplikacji na interakcję z systemem odzyskiwania i aktualizacjami systemu."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dotknij dwukrotnie, aby sterować powiększeniem."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3e55c58..9eb7512 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que uma aplicação ouça observações sobre as condições da rede. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"alterar a calibragem de entrada do dispositivo"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite à aplicação modificar os parâmetros de calibragem do ecrã tátil. Esta funcionalidade nunca deverá ser necessária para aplicações normais."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Aceder a certificados DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que uma aplicação forneça e utilize certificados DRM. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite a uma aplicação aceder ao armazenamento seguro de proteção de teclado."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar apresentação e ocultação de proteção de teclado"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que uma aplicação controle a proteção de teclado."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Registar alterações no estado trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que uma aplicação registe alterações no trust state."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Vincular a um serviço de trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que uma aplicação fique vinculada a um serviço de trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de recuperação e de atualização"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que uma aplicação interaja com o sistema de recuperação e as atualizações do sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toque duas vezes para controlar o zoom"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index de22fd5..fd75660 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que o aplicativo detecte observações nas condições da rede. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"alterar calibragem do dispositivo de entrada"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que o aplicativo modifique os parâmetros de calibragem da tela sensível ao toque. Não deve ser necessário para aplicativos normais."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"acessar certificados de DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que o aplicativo provisione e use certificados de DRM. Não deve ser necessário para aplicativos comuns."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite que o aplicativo acesse o armazenamento seguro do bloqueio de teclado."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Controlar a exibição e ocultação do bloqueio de tela"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite que o aplicativo controle o bloqueio de teclado."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectar alterações no estado de confiança."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que o aplicativo detecte alterações no estado de confiança."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Associar a um serviço de agente de confiança"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que o aplicativo se associe a um serviço de agente de confiança."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de atualizações e recuperação"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite que um aplicativo interaja com o sistema de recuperação e as atualizações do sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Toque duas vezes para controlar o zoom"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 6c5344b..4e9806b 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1166,6 +1166,10 @@
     <skip />
     <!-- no translation found for permdesc_setInputCalibration (4527511047549456929) -->
     <skip />
+    <!-- no translation found for permlab_accessDrmCertificates (7436886640723203615) -->
+    <skip />
+    <!-- no translation found for permdesc_accessDrmCertificates (8073288354426159089) -->
+    <skip />
     <!-- no translation found for policylab_limitPassword (4497420728857585791) -->
     <skip />
     <!-- no translation found for policydesc_limitPassword (3252114203919510394) -->
@@ -2104,6 +2108,14 @@
     <skip />
     <!-- no translation found for permdesc_control_keyguard (3043732290518629061) -->
     <skip />
+    <!-- no translation found for permlab_trust_listener (1765718054003704476) -->
+    <skip />
+    <!-- no translation found for permdesc_trust_listener (8233895334214716864) -->
+    <skip />
+    <!-- no translation found for permlab_bind_trust_agent_service (8242093169457695334) -->
+    <skip />
+    <!-- no translation found for permdesc_bind_trust_agent_service (7041930026024507515) -->
+    <skip />
     <!-- no translation found for permlab_recovery (3157024487744125846) -->
     <skip />
     <!-- no translation found for permdesc_recovery (8511774533266359571) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index d4f5183..a8a75a5 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite unei aplicații să asculte observații despre starea rețelei. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"schimbați calibrarea dispozitivului de intrare"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite aplicației să modifice parametrii de calibrare a ecranului tactil. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesați certificatele DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite unei aplicații să furnizeze și să utilizeze certificate DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Permite unei aplicații să acceseze stocarea securizată când tastatura este blocată."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Stabilește afișarea și ascunderea blocării tastaturii"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Permite unei aplicații să controleze blocarea tastaturii."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Detectarea modificărilor în starea de încredere."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite unei aplicații să detecteze modificările în starea de încredere."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Asocierea la un serviciu „agenți de încredere”."</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite unei aplicații să se asocieze la un serviciu „agent de încredere”."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interacțiune cu sistemul de recuperare și de actualizare"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Permite unei aplicații să interacționeze cu sistemul de recuperare și cu actualizările de sistem."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeţi de două ori pentru a mări/micşora"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fd0776b..d142e9a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Приложение сможет использовать данные о состоянии сети. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"изменение параметров калибровки экрана"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Приложение сможет изменять параметры калибровки сенсорного экрана. Это разрешение обычно используется только специальными приложениями."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Доступ к сертификатам DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Приложение сможет синхронизировать и использовать сертификаты DRM (разрешение актуально только для специальных приложений)."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Приложение сможет получить доступ к хранилищу ключей."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Управлять отображением хранилища ключей"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Приложение сможет управлять хранилищем ключей."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Отслеживание изменений статуса доверия"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Приложение сможет отслеживать изменения в статусе доверия."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Подключение к службе Trust Agents"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Приложение сможет подключаться к службе Trust Agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаимодействовать с системой восстановления и обновлениями"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Приложение сможет взаимодействовать с системой восстановления и обновлениями системы."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Нажмите дважды для изменения масштаба"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 2c8b5d2..707bdf1 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -233,7 +233,7 @@
     <string name="permgrouplab_display" msgid="4279909676036402636">"Používateľské rozhranie iných aplikácií"</string>
     <string name="permgroupdesc_display" msgid="6051002031933013714">"Vplyv na používateľské rozhranie ďalších aplikácií."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložisko"</string>
-    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do úložiska USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
     <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Funkcie zjednodušenia ovládania"</string>
     <string name="permgroupdesc_accessibilityFeatures" msgid="4205196881678144335">"Funkcie, ktoré môže vyžadovať nápomocná technológia."</string>
@@ -347,7 +347,7 @@
     <string name="permdesc_backup" msgid="6912230525140589891">"Umožňuje aplikácii ovládať mechanizmus na zálohovanie a obnovu údajov systému. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potvrdenie operácie úplnej zálohy alebo úplného obnovenia"</string>
     <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Umožňuje aplikácii spustiť používateľské rozhranie potvrdenia úplnej zálohy. Toto nastavenie by nemala používať žiadna aplikácia."</string>
-    <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobrazenie neoprávnených okien"</string>
+    <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobraziť neoprávnené okná"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Umožňuje aplikácii vytvárať okná, ktoré majú byť použité interným systémom používateľského rozhrania. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vykresliť cez ďalšie aplikácie"</string>
     <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Umožňuje aplikáciu vykresľovanie nad inými aplikáciami alebo súčasťami používateľského rozhrania. Táto funkcia môže zasahovať do vášho používania rozhrania inej aplikácie alebo meniť zobrazovaný obsah v iných aplikáciách."</string>
@@ -474,9 +474,9 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"Oprávnenie na inštaláciu poskytovateľa polohy"</string>
     <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváranie simulovaných zdrojov polohy na testovanie alebo inštalácia nového poskytovateľa informácií o polohe. Aplikácii to umožní nahradiť polohu a stav, ktoré vracajú iné zdroje informácií o polohe, ako sú napríklad systém GPS alebo poskytovatelia informácií o polohe."</string>
-    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"presná poloha (pomocou GPS a siete)"</string>
+    <string name="permlab_accessFineLocation" msgid="1191898061965273372">"zistiť presnú polohu (pomocou GPS a siete)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Umožňuje aplikácii získať vašu presnú polohu pomocou systému GPS (Global Positioning System) alebo zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej polohy. Tieto služby môžu zvýšiť spotrebu batérie."</string>
-    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"približná poloha (pomocou siete)"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"zistiť približnú polohu (pomocou siete)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Umožňuje aplikácii získať vašu približnú polohu. Táto poloha je odvodená zo služieb určovania polohy pomocou zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej približnej polohy."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"prístup k službe SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Umožňuje aplikácii používať funkcie nízkej úrovne aplikácie SurfaceFlinger."</string>
@@ -498,13 +498,13 @@
     <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Umožňuje aplikácii zachytiť a presmerovať zabezpečený výstup videa."</string>
     <string name="permlab_mediaContentControl" msgid="8749790560720562511">"ovládanie reprodukcie médií a prístup k metadátam"</string>
     <string name="permdesc_mediaContentControl" msgid="1637478200272062">"Umožňuje aplikácii ovládať reprodukciu médií a pristupovať k informáciám o médiách (názov, autor...)."</string>
-    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmeny vašich nastavení zvuku"</string>
+    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"meniť nastavenia zvuku"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať."</string>
-    <string name="permlab_recordAudio" msgid="3876049771427466323">"záznam zvuku"</string>
+    <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávať zvuk"</string>
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"Umožňuje aplikácii zaznamenávať zvuk pomocou mikrofónu. Toto povolenie umožňuje aplikácii zaznamenávať zvuk kedykoľvek bez vášho potvrdenia."</string>
     <string name="permlab_sim_communication" msgid="1180265879464893029">"komunikácia s kartou SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Umožňuje aplikácii odosielať príkazy na kartu SIM. Toto je veľmi nebezpečné povolenie."</string>
-    <string name="permlab_camera" msgid="3616391919559751192">"snímanie fotografií a natáčanie videí"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fotiť a nakrúcať videá"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"Umožňuje aplikácii fotografovať a nahrávať videá pomocou fotoaparátu. Toto povolenie umožňuje aplikácii používať fotoaparát kedykoľvek a bez vášho potvrdenia."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Zakázať indikátor LED prenosu pri používaní fotoaparátu"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Umožňuje v predinštalovanej systémovej aplikácii zakázať indikátor LED používania fotoaparátu."</string>
@@ -534,7 +534,7 @@
     <string name="permdesc_asec_rename" msgid="1794757588472127675">"Umožňuje aplikácii premenovať interné úložisko."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ovládať vibrovanie"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Umožňuje aplikácii ovládať vibrácie."</string>
-    <string name="permlab_flashlight" msgid="2155920810121984215">"ovládanie kontrolky"</string>
+    <string name="permlab_flashlight" msgid="2155920810121984215">"ovládať kontrolku"</string>
     <string name="permdesc_flashlight" msgid="6522284794568368310">"Umožňuje aplikácii ovládať svetlo."</string>
     <string name="permlab_manageUsb" msgid="1113453430645402723">"spravovať predvoľby a povolenia zariadení USB"</string>
     <string name="permdesc_manageUsb" msgid="7776155430218239833">"Umožňuje aplikácii spravovať predvoľby a povolenia zariadení USB."</string>
@@ -575,7 +575,7 @@
     <string name="permlab_factoryTest" msgid="3715225492696416187">"spustenie v režime továrenského testu"</string>
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Umožňuje aplikácii spustenie v režime nízkoúrovňového testu výrobcu a povolí úplný prístup k hardvéru tabletu. K dispozícii iba vtedy, keď je tablet spustený v režime testovania výrobcu."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Umožňuje aplikácii spustenie v režime nízkoúrovňového testu výrobcu a povolí úplný prístup k hardvéru telefónu. K dispozícii iba vtedy, keď je telefón spustený v režime testovania výrobcu."</string>
-    <string name="permlab_setWallpaper" msgid="6627192333373465143">"nastavenie tapety"</string>
+    <string name="permlab_setWallpaper" msgid="6627192333373465143">"nastaviť tapetu"</string>
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Umožňuje aplikácii nastaviť tapetu systému."</string>
     <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"upraviť veľkosť tapety"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Umožňuje aplikácii nastaviť tipy pre veľkosť tapety systému."</string>
@@ -610,7 +610,7 @@
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Umožňuje aplikácii zmeniť stav sieťového pripojenia zdieľaného pomocou tetheringu."</string>
     <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"zmeniť nastavenie použitia údajov na pozadí"</string>
     <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Umožňuje aplikácii zmeniť nastavenie používania údajov na pozadí."</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"zobraziť pripojenia siete Wi-Fi"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"zobraziť pripojenia Wi-Fi"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Umožňuje aplikácii zobraziť informácie o sieťach Wi-Fi. Napríklad o tom, či je sieť Wi-Fi povolená alebo názvy pripojených zariadení Wi-Fi."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"pripojiť a odpojiť od siete Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Umožňuje aplikácii pripojiť sa na prístupové body siete Wi-Fi, odpojiť sa od nich a meniť konfiguráciu zariadení pre siete Wi-Fi."</string>
@@ -631,19 +631,19 @@
     <string name="permlab_bluetooth" msgid="6127769336339276828">"párovať so zariadeniami Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
-    <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu NFC"</string>
+    <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie NFC."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivácia zámky obrazovky"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítať nastavenia synchronizácie"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"prepínať nastavenie synchronizácie medzi hodnotou zapnuté a vypnuté"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"zapnúť alebo vypnúť synchronizáciu"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Umožňuje aplikácii upraviť nastavenia synchronizácie v účte. Pomocou tohto povolenia je možné napríklad povoliť synchronizáciu aplikácie Ľudia s účtom."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"čítanie štatistických údajov o synchronizácii"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Umožňuje aplikácii čítať štatistické informácie o synchronizácii v účte vrátane histórie uskutočnených synchronizácií a informácií o množstve synchronizovaných údajov."</string>
-    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítanie zdrojov prihlásených na odber"</string>
+    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítať odoberané informačné kanály"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Umožňuje aplikácii získať podrobnosti o aktuálne synchronizovaných informačných kanáloch."</string>
-    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"zápis odoberaných zdrojov"</string>
+    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"zapisovať odoberané informačné kanály"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Umožňuje aplikácii upraviť vaše aktuálne synchronizované informačné kanály. Škodlivé aplikácie môžu synchronizované informačné kanály zmeniť."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"čítať výrazy pridané do slovníka"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Umožňuje aplikácii čítať všetky slová, názvy a frázy, ktoré mohol používateľ uložiť do svojho slovníka."</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikácii zachytávať informácie o stave siete. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"zmeniť kalibráciu vstupného zariadenia"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Umožňuje aplikácii upraviť parametre kalibrácie dotykovej obrazovky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"prístup k certifikátom DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Umožňuje aplikácii vydávať a používať certifikáty DRM. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Umožňuje aplikácii získať prístup k ukladaciemu priestoru zabezpečenému technológiou keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Ovládanie zobrazenia alebo skrytia technológie keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Umožňuje aplikácii ovládať technológiu keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Reagovanie na zmeny stavu dôveryhodnosti."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Umožňuje aplikácii reagovať na zmeny stavu dôveryhodnosti."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Viazanie sa na službu zástupcu dôveryhodnosti"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Umožňuje aplikácii viazať sa na službu zástupcu dôveryhodnosti."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcia so systémom aktualizácií a obnovenia"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Umožňuje aplikácii interakciu so systémom obnovenia a s aktualizáciami systému."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Ovládacie prvky lupy zobrazíte dvojitým dotknutím"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 1302eb8..e93b128 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Aplikaciji omogoča spremljanje razmer v omrežju. Pri navadnih aplikacijah to ne bi smelo biti potrebno."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"sprememba umerjanja vhodne naprave"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Aplikaciji dovoli spreminjanje parametrov za umerjanje zaslona na dotik. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"dostop do potrdil za upravljanje digitalnih pravic"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogoča pripravo in uporabo potrdil za upravljanje digitalnih pravic. To naj ne bi bilo nikoli potrebno za običajne aplikacije."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Aplikaciji omogoča dostop do varne shrambe Keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Nadzira prikaz in skrivanje zaklepanja tipkovnice"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Aplikaciji omogoča nadzor zaklepanja tipkovnice."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Spremljanje sprememb stanja zaupanja."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Aplikaciji dovoli spremljanje sprememb stanja zaupanja."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezovanje s storitvijo posrednikov zaupanja"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Aplikaciji dovoli povezovanje s storitvijo posrednikov zaupanja."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Uporaba sistema za posodobitev in obnovitev"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Aplikaciji dovoli uporabo sistema za obnovitev in posodobitev sistema."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Dvakrat se dotaknite za nadzor povečave/pomanjšave"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e636874..b2928e4 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Дозвољава апликацији да прати податке о условима на мрежи. Не би никада требало да буде потребно за нормалне апликације."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"промени калибрацију улазног уређаја"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Дозвољава апликацији да модификује параметре калибрације додирног екрана. Не би требало да буде потребно за нормалне апликације."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"приступ DRM сертификатима"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Дозвољава апликацији да додељује и користи DRM сертификате. Никада не би требало да се користи за уобичајене апликације."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Дозвољава апликацији да приступа безбедној меморији заштићеној шифром."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Контролиши приказивање и скривање заштите шифром"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Дозвољава апликацији да контролише заштиту шифром."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Праћење промена Trust стања."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Дозвољава апликацији да прати промене Trust стања."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Везивање за услугу Trust agents"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозвољава апликацији да се веже за услугу Trust agents."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Интеракција са системом за ажурирање и опоравак"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозвољава апликацији да ступа у интеракцију са системом за опоравак и ажурирањима система."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Додирните двапут да бисте контролисали зум"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 31e3c9c..b134a85 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillåter att appen lyssnar efter information om nätverksförhållanden. Vanliga appar bör aldrig behöva den här behörigheten."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ändra kalibreringen för inmatningsenheten"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Tillåter att appen ändrar kalibreringsparametrarna för pekskärmen. Detta behövs aldrig för vanliga appar."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tillgång till DRM-certifikat"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillåter att en app tillhandahåller och använder DRM-certifikat. Behövs inte för vanliga appar."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Tillåter att en app får åtkomst till säkert keyguard-lagringsutrymme."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrollera hur knapplåset visas och döljs"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Tillåter att en app kontrollerar knapplåsfunktionen."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Lyssna efter ändringar i betrodda agenters status."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Tillåter att en app lyssnar efter ändringar i den betrodda agentens status."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bind till en tjänst från en betrodd agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillåter att en app binds vid en tjänst från en betrodd agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interagera med uppdaterings- och återställningssystemet"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Tillåter att en app interagerar med systemuppdateringar och återställningssystemet."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Tryck två gånger för zoomkontroll"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 84fbf08..8f319f3 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Huruhusu programu kusikiliza matukio katika hali za mtandao. Haipaswi kuhitajika kamwe kwa programu za kawaida."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"badilisha urekebishaji wa kifaa cha kuingiza data"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Huruhusu programu kubadilisha vigezo vya urekebishaji vya skrini ya kugusa. Havipaswi kuhitajika kamwe kwa programu za kawaida."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"fikia vyeti vya DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Huruhusu programu kwa utoaji na matumizi ya vyeti vya DRM. Havifahi kuhitajika kwa ajili ya programu za kawaida."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kudhibiti urefu na herufi zinazoruhusiwa katika manenosiri ya kufungua skrini."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu idadi ya mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Inaruhusu programu kufikia hifadhi salama ya ufunguo wa ulinzi."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Dhibiti uonyeshaji na ufichaji wa kilinda-funguo"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Huruhusu programu kudhibiti kilinda-funguo."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Sikiliza mabadiliko ya hali ya kuaminiwa."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Huruhusu programu kusikiliza mabadiliko katika hali ya kuaminiwa."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Funga kwenye huduma ya dalali wa kuaminiwa"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Huruhusu programu kufungamanisha kwenye huduma ya dalali wa kuaminiwa."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Ingiliana na sasisho na mfumo wa kurejesha"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Huruhusu programu kuingiliana na mfumo wa kurejesha na sasisho la mfumo."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Gusa mara mbili kwa udhibiti cha kuza"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 57850a1..ecb3a58 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"อนุญาตให้แอปพลิเคชันฟังข้อสังเกตเกี่ยวกับสภาวะของเครือข่าย ไม่จำเป็นสำหรับแอปปกติ"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"เปลี่ยนการเทียบมาตรฐานอุปกรณ์อินพุต"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"อนุญาตให้แอปสามารถปรับพารามิเตอร์การเทียบมาตรฐานของหน้าจอสัมผัส ไม่ควรใช้สำหรับแอปทั่วไป"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"เข้าถึงใบรับรอง DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ช่วยให้แอปพลิเคชันสามารถจัดสรรและใช้ใบรับรอง DRM ได้ ไม่จำเป็นสำหรับแอปปกติทั่วไป"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"อนุญาตให้แอปพลิเคชันเข้าถึงพื้นที่จัดเก็บที่รักษาความปลอดภัยด้วยคีย์การ์ด"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ควบคุมการแสดงผลและการซ่อนตัวล็อกปุ่มกด"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"อนุญาตให้แอปพลิเคชันควบคุมตัวล็อกปุ่มกด"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"ฟังการเปลี่ยนแปลงของสถานะความน่าเชื่อถือ"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"อนุญาตให้แอปพลิเคชันฟังการเปลี่ยนแปลงที่มีต่อสถานะความน่าเชื่อถือ"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"ผูกกับบริการของตัวแทนที่เชื่อถือได้"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"อนุญาตให้แอปพลิเคชันผูกกับบริการของตัวแทนที่เชื่อถือได้"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"โต้ตอบกับการอัปเดตและระบบการกู้คืน"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"ช่วยให้แอปพลิเคชันสามารถโต้ตอบกับระบบการกู้คืนและการอัปเดตระบบ"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b91b44c..0a5e64c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Nagbibigay-daan sa isang application na makinig sa mga obserbasyon sa mga kundisyon ng network. Dapat na hindi kailanman kakailanganin para sa normal na apps."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"baguhin ang pag-calibrate ng input device"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Pinapayagan ang app na baguhin ang mga parameter sa pag-calibrate ng touch screen. Hindi dapat kailanganin sa normal na apps."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access sa Mga DRM certificate"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Nagbibigay-daan sa isang application na makapagbigay at gumamit ng mga DRM certficate. Hindi dapat kailanman kailanganin para sa mga normal na app."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Nagbibigay-daan sa isang application na i-access ang secure na storage ng keyguard."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kontrolin ang pagpapakita at pagtago sa keyguard"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Pinapayagan ang isang application na kontrolin ang keyguard."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Makinig sa mga pagbabago sa estado ng trust."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Pinapayagan ang isang application na makinig para sa mga pagbabago sa estado ng trust."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Sumailalim sa isang serbisyo ng trust agent"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Pinapayagan ang isang application na sumailalim sa isang serbisyo ng trust agent."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Makipag-ugnay sa system ng pag-update at pagbawi"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Binibigyang-daan ang isang application na makipag-ugnay sa system ng pagbawi at mga pag-update ng system."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Pindutin nang dalawang beses para sa pagkontrol ng zoom"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index dfb21f7..72e149f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Bir uygulamaya, ağ koşullarındaki gözlemleri dinleme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"giriş cihazı kalibrasyonunu değiştir"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Uygulamaya, dokunmatik ekranın kalibrasyon parametrelerini değiştirme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM sertifikalarına eriş"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Bir uygulamanın DRM sertifikaları için temel hazırlık yapmasına ve bunları kullanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Bir uygulamanın tuş kilitli güvenli depolamaya erişimine izin verir."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Tuş koruyucuyu görüntülemeyi ve gizlemeyi kontrol et"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Bir uygulamaya tuş koruyucuyu denetleme izni verir."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Güven durumundaki değişiklileri dinle."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Bir uygulamanın, güven durumundaki değişiklikleri dinlemesine izin verir."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Güven aracı hizmetine bağlan"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Bir uygulamanın, güven aracı hizmetine bağlanmasına izin verir."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Güncelleme ve kurtarma sistemiyle etkileşim kur"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Bir uygulamaya, kurtarma sistemi ve sistem güncellemeriyle etkileşim kurma izni verir."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Yakınlaştırma denetimi için iki kez dokunun"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 238293c..563d5ee 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Дозволяє програмі прослуховувати дані спостережень за станом мережі. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"змінювати калібрування пристрою введення"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Програма може змінювати параметри калібрування сенсорного екрана. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"отримувати доступ до сертифікатів DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Дозволяє додатку надавати та використовувати сертифікати DRM. Ніколи не застосовується для звичайних додатків."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів для розблокування екрана та дозволені в них символи."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Дозволяє програмі отримувати доступ до безпечного сховища через клавіатуру."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Керувати відображенням і хованням клавіатури"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Дозволяє програмі керувати клавіатурою."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Відстежувати зміни в стані довіри."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Дозволяє додатку відстежувати зміни в стані довіри."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Прив’язуватися до служби довірчих агентів"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Дозволяє додатку прив’язуватися до служби довірчих агентів."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Взаємодіяти з оновленнями системи та системою відновлення."</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Дозволяє додатку взаємодіяти із системою відновлення й оновленнями системи."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Двічі торкніться, щоб керувати масштабом"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b0a617f..8c424c3 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -323,8 +323,8 @@
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"truy cập thông tin ứng dụng hiện tại"</string>
     <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Cho phép chủ sở hữu truy xuất thông tin cá nhân về ứng dụng hiện tại ở nền trước của màn hình."</string>
-    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động khởi chạy ứng dụng"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho mục đích phát triển, không dành cho mục đích sử dụng thông thường."</string>
+    <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động chạy ứng dụng"</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho mục đích phát triển, không dành cho mục đích sử dụng thông thường."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xóa của gói"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"Cho phép ứng dụng truyền phát thông báo cho biết rằng gói ứng dụng đã bị xóa. Ứng dụng độc hại có thể sử dụng quyền này để loại bỏ bất kỳ ứng dụng nào khác đang chạy."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"gửi truyền phát SMS nhận được"</string>
@@ -346,7 +346,7 @@
     <string name="permlab_backup" msgid="470013022865453920">"kiểm soát sao lưu và khôi phục hệ thống"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Cho phép ứng dụng kiểm soát cơ chế sao lưu và khôi phục của hệ thống. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"xác nhận bản sao lưu đầy đủ hoặc khôi phục hoạt động"</string>
-    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Cho phép ứng dụng khởi chạy UI xác nhận sao lưu toàn bộ. Không dành cho bất kỳ ứng dụng nào."</string>
+    <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Cho phép ứng dụng chạy UI xác nhận sao lưu toàn bộ. Không dành cho bất kỳ ứng dụng nào."</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"hiển thị các cửa sổ trái phép"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Cho phép ứng dụng tạo các cửa sổ dùng cho giao diện người dùng hệ thống nội bộ. Không dành cho các ứng dụng thông thường."</string>
     <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vẽ trên ứng dụng khác"</string>
@@ -437,8 +437,8 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"sửa đổi bản đồ dịch vụ của Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"Cho phép ứng dụng sửa đổi bản đồ dịch vụ của Google. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"chạy khi khởi động"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến máy tính bảng mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ máy tính bảng do ứng dụng luôn chạy."</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Cho phép ứng dụng tự khởi chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến điện thoại mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ điện thoại do ứng dụng luôn chạy."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Cho phép ứng dụng tự chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến máy tính bảng mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ máy tính bảng do ứng dụng luôn chạy."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Cho phép ứng dụng tự chạy ngay khi hệ thống khởi động xong. Quyền này có thể khiến điện thoại mất nhiều thời gian khởi động hơn và cho phép ứng dụng làm chậm toàn bộ điện thoại do ứng dụng luôn chạy."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"gửi truyền phát hấp dẫn người xem"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho máy tính bảng bị chậm hoặc không ổn định do khiến máy tính bảng sử dụng quá nhiều bộ nhớ."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Cho phép ứng dụng gửi nội dung truyền phát hấp dẫn người xem. Nội dung này sẽ vẫn còn sau khi quá trình truyền phát kết thúc. Việc sử dụng quá mức có thể làm cho điện thoại bị chậm hoặc không ổn định do khiến điện thoại sử dụng quá nhiều bộ nhớ."</string>
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Cho phép ứng dụng quan sát các điều kiện mạng. Không bao giờ cần cho ứng dụng thông thường."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"thay đổi hiệu chỉnh thiết bị đầu vào"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Cho phép ứng dụng sửa đổi các thông số hiệu chỉnh của màn hình cảm ứng. Không cần cho ứng dụng thông thường."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"truy cập chứng chỉ DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Cho phép ứng dụng cung cấp và sử dụng chứng chỉ DRM. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -1149,7 +1151,7 @@
     <string name="webpage_unresponsive" msgid="3272758351138122503">"Trang không phản hồi.\n\nBạn có muốn đóng trang không?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"Đã chuyển hướng ứng dụng"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện đang chạy."</string>
-    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> được khởi chạy trước tiên."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> được chạy trước tiên."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Tỷ lệ"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"Luôn hiển thị"</string>
     <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Bật lại chế độ này trong cài đặt Hệ thống &gt; Ứng dụng &gt; Đã tải xuống."</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Cho phép ứng dụng truy cập bộ nhớ an toàn khóa"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Kiểm soát việc hiển thị và ẩn tính năng bảo vệ phím"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Cho phép ứng dụng kiểm soát tính năng bảo vệ phím."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Cho phép ứng dụng quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Liên kết với một dịch vụ của đại lý đáng tin cậy"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tương tác với hệ thống khôi phục và bản cập nhật"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Cho phép ứng dụng tương tác với hệ thống khôi phục và bản cập nhật hệ thống."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Chạm hai lần để kiểm soát thu phóng"</string>
@@ -1430,7 +1436,7 @@
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"Chọn một ứng dụng"</string>
-    <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Không thể khởi chạy <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Không thể chạy <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Chia sẻ với"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Chia sẻ với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Tay trượt. Chạm &amp; giữ."</string>
@@ -1479,7 +1485,7 @@
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Chia sẻ với"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
     <string name="sending" msgid="3245653681008218030">"Đang gửi…"</string>
-    <string name="launchBrowserDefault" msgid="2057951947297614725">"Khởi chạy trình duyệt?"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Chạy trình duyệt?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Chấp nhận cuộc gọi?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Luôn chọn"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Chỉ một lần"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 902533a..acb4a81 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允许应用监听网络状况的观测信息。普通应用绝不需要此权限。"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"更改输入设备校准设置"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允许应用修改触摸屏的校准参数。普通应用绝不需要此权限。"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"访问DRM证书"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允许应用配置和使用DRM证书。普通应用绝不需要此权限。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允许应用访问密钥保护安全存储空间。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制是显示还是隐藏锁屏"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允许应用控制锁屏。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"检测信任状态的变化。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允许应用检测信任状态的变化。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"绑定至信任的代理服务"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允许应用绑定至信任的代理服务。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"与更新和恢复系统互动"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允许应用与恢复系统和系统更新互动。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"触摸两次可进行缩放控制"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d189060..deb5a11 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允許應用程式監聽對網絡狀況的觀察 (不建議一般應用程式使用)。"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"變更輸入裝置校正設定"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允許應用程式修改觸控式螢幕的校正參數,而一般應用程式並不需要作出類似修改。"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"存取 DRM 憑證"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允許應用程式準備和使用 DRM 憑證,但一般應用程式並不需要使用。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解鎖密碼所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監控屏幕解鎖嘗試次數"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允許應用程式存取 Keyguard 安全儲存空間。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制顯示或隱藏鍵盤鎖"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允許應用程式控制鍵盤鎖。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"聽取信任狀態變更。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允許應用程式聽取信任狀態的變更。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"繫結至信任的代理程式服務"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和復原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與復原系統和系統更新互動。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index dcdfd28..b058860 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允許應用程式監聽網路狀況觀察資訊 (一般應用程式並不需要)。"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"變更輸入裝置校正設定"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允許應用程式修改觸控螢幕的校正參數 (一般應用程式並不需要)。"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"存取 DRM 憑證"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允許應用程式佈建及使用 DRM 憑證 (一般應用程式並不需要)。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"允許應用程式存取 Keyguard 安全儲存空間。"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"控制鍵盤鎖的顯示和隱藏"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"允許應用程式控制鍵盤鎖。"</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"接聽信任狀態變更。"</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"允許應用程式接聽信任狀態變更。"</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"繫結至信任的代理程式服務"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"與更新和還原系統互動"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"允許應用程式與還原系統及系統更新互動。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"輕觸兩下即可控制縮放"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1b12907..aacd3c1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -687,6 +687,8 @@
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ivumela uhlelo lokusebenza ukuthi lulalele okubonwa kuzimo zenethiwekhi. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"guqula ukulinganisa kokufaka kwedivayisi"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ivumela uhlelo lokusebenza ukuthi lushintshe imingcele yokulinganisa yesikrini esithintwayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"finyelela izitifiketi ze-DRM"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ivumela uhlelo lokusebenza ekunikezweni nokusetshenziswa kwezitifiketi ze-DRM. Akufanele kudingeke kuzinhlelo zokusebenza ezivamile."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
@@ -796,7 +798,7 @@
     <string name="imProtocolYahoo" msgid="8271439408469021273">"i-Yahoo"</string>
     <string name="imProtocolSkype" msgid="9019296744622832951">"i-Skype"</string>
     <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string>
-    <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Ama-Hangout"</string>
+    <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string>
     <string name="imProtocolIcq" msgid="1574870433606517315">"i-ICQ"</string>
     <string name="imProtocolJabber" msgid="2279917630875771722">"i-Jabber"</string>
     <string name="imProtocolNetMeeting" msgid="8287625655986827971">"Umhlangano we-Net"</string>
@@ -1319,6 +1321,10 @@
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ivumela uhlelo lokusebenza ukuthi lufinyelele kusitoreji esiqashwa ngesikhiya esiphephile."</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Lawula ukubonisa nokufihla ukhiye wokuqapha"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"Ivumela uhlelo lokusebenza ukuthi lulawule ukhiye wokuqapha."</string>
+    <string name="permlab_trust_listener" msgid="1765718054003704476">"Lalela izinguquko zesimo sokuthemba."</string>
+    <string name="permdesc_trust_listener" msgid="8233895334214716864">"Ivumela uhlelo lokusebenza ukuthi lilalelele izinguquko kusimo sethemba."</string>
+    <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bophezela kusevisi yomenzeli wethemba"</string>
+    <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ivumela uhlelo lokusebenza ukuthi libophezeleke kusevisi yomenzeli wethemba."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Ixhumana nesibuyekezo nesistimu yokutakula"</string>
     <string name="permdesc_recovery" msgid="8511774533266359571">"Ivumela uhlelo lokusebenza ukuthi lixhumane nesistimu yokutakula nezibuyekezo zesistimu."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Thinta kabili ukulawula ukusondeza"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index df7cde7..46cb9b2 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -650,6 +650,8 @@
         <!-- Default ActivityChooserView style. -->
         <attr name="activityChooserViewStyle" format="reference" />
 
+        <attr name="toolbarStyle" format="reference" />
+
         <!-- Fast scroller styles -->
         <eat-comment />
 
@@ -677,8 +679,6 @@
         <!-- Action bar styles   -->
         <!-- =================== -->
         <eat-comment />
-        <!-- Theme override for the Action Bar -->
-        <attr name="actionBarTheme" format="reference" />
         <!-- Default style for tabs within an action bar -->
         <attr name="actionBarTabStyle" format="reference" />
         <attr name="actionBarTabBarStyle" format="reference" />
@@ -691,6 +691,10 @@
              buttons. actionBarStyle is still used for the primary
              bar. -->
         <attr name="actionBarSplitStyle" format="reference" />
+        <!-- Reference to a theme that should be used to inflate the
+             action bar. This will be inherited by any widget inflated
+             into the action bar. -->
+        <attr name="actionBarTheme" format="reference" />
         <!-- Reference to a theme that should be used to inflate widgets
              and layouts destined for the action bar. Most of the time
              this will be a reference to the current theme, but when
@@ -913,8 +917,14 @@
         <!-- ============= -->
         <!-- Color palette -->
         <!-- ============= -->
+        <attr name="colorPrimaryDark" format="color" />
+        <attr name="colorPrimary" format="color" />
+        <attr name="colorPrimaryLight" format="color" />
+        <attr name="colorAccent" format="color" />
+
         <attr name="colorControlNormal" format="color" />
         <attr name="colorControlActivated" format="color" />
+
         <attr name="colorButtonNormal" format="color" />
         <attr name="colorButtonPressed" format="color" />
         <attr name="colorButtonNormalColored" format="color" />
@@ -1677,6 +1687,7 @@
              that is, when in portrait. Can be either an absolute dimension
              or a fraction of the screen size in that dimension. -->
         <attr name="windowFixedHeightMajor" format="dimension|fraction" />
+        <attr name="windowOutsetBottom" format="dimension" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -4555,6 +4566,7 @@
             <enum name="state_activated" value="8" />
             <enum name="state_window_focused" value="9" />
         </attr>
+        <attr name="versionCode" />
     </declare-styleable>
 
     <!-- Define the virtual size of the drawing surface paths will draw to. -->
@@ -4889,6 +4901,24 @@
         </attr>
     </declare-styleable>
 
+    <!-- Use <code>slide</code>as the root tag of the XML resource that
+         describes a {@link android.transition.Slide Slide} transition.
+         The attributes of the {@link android.R.styleable#Transition Transition}
+         resource are available in addition to the specific attributes of Slide
+         described here. -->
+    <declare-styleable name="Slide">
+        <attr name="slideEdge">
+            <!-- Slide to and from the bottom edge of the Scene. -->
+            <enum name="left" value="0" />
+            <!-- Slide to and from the bottom edge of the Scene. -->
+            <enum name="top" value="1" />
+            <!-- Slide to and from the bottom edge of the Scene. -->
+            <enum name="right" value="2" />
+            <!-- Slide to and from the bottom edge of the Scene. -->
+            <enum name="bottom" value="3" />
+        </attr>
+    </declare-styleable>
+
     <!-- Use <code>target</code> as the root tag of the XML resource that
      describes a {@link android.transition.Transition#addTarget(int)
      targetId} of a transition. There can be one or more targets inside
@@ -5925,6 +5955,16 @@
         <attr name="settingsActivity" />
     </declare-styleable>
 
+    <!-- Use <code>trust_agent</code> as the root tag of the XML resource that
+         describes an {@link android.service.trust.TrustAgentService}, which is
+         referenced from its {@link android.service.trust.TrustAgentService#TRUST_AGENT_META_DATA}
+         meta-data entry.  Described here are the attributes that can be included in that tag. -->
+    <declare-styleable name="TrustAgent">
+        <!-- Component name of an activity that allows the user to modify
+             the settings for this TrustAgent. -->
+        <attr name="settingsActivity" />
+    </declare-styleable>
+
     <!-- =============================== -->
     <!-- Accounts package class attributes -->
     <!-- =============================== -->
@@ -6033,16 +6073,16 @@
     <eat-comment />
     <declare-styleable name="GlowPadView">
         <!-- Reference to an array resource that be shown as targets around a circle. -->
-        <attr name="targetDrawables"/>
+        <attr name="targetDrawables" format="reference" />
 
         <!-- Reference to an array resource that be used as description for the targets around the circle. -->
-        <attr name="targetDescriptions"/>
+        <attr name="targetDescriptions" format="reference" />
 
         <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
-        <attr name="directionDescriptions"/>
+        <attr name="directionDescriptions" format="reference" />
 
         <!-- Sets a drawable as the center. -->
-        <attr name="handleDrawable"/>
+        <attr name="handleDrawable" format="reference" />
 
         <!-- Drawable to use for wave ripple animation. -->
         <attr name="outerRingDrawable" format="reference"/>
@@ -6054,22 +6094,22 @@
         <attr name="innerRadius"/>
 
         <!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
-        <attr name="outerRadius"/>
+        <attr name="outerRadius" format="dimension" />
 
         <!-- Radius of glow under finger. -->
         <attr name="glowRadius" format="dimension" />
 
         <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
-        <attr name="vibrationDuration"/>
+        <attr name="vibrationDuration" format="integer" />
 
         <!-- How close we need to be before snapping to a target. -->
-        <attr name="snapMargin"/>
+        <attr name="snapMargin" format="dimension" />
 
         <!-- Number of waves/chevrons to show in animation. -->
-        <attr name="feedbackCount"/>
+        <attr name="feedbackCount" format="integer" />
 
         <!-- Used when the handle shouldn't wait to be hit before following the finger -->
-        <attr name="alwaysTrackFinger"/>
+        <attr name="alwaysTrackFinger" format="boolean" />
 
         <!-- Location along the circle of the first item, in degrees.-->
         <attr name="firstItemOffset" format="float" />
@@ -6086,45 +6126,6 @@
     </declare-styleable>
 
     <!-- =============================== -->
-    <!-- MultiWaveView class attributes -->
-    <!-- =============================== -->
-    <eat-comment />
-    <declare-styleable name="MultiWaveView">
-        <!-- Reference to an array resource that be shown as targets around a circle. -->
-        <attr name="targetDrawables" format="reference"/>
-
-        <!-- Reference to an array resource that be used as description for the targets around the circle. -->
-        <attr name="targetDescriptions" format="reference"/>
-
-        <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
-        <attr name="directionDescriptions" format="reference"/>
-
-        <!-- Sets a drawable as the drag center. -->
-        <attr name="handleDrawable" format="reference" />
-
-        <!-- Drawables to use for chevron animations. May be null. -->
-        <attr name="chevronDrawables" format="reference"/>
-
-        <!-- Drawable to use for wave ripple animation. -->
-        <attr name="waveDrawable" format="reference" />
-
-        <!-- Outer radius of target circle. Icons will be drawn on this circle. -->
-        <attr name="outerRadius" format="dimension" />
-
-        <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
-        <attr name="vibrationDuration" format="integer"/>
-
-        <!-- How close we need to be before snapping to a target. -->
-        <attr name="snapMargin" format="dimension" />
-
-        <!-- Number of waves/chevrons to show in animation. -->
-        <attr name="feedbackCount" format="integer" />
-
-        <!-- Used when the handle shouldn't wait to be hit before following the finger -->
-        <attr name="alwaysTrackFinger" format="boolean" />
-    </declare-styleable>
-
-    <!-- =============================== -->
     <!-- SizeAdaptiveLayout class attributes -->
     <!-- =============================== -->
     <eat-comment />
@@ -6167,6 +6168,8 @@
         <!-- Aspect to use when drawing LockPatternView. Choices are "square"(default), "lock_width"
              or "lock_height" -->
         <attr name="aspect" format="string" />
+        <!-- Color to use when drawing LockPatternView paths. -->
+        <attr name="pathColor" format="color|reference" />
     </declare-styleable>
 
     <!-- Use <code>recognition-service</code> as the root tag of the XML resource that
@@ -6262,10 +6265,6 @@
         <attr name="inputType" />
     </declare-styleable>
 
-    <declare-styleable name="ActionBar_LayoutParams">
-        <attr name="layout_gravity" />
-    </declare-styleable>
-
     <declare-styleable name="Switch">
         <!-- Drawable to use as the "thumb" that switches back and forth. -->
         <attr name="thumb" />
@@ -6474,4 +6473,25 @@
         <attr name="textView" format="reference" />
     </declare-styleable>
 
+    <declare-styleable name="Toolbar">
+        <attr name="titleTextAppearance" format="reference" />
+        <attr name="subtitleTextAppearance" format="reference" />
+        <attr name="title" />
+        <attr name="subtitle" />
+        <attr name="gravity" />
+        <attr name="titleMargins" format="dimension" />
+        <attr name="titleMarginStart" format="dimension" />
+        <attr name="titleMarginEnd" format="dimension" />
+        <attr name="titleMarginTop" format="dimension" />
+        <attr name="titleMarginBottom" format="dimension" />
+    </declare-styleable>
+
+    <declare-styleable name="Toolbar_LayoutParams">
+        <attr name="layout_gravity" />
+    </declare-styleable>
+
+    <declare-styleable name="ActionBar_LayoutParams">
+        <attr name="layout_gravity" />
+    </declare-styleable>
+
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 39b8a6b..b14453a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -866,6 +866,18 @@
     <!-- The name of the logical parent of the activity as it appears in the manifest. -->
     <attr name="parentActivityName" format="string" />
 
+    <!-- Define an activity that will persist across reboots. If such an activity is in the
+         Recents list when the device is shut off it will appear in the Recents list when
+         the device is next powered on. To be persisted all activities in the task from the
+         root activity up to the last activity before a <em>break</em> must be declared with
+         the persistable attribute. A <em>break</em> is the first activity after the root
+         started with Intent.FLAG_CLEAR_TASK_WHEN_RESET.
+
+         <p>Activities that are declared with the persistable attribute will be provided with a
+         forced-persistable Bundle in onCreate() and onSavedInstanceState(), and must only
+         be passed a persistable Bundle in their Intent.extras. -->
+    <attr name="persistable" format="boolean" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -1528,6 +1540,7 @@
         <!-- @hide This broacast receiver will only receive broadcasts for the
              primary user.  Can only be used with receivers. -->
         <attr name="primaryUserOnly" format="boolean" />
+        <attr name="persistable" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index d10f7c0..ebe4a49 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -16,16 +16,14 @@
 
 <resources>
     <color name="background_quantum_dark">@color/black</color>
-    <color name="background_quantum_light">@color/quantum_grey_50</color>
-    <color name="secondary_background_quantum_dark">@color/quantum_grey_700</color>
-    <color name="secondary_background_quantum_light">@color/quantum_grey_100</color>
+    <color name="background_quantum_light">@color/white</color>
 
     <color name="bright_foreground_quantum_dark">@color/background_quantum_light</color>
     <color name="bright_foreground_quantum_light">@color/background_quantum_dark</color>
     <!-- TODO: This is 50% alpha black -->
     <color name="bright_foreground_disabled_quantum_dark">#80000000</color>
-    <!-- TODO: This is 50% alpha grey_50 -->
-    <color name="bright_foreground_disabled_quantum_light">#80fafafa</color>
+    <!-- TODO: This is 50% alpha white -->
+    <color name="bright_foreground_disabled_quantum_light">#80ffffff</color>
     <color name="bright_foreground_inverse_quantum_dark">@color/bright_foreground_quantum_light</color>
     <color name="bright_foreground_inverse_quantum_light">@color/bright_foreground_quantum_dark</color>
 
@@ -34,41 +32,13 @@
     <color name="dim_foreground_disabled_quantum_dark">#80bebebe</color>
     <color name="dim_foreground_disabled_quantum_light">#80323232</color>
 
-    <!-- TODO: These should be theme attributes. -->
-    <color name="control_normal_foreground_quantum_light">@color/secondary_text_quantum_light</color>
-    <color name="control_activated_foreground_quantum_light">@color/quantum_teal_700</color>
-
-    <!-- TODO: These should be theme attributes. -->
-    <color name="control_normal_foreground_quantum_dark">@color/secondary_text_quantum_dark</color>
-    <color name="control_activated_foreground_quantum_dark">@color/quantum_lime_A200</color>
-
-    <!-- TODO: These should be theme attributes. -->
-    <color name="btn_default_normal_quantum_light">@color/quantum_grey_300</color>
-    <color name="btn_default_pressed_quantum_light">@color/quantum_grey_500</color>
-
-    <!-- TODO: These should be theme attributes. -->
-    <color name="btn_default_normal_quantum_dark">@color/quantum_grey_700</color>
-    <color name="btn_default_pressed_quantum_dark">@color/quantum_grey_500</color>
-
     <color name="hint_foreground_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
     <color name="hint_foreground_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
-    <!-- TODO: This is 40% alpha lime_A200 -->
-    <color name="highlighted_text_quantum_dark">#66eeff41</color>
-    <!-- TODO: This is 40% alpha teal_700 -->
+    <!-- TODO: This is 40% alpha teal_A200 -->
+    <color name="highlighted_text_quantum_dark">#660097a7</color>
+    <!-- TODO: This is 40% alpha teal_A200 -->
     <color name="highlighted_text_quantum_light">#660097a7</color>
 
-    <!-- TODO: These should all be pushed into a TimePicker widget style. -->
-    <color name="timepicker_default_background_quantum_dark">@color/background_quantum_dark</color>
-    <color name="timepicker_default_background_quantum_light">@color/background_quantum_light</color>
-    <color name="timepicker_default_text_color_quantum_dark">@color/bright_foreground_quantum_dark</color>
-    <color name="timepicker_default_text_color_quantum_light">@color/bright_foreground_quantum_light</color>
-    <color name="timepicker_default_disabled_color_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
-    <color name="timepicker_default_disabled_color_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
-    <color name="timepicker_default_ampm_selected_background_color_quantum_dark">@color/control_activated_foreground_quantum_dark</color>
-    <color name="timepicker_default_ampm_selected_background_color_quantum_light">@color/control_activated_foreground_quantum_light</color>
-    <color name="timepicker_default_ampm_unselected_background_color_quantum_dark">@color/transparent</color>
-    <color name="timepicker_default_ampm_unselected_background_color_quantum_light">@color/white</color>
-
     <!-- Primary & accent colors -->
 
     <color name="quantum_red_100">#fff4c7c3</color>
@@ -155,10 +125,4 @@
     <color name="primary_text_quantum_dark">#deffffff</color>
     <color name="secondary_text_quantum_dark">#8affffff</color>
     <color name="tertiary_text_quantum_dark">#4dffffff</color>
-
-    <!-- "Theme" colors to be replaced by attrs when available -->
-    <color name="theme_color_100">@color/quantum_teal_100</color>
-    <color name="theme_color_300">@color/quantum_teal_300</color>
-    <color name="theme_color_500">@color/quantum_teal_500</color>
-    <color name="theme_color_700">@color/quantum_teal_700</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4656f32..fbe066a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -467,6 +467,7 @@
              1  UI_MODE_TYPE_NORMAL
              4  UI_MODE_TYPE_TELEVISION
              5  UI_MODE_TYPE_APPLIANCE
+             6  UI_MODE_TYPE_WATCH
          Any other values will have surprising consequences. -->
     <integer name="config_defaultUiModeType">1</integer>
 
@@ -950,7 +951,7 @@
     <!-- Max space (in MB) allocated to DownloadManager to store the downloaded
          files if they are to be stored in DownloadManager's data dir,
          which typically is /data/data/com.android.providers.downloads/files -->
-    <integer name="config_downloadDataDirSize">100</integer>
+    <integer name="config_downloadDataDirSize">200</integer>
 
     <!-- Max number of downloads allowed to proceed concurrently -->
     <integer name="config_MaxConcurrentDownloadsAllowed">5</integer>
@@ -1339,6 +1340,12 @@
          Example: com.google.android.myapp/.resolver.MyResolverActivity  -->
     <string name="config_customResolverActivity"></string>
 
+    <!-- Name of the activity that prompts the user to reject, accept, or whitelist
+         an adb host's public key, when an unwhitelisted host connects to the local adbd.
+         Can be customized for other product types -->
+    <string name="config_customAdbPublicKeyActivity"
+            >com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>
+
     <!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
     <string name="config_appsAuthorizedForSharedAccounts">;com.android.settings;</string>
 
@@ -1421,4 +1428,5 @@
          1 - The device DOES have a permanent menu key; ignore autodetection.
          2 - The device DOES NOT have a permanent menu key; ignore autodetection. -->
     <integer name="config_overrideHasPermanentMenuKey">0</integer>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d49980f..acdf926 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2131,6 +2131,7 @@
   <public type="attr" name="trimPathEnd" />
   <public type="attr" name="trimPathOffset" />
   <public type="attr" name="strokeLineCap" />
+  <public type="attr" name="strokeLineJoin" />
   <public type="attr" name="clipToPath" />
   <public type="attr" name="animate" />
   <public type="attr" name="limitTo" />
@@ -2142,6 +2143,11 @@
   <public type="attr" name="colorButtonPressed" />
   <public type="attr" name="colorButtonNormalColored" />
   <public type="attr" name="colorButtonPressedColored" />
+  <public type="attr" name="persistable" />
+  <public type="attr" name="titleTextAppearance" />
+  <public type="attr" name="subtitleTextAppearance" />
+  <public type="attr" name="slideEdge" />
+  <public type="attr" name="actionBarTheme" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2181,9 +2187,13 @@
   <public type="style" name="TextAppearance.Quantum.Widget" />
   <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Menu" />
   <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" />
+  <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" />
   <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Title" />
+  <public type="style" name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" />
   <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" />
+  <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" />
   <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Title" />
+  <public type="style" name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" />
   <public type="style" name="TextAppearance.Quantum.Widget.Button" />
   <public type="style" name="TextAppearance.Quantum.Widget.DropDownHint" />
   <public type="style" name="TextAppearance.Quantum.Widget.DropDownItem" />
@@ -2365,4 +2375,6 @@
   <public type="style" name="TextAppearance.Quantum.Caption" />
   <public type="style" name="TextAppearance.Quantum.Menu" />
   <public type="style" name="TextAppearance.Quantum.Button" />
+
+  <public type="style" name="Widget.Holo.Light.Button.Borderless" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0699e8b..4a121d1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1056,6 +1056,12 @@
         a device administrator. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindTvInput">bind to a TV input</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindTvInput">Allows the holder to bind to the top-level
+        interface of a TV input. Should never be needed for normal apps.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_manageDeviceAdmins">add or remove a device admin</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_manageDeviceAdmins">Allows the holder to add or remove active device
@@ -2002,6 +2008,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_setInputCalibration">Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_accessDrmCertificates">access DRM certificates</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_accessDrmCertificates">Allows an application to provision and use DRM certficates. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
@@ -3651,6 +3662,16 @@
     <!-- Description of an application permission that lets it control keyguard. -->
     <string name="permdesc_control_keyguard">Allows an application to control keguard.</string>
 
+    <!-- Title of an application permission that lets it listen to trust state changes. -->
+    <string name="permlab_trust_listener">Listen to trust state changes.</string>
+    <!-- Description of an application permission that lets it listen to trust state changes. -->
+    <string name="permdesc_trust_listener">Allows an application to listen for changes in trust state.</string>
+
+    <!-- Title of an application permission that lets it bind to a trust agent service. -->
+    <string name="permlab_bind_trust_agent_service">Bind to a trust agent service</string>
+    <!-- Description of an application permission that lets it bind to a trust agent service. -->
+    <string name="permdesc_bind_trust_agent_service">Allows an application to bind to a trust agent service.</string>
+
     <!-- Title of an application permission that lets it interact with recovery. -->
     <string name="permlab_recovery">Interact with update and recovery system</string>
     <!-- Description of an application permission that lets it control keyguard. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index be875ff..fc0fccc 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1208,6 +1208,13 @@
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Widget.ActionMode.Subtitle</item>
     </style>
 
+    <style name="Widget.Toolbar">
+        <item name="android:titleTextAppearance">@android:style/TextAppearance.Widget.Toolbar.Title</item>
+        <item name="android:subtitleTextAppearance">@android:style/TextAppearance.Widget.Toolbar.Subtitle</item>
+        <item name="android:minHeight">?android:attr/actionBarSize</item>
+        <item name="android:titleMargins">4dp</item>
+    </style>
+
     <style name="TextAppearance.Widget.ActionBar.Title"
            parent="@android:style/TextAppearance.Medium">
     </style>
@@ -1225,6 +1232,14 @@
         <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
+    <style name="TextAppearance.Widget.Toolbar.Title"
+           parent="@android:style/TextAppearance.Widget.ActionBar.Title">
+    </style>
+
+    <style name="TextAppearance.Widget.Toolbar.Subtitle"
+           parent="@android:style/TextAppearance.Widget.ActionBar.Subtitle">
+    </style>
+
     <style name="Widget.ActionButton">
         <item name="android:background">?android:attr/actionBarItemBackground</item>
         <item name="android:paddingStart">12dip</item>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 512c9b8..629b2b7 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -32,731 +32,271 @@
  -->
 <resources>
     <!-- Widget Styles -->
-    <style name="Widget.DeviceDefault" parent="Widget.Holo" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button" parent="Widget.Holo.Button" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button.Small" parent="Widget.Holo.Button.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Holo.Button.Inset" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Holo.Button.Toggle" >
-
-    </style>
-    <style name="Widget.DeviceDefault.TextView" parent="Widget.Holo.TextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Holo.CheckedTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Holo.AutoCompleteTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CompoundButton.CheckBox" parent="Widget.Holo.CompoundButton.CheckBox" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ListView.DropDown" parent="Widget.Holo.ListView.DropDown" >
-
-    </style>
-    <style name="Widget.DeviceDefault.EditText" parent="Widget.Holo.EditText" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ExpandableListView" parent="Widget.Holo.ExpandableListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.GridView" parent="Widget.Holo.GridView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ImageButton" parent="Widget.Holo.ImageButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ListView" parent="Widget.Holo.ListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.PopupWindow" parent="Widget.Holo.PopupWindow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar" parent="Widget.Holo.ProgressBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Horizontal" parent="Widget.Holo.ProgressBar.Horizontal" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Small" parent="Widget.Holo.ProgressBar.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Small.Title" parent="Widget.Holo.ProgressBar.Small.Title" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Large" parent="Widget.Holo.ProgressBar.Large" >
-
-    </style>
-    <style name="Widget.DeviceDefault.SeekBar" parent="Widget.Holo.SeekBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.RatingBar" parent="Widget.Holo.RatingBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.RatingBar.Indicator" parent="Widget.Holo.RatingBar.Indicator" >
-
-    </style>
-    <style name="Widget.DeviceDefault.RatingBar.Small" parent="Widget.Holo.RatingBar.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CompoundButton.RadioButton" parent="Widget.Holo.CompoundButton.RadioButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ScrollView" parent="Widget.Holo.ScrollView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Holo.HorizontalScrollView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Spinner" parent="Widget.Holo.Spinner" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Holo.CompoundButton.Star" >
-
-    </style>
-    <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Holo.TabWidget" >
-
-    </style>
-    <style name="Widget.DeviceDefault.WebTextView" parent="Widget.Holo.WebTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.WebView" parent="Widget.Holo.WebView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Holo.DropDownItem" >
-
-    </style>
-    <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Holo.DropDownItem.Spinner" >
-
-    </style>
-    <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Holo.TextView.SpinnerItem" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Holo.ListPopupWindow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Holo.PopupMenu" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Holo.ActionButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Holo.ActionButton.Overflow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Holo.ActionButton.TextButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Holo.ActionMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Holo.ActionButton.CloseMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Holo.ActionBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Holo.Button.Borderless" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Tab" parent="Widget.Holo.Tab" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CalendarView" parent="Widget.Holo.CalendarView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.DatePicker" parent="Widget.Holo.DatePicker" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Holo.ActionBar.TabBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Holo.ActionBar.Solid" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Button.Borderless.Small" parent="Widget.Holo.Button.Borderless.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.AbsListView" parent="Widget.Holo.AbsListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Holo.Spinner.DropDown.ActionBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Holo.PopupWindow.ActionMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Holo.CompoundButton.Switch">
-
-    </style>
-    <style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Holo.ExpandableListView.White">
-
-    </style>
-    <style name="Widget.DeviceDefault.FastScroll" parent="Widget.Holo.FastScroll">
-
-    </style>
-    <style name="Widget.DeviceDefault.FragmentBreadCrumbs" parent="Widget.Holo.FragmentBreadCrumbs">
-
-    </style>
-    <style name="Widget.DeviceDefault.Gallery" parent="Widget.Holo.Gallery">
-
-    </style>
-    <style name="Widget.DeviceDefault.GestureOverlayView" parent="Widget.Holo.GestureOverlayView">
-
-    </style>
-    <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Holo.ImageWell">
-
-    </style>
-    <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Holo.KeyboardView">
-
-    </style>
-    <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Holo.ListView.White">
-
-    </style>
-    <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Holo.NumberPicker">
-
-    </style>
-    <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Holo.PreferenceFrameLayout">
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Holo.ProgressBar.Inverse">
-
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Large.Inverse" parent="Widget.Holo.ProgressBar.Large.Inverse">
-
-    </style>
-    <style name="Widget.DeviceDefault.ProgressBar.Small.Inverse" parent="Widget.Holo.ProgressBar.Small.Inverse">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadge.WindowLarge" parent="Widget.Holo.QuickContactBadge.WindowLarge">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadge.WindowMedium" parent="Widget.Holo.QuickContactBadge.WindowMedium">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadge.WindowSmall" parent="Widget.Holo.QuickContactBadge.WindowSmall">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge" parent="Widget.Holo.QuickContactBadgeSmall.WindowLarge">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium" parent="Widget.Holo.QuickContactBadgeSmall.WindowMedium">
-
-    </style>
-    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall" parent="Widget.Holo.QuickContactBadgeSmall.WindowSmall">
-
-    </style>
-    <style name="Widget.DeviceDefault.Spinner.DropDown" parent="Widget.Holo.Spinner.DropDown">
-
-    </style>
-    <style name="Widget.DeviceDefault.StackView" parent="Widget.Holo.StackView">
-
-    </style>
-    <style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Holo.TextSelectHandle">
-
-    </style>
-    <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Holo.TextSuggestionsPopupWindow">
-
-    </style>
-    <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Holo.TextView.ListSeparator">
-
-    </style>
-    <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Holo.TimePicker">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light" parent="Widget.Holo.Light" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Holo.Light.Button" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Holo.Light.Button.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Holo.Light.Button.Inset" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Holo.Light.Button.Toggle" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Holo.Light.TextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Holo.Light.CheckedTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Holo.Light.AutoCompleteTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" parent="Widget.Holo.Light.CompoundButton.CheckBox" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ListView.DropDown" parent="Widget.Holo.Light.ListView.DropDown" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.EditText" parent="Widget.Holo.Light.EditText" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ExpandableListView" parent="Widget.Holo.Light.ExpandableListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.FastScroll" parent="Widget.Holo.Light.FastScroll">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" parent="Widget.Holo.Light.FragmentBreadCrumbs">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Holo.Light.GridView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Holo.Light.ImageButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Holo.Light.ListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Holo.Light.PopupWindow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Holo.Light.ProgressBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Holo.Light.ProgressBar.Horizontal" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Small" parent="Widget.Holo.Light.ProgressBar.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" parent="Widget.Holo.Light.ProgressBar.Small.Title" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Large" parent="Widget.Holo.Light.ProgressBar.Large" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Inverse" parent="Widget.Holo.Light.ProgressBar.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" parent="Widget.Holo.Light.ProgressBar.Small.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" parent="Widget.Holo.Light.ProgressBar.Large.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.SeekBar" parent="Widget.Holo.Light.SeekBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.RatingBar" parent="Widget.Holo.Light.RatingBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.RatingBar.Indicator" parent="Widget.Holo.Light.RatingBar.Indicator" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.RatingBar.Small" parent="Widget.Holo.Light.RatingBar.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" parent="Widget.Holo.Light.CompoundButton.RadioButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ScrollView" parent="Widget.Holo.Light.ScrollView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Holo.Light.HorizontalScrollView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Holo.Light.Spinner" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Holo.Light.CompoundButton.Star" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Holo.Light.TabWidget" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Holo.Light.WebTextView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Holo.Light.WebView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Holo.Light.DropDownItem" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Holo.Light.DropDownItem.Spinner" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Holo.Light.TextView.SpinnerItem" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Holo.Light.ListPopupWindow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Holo.Light.PopupMenu" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Holo.Light.Tab" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.CalendarView" parent="Widget.Holo.Light.CalendarView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Holo.Light.Button.Borderless.Small" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Holo.Light.ActionButton" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Holo.Light.ActionButton.Overflow" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Holo.Light.ActionMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Holo.Light.ActionButton.CloseMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Holo.Light.ActionBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Holo.Light.ActionBar.TabView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Holo.Light.ActionBar.TabText" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Holo.Light.ActionBar.TabBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Holo.Light.ActionBar.Solid" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" parent="Widget.Holo.Light.ActionBar.TabBar.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" parent="Widget.Holo.Light.ActionBar.TabView.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" parent="Widget.Holo.Light.ActionBar.TabText.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ActionMode.Inverse" parent="Widget.Holo.Light.ActionMode.Inverse" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.AbsListView" parent="Widget.Holo.Light.AbsListView" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar" parent="Widget.Holo.Light.Spinner.DropDown.ActionBar" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.PopupWindow.ActionMode" parent="Widget.Holo.Light.PopupWindow.ActionMode" >
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Button.Borderless" parent="Widget.Holo.Light.Button.Borderless">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.DatePicker" parent="Widget.Holo.Light.DatePicker">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ExpandableListView.White" parent="Widget.Holo.Light.ExpandableListView.White">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Gallery" parent="Widget.Holo.Light.Gallery">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.GestureOverlayView" parent="Widget.Holo.Light.GestureOverlayView">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ImageWell" parent="Widget.Holo.Light.ImageWell">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.ListView.White" parent="Widget.Holo.Light.ListView.White">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.NumberPicker" parent="Widget.Holo.Light.NumberPicker">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.Spinner.DropDown" parent="Widget.Holo.Light.Spinner.DropDown">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TextView.ListSeparator" parent="Widget.Holo.Light.TextView.ListSeparator">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Holo.Light.TimePicker">
-
-    </style>
-    <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Holo.Light.TextSuggestionsPopupWindow">
-
-    </style>
+    <style name="Widget.DeviceDefault" parent="Widget.Quantum"/>
+    <style name="Widget.DeviceDefault.Button" parent="Widget.Quantum.Button"/>
+    <style name="Widget.DeviceDefault.Button.Small" parent="Widget.Quantum.Button.Small"/>
+    <style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
+    <style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Quantum.Button.Toggle"/>
+    <style name="Widget.DeviceDefault.TextView" parent="Widget.Quantum.TextView"/>
+    <style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Quantum.CheckedTextView"/>
+    <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Quantum.AutoCompleteTextView"/>
+    <style name="Widget.DeviceDefault.CompoundButton.CheckBox" parent="Widget.Quantum.CompoundButton.CheckBox"/>
+    <style name="Widget.DeviceDefault.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
+    <style name="Widget.DeviceDefault.EditText" parent="Widget.Quantum.EditText"/>
+    <style name="Widget.DeviceDefault.ExpandableListView" parent="Widget.Quantum.ExpandableListView"/>
+    <style name="Widget.DeviceDefault.GridView" parent="Widget.Quantum.GridView"/>
+    <style name="Widget.DeviceDefault.ImageButton" parent="Widget.Quantum.ImageButton"/>
+    <style name="Widget.DeviceDefault.ListView" parent="Widget.Quantum.ListView"/>
+    <style name="Widget.DeviceDefault.PopupWindow" parent="Widget.Quantum.PopupWindow"/>
+    <style name="Widget.DeviceDefault.ProgressBar" parent="Widget.Quantum.ProgressBar"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Horizontal" parent="Widget.Quantum.ProgressBar.Horizontal"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Small" parent="Widget.Quantum.ProgressBar.Small"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Small.Title" parent="Widget.Quantum.ProgressBar.Small.Title"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Large" parent="Widget.Quantum.ProgressBar.Large"/>
+    <style name="Widget.DeviceDefault.SeekBar" parent="Widget.Quantum.SeekBar"/>
+    <style name="Widget.DeviceDefault.RatingBar" parent="Widget.Quantum.RatingBar"/>
+    <style name="Widget.DeviceDefault.RatingBar.Indicator" parent="Widget.Quantum.RatingBar.Indicator"/>
+    <style name="Widget.DeviceDefault.RatingBar.Small" parent="Widget.Quantum.RatingBar.Small"/>
+    <style name="Widget.DeviceDefault.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
+    <style name="Widget.DeviceDefault.ScrollView" parent="Widget.Quantum.ScrollView"/>
+    <style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Quantum.HorizontalScrollView"/>
+    <style name="Widget.DeviceDefault.Spinner" parent="Widget.Quantum.Spinner"/>
+    <style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
+    <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Quantum.TabWidget"/>
+    <style name="Widget.DeviceDefault.WebTextView" parent="Widget.Quantum.WebTextView"/>
+    <style name="Widget.DeviceDefault.WebView" parent="Widget.Quantum.WebView"/>
+    <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Quantum.DropDownItem"/>
+    <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Quantum.DropDownItem.Spinner"/>
+    <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Quantum.TextView.SpinnerItem"/>
+    <style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Quantum.ListPopupWindow"/>
+    <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Quantum.PopupMenu"/>
+    <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Quantum.ActionButton"/>
+    <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
+    <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Quantum.ActionButton.TextButton"/>
+    <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Quantum.ActionMode"/>
+    <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Quantum.ActionButton.CloseMode"/>
+    <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Quantum.ActionBar"/>
+    <style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
+    <style name="Widget.DeviceDefault.Tab" parent="Widget.Quantum.Tab"/>
+    <style name="Widget.DeviceDefault.CalendarView" parent="Widget.Quantum.CalendarView"/>
+    <style name="Widget.DeviceDefault.DatePicker" parent="Widget.Quantum.DatePicker"/>
+    <style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView"/>
+    <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Quantum.ActionBar.TabText"/>
+    <style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Quantum.ActionBar.TabBar"/>
+    <style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Quantum.ActionBar.Solid"/>
+    <style name="Widget.DeviceDefault.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
+    <style name="Widget.DeviceDefault.AbsListView" parent="Widget.Quantum.AbsListView"/>
+    <style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Spinner.DropDown.ActionBar"/>
+    <style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Quantum.PopupWindow.ActionMode"/>
+    <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch"/>
+    <style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Quantum.ExpandableListView.White"/>
+    <style name="Widget.DeviceDefault.FastScroll" parent="Widget.Quantum.FastScroll"/>
+    <style name="Widget.DeviceDefault.FragmentBreadCrumbs" parent="Widget.Quantum.FragmentBreadCrumbs"/>
+    <style name="Widget.DeviceDefault.Gallery" parent="Widget.Quantum.Gallery"/>
+    <style name="Widget.DeviceDefault.GestureOverlayView" parent="Widget.Quantum.GestureOverlayView"/>
+    <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Quantum.ImageWell"/>
+    <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Quantum.KeyboardView"/>
+    <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Quantum.ListView.White"/>
+    <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
+    <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Quantum.PreferenceFrameLayout"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Quantum.ProgressBar.Inverse"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
+    <style name="Widget.DeviceDefault.ProgressBar.Small.Inverse" parent="Widget.Quantum.ProgressBar.Small.Inverse"/>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowLarge" parent="Widget.Quantum.QuickContactBadge.WindowLarge"/>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowMedium" parent="Widget.Quantum.QuickContactBadge.WindowMedium"/>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowSmall" parent="Widget.Quantum.QuickContactBadge.WindowSmall"/>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge" parent="Widget.Quantum.QuickContactBadgeSmall.WindowLarge"/>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium" parent="Widget.Quantum.QuickContactBadgeSmall.WindowMedium"/>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall" parent="Widget.Quantum.QuickContactBadgeSmall.WindowSmall"/>
+    <style name="Widget.DeviceDefault.Spinner.DropDown" parent="Widget.Quantum.Spinner.DropDown"/>
+    <style name="Widget.DeviceDefault.StackView" parent="Widget.Quantum.StackView"/>
+    <style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Quantum.TextSelectHandle"/>
+    <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Quantum.TextSuggestionsPopupWindow"/>
+    <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Quantum.TextView.ListSeparator"/>
+    <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Quantum.TimePicker"/>
+    <style name="Widget.DeviceDefault.Light" parent="Widget.Quantum.Light"/>
+    <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Quantum.Light.Button"/>
+    <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Quantum.Light.Button.Small"/>
+    <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Quantum.Light.Button.Inset"/>
+    <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Quantum.Light.Button.Toggle"/>
+    <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Quantum.Light.TextView"/>
+    <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Quantum.Light.CheckedTextView"/>
+    <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Quantum.Light.AutoCompleteTextView"/>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" parent="Widget.Quantum.Light.CompoundButton.CheckBox"/>
+    <style name="Widget.DeviceDefault.Light.ListView.DropDown" parent="Widget.Quantum.Light.ListView.DropDown"/>
+    <style name="Widget.DeviceDefault.Light.EditText" parent="Widget.Quantum.Light.EditText"/>
+    <style name="Widget.DeviceDefault.Light.ExpandableListView" parent="Widget.Quantum.Light.ExpandableListView"/>
+    <style name="Widget.DeviceDefault.Light.FastScroll" parent="Widget.Quantum.Light.FastScroll"/>
+    <style name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" parent="Widget.Quantum.Light.FragmentBreadCrumbs"/>
+    <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Quantum.Light.GridView"/>
+    <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Quantum.Light.ImageButton"/>
+    <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Quantum.Light.ListView"/>
+    <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Quantum.Light.PopupWindow"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Quantum.Light.ProgressBar"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Quantum.Light.ProgressBar.Horizontal"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small" parent="Widget.Quantum.Light.ProgressBar.Small"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" parent="Widget.Quantum.Light.ProgressBar.Small.Title"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Large" parent="Widget.Quantum.Light.ProgressBar.Large"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Inverse" parent="Widget.Quantum.Light.ProgressBar.Inverse"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" parent="Widget.Quantum.Light.ProgressBar.Small.Inverse"/>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.Light.ProgressBar.Large.Inverse"/>
+    <style name="Widget.DeviceDefault.Light.SeekBar" parent="Widget.Quantum.Light.SeekBar"/>
+    <style name="Widget.DeviceDefault.Light.RatingBar" parent="Widget.Quantum.Light.RatingBar"/>
+    <style name="Widget.DeviceDefault.Light.RatingBar.Indicator" parent="Widget.Quantum.Light.RatingBar.Indicator"/>
+    <style name="Widget.DeviceDefault.Light.RatingBar.Small" parent="Widget.Quantum.Light.RatingBar.Small"/>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" parent="Widget.Quantum.Light.CompoundButton.RadioButton"/>
+    <style name="Widget.DeviceDefault.Light.ScrollView" parent="Widget.Quantum.Light.ScrollView"/>
+    <style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Quantum.Light.HorizontalScrollView"/>
+    <style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Quantum.Light.Spinner"/>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Quantum.Light.CompoundButton.Star"/>
+    <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Quantum.Light.TabWidget"/>
+    <style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Quantum.Light.WebTextView"/>
+    <style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Quantum.Light.WebView"/>
+    <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Quantum.Light.DropDownItem"/>
+    <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Quantum.Light.DropDownItem.Spinner"/>
+    <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Quantum.Light.TextView.SpinnerItem"/>
+    <style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Quantum.Light.ListPopupWindow"/>
+    <style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Quantum.Light.PopupMenu"/>
+    <style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Quantum.Light.Tab"/>
+    <style name="Widget.DeviceDefault.Light.CalendarView" parent="Widget.Quantum.Light.CalendarView"/>
+    <style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Quantum.Light.Button.Borderless.Small"/>
+    <style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Quantum.Light.ActionButton"/>
+    <style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Quantum.Light.ActionButton.Overflow"/>
+    <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Quantum.Light.ActionMode"/>
+    <style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Quantum.Light.ActionButton.CloseMode"/>
+    <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Quantum.Light.ActionBar"/>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Quantum.Light.ActionBar.TabView"/>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Quantum.Light.ActionBar.TabText"/>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Quantum.Light.ActionBar.TabBar"/>
+    <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Quantum.Light.ActionBar.Solid"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" parent="Widget.Holo.Light.ActionBar.TabBar.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" parent="Widget.Holo.Light.ActionBar.TabView.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" parent="Widget.Holo.Light.ActionBar.TabText.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="Widget.DeviceDefault.Light.ActionMode.Inverse" parent="Widget.Holo.Light.ActionMode.Inverse"/>
+    <style name="Widget.DeviceDefault.Light.AbsListView" parent="Widget.Quantum.Light.AbsListView"/>
+    <style name="Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Light.Spinner.DropDown.ActionBar"/>
+    <style name="Widget.DeviceDefault.Light.PopupWindow.ActionMode" parent="Widget.Quantum.Light.PopupWindow.ActionMode"/>
+    <style name="Widget.DeviceDefault.Light.Button.Borderless" parent="Widget.Quantum.Light.Button.Borderless"/>
+    <style name="Widget.DeviceDefault.Light.DatePicker" parent="Widget.Quantum.Light.DatePicker"/>
+    <style name="Widget.DeviceDefault.Light.ExpandableListView.White" parent="Widget.Quantum.Light.ExpandableListView.White"/>
+    <style name="Widget.DeviceDefault.Light.Gallery" parent="Widget.Quantum.Light.Gallery"/>
+    <style name="Widget.DeviceDefault.Light.GestureOverlayView" parent="Widget.Quantum.Light.GestureOverlayView"/>
+    <style name="Widget.DeviceDefault.Light.ImageWell" parent="Widget.Quantum.Light.ImageWell"/>
+    <style name="Widget.DeviceDefault.Light.ListView.White" parent="Widget.Quantum.Light.ListView.White"/>
+    <style name="Widget.DeviceDefault.Light.NumberPicker" parent="Widget.Quantum.Light.NumberPicker"/>
+    <style name="Widget.DeviceDefault.Light.Spinner.DropDown" parent="Widget.Quantum.Light.Spinner.DropDown"/>
+    <style name="Widget.DeviceDefault.Light.TextView.ListSeparator" parent="Widget.Quantum.Light.TextView.ListSeparator"/>
+    <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Quantum.Light.TimePicker"/>
+    <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Quantum.Light.TextSuggestionsPopupWindow"/>
 
 
     <!-- Text Appearance Styles -->
-    <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Holo" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Holo.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Large" parent="TextAppearance.Holo.Large" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Large.Inverse" parent="TextAppearance.Holo.Large.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Medium" parent="TextAppearance.Holo.Medium" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Medium.Inverse" parent="TextAppearance.Holo.Medium.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Small" parent="TextAppearance.Holo.Small" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Holo.Small.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Holo.SearchResult.Title" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Holo.SearchResult.Subtitle" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Holo.Widget" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Holo.Widget.Button" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Holo.Widget.IconMenu.Item" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.TabWidget" parent="TextAppearance.Holo.Widget.TabWidget" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.TextView" parent="TextAppearance.Holo.Widget.TextView" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" parent="TextAppearance.Holo.Widget.TextView.PopupMenu" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.DropDownHint" parent="TextAppearance.Holo.Widget.DropDownHint" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.DropDownItem" parent="TextAppearance.Holo.Widget.DropDownItem" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" parent="TextAppearance.Holo.Widget.TextView.SpinnerItem" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Holo.Widget.EditText" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Holo.Widget.PopupMenu" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Widget.PopupMenu.Large" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Widget.PopupMenu.Small" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Holo.Widget.ActionBar.Title" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Holo.Widget.ActionMode.Title" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Holo.WindowTitle" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Holo.DialogWindowTitle" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Holo.Widget.ActionBar.Menu" >
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Holo.Light">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Holo.Light.Inverse">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Holo.Light.Large">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Holo.Light.Large.Inverse">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Holo.Light.Medium">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Holo.Light.Medium.Inverse">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Holo.Light.SearchResult.Subtitle">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Holo.Light.SearchResult.Title">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Holo.Light.Small">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Holo.Light.Small.Inverse">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Holo.Light.Widget.Button">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Large">
-
-    </style>
-    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Small">
-
-    </style>
+    <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Quantum"/>
+    <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Quantum.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Large" parent="TextAppearance.Quantum.Large"/>
+    <style name="TextAppearance.DeviceDefault.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Medium" parent="TextAppearance.Quantum.Medium"/>
+    <style name="TextAppearance.DeviceDefault.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Small" parent="TextAppearance.Quantum.Small"/>
+    <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title"/>
+    <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle"/>
+    <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Quantum.Widget"/>
+    <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Quantum.Widget.Button"/>
+    <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Widget.IconMenu.Item"/>
+    <style name="TextAppearance.DeviceDefault.Widget.TabWidget" parent="TextAppearance.Quantum.Widget.TabWidget"/>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView" parent="TextAppearance.Quantum.Widget.TextView"/>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" parent="TextAppearance.Quantum.Widget.TextView.PopupMenu"/>
+    <style name="TextAppearance.DeviceDefault.Widget.DropDownHint" parent="TextAppearance.Quantum.Widget.DropDownHint"/>
+    <style name="TextAppearance.DeviceDefault.Widget.DropDownItem" parent="TextAppearance.Quantum.Widget.DropDownItem"/>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" parent="TextAppearance.Quantum.Widget.TextView.SpinnerItem"/>
+    <style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText"/>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Widget.PopupMenu.Large"/>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Widget.PopupMenu.Small"/>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Widget.ActionBar.Title"/>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Widget.ActionBar.Subtitle"/>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Widget.ActionMode.Title"/>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle"/>
+    <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Quantum.WindowTitle"/>
+    <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse"/>
+    <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Widget.ActionBar.Menu"/>
+    <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Quantum.Light"/>
+    <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Quantum.Light.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Quantum.Light.Large"/>
+    <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Quantum.Light.Large.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Quantum.Light.Medium"/>
+    <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Quantum.Light.Medium.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.Light.SearchResult.Subtitle"/>
+    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Quantum.Light.SearchResult.Title"/>
+    <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Quantum.Light.Small"/>
+    <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Quantum.Light.Small.Inverse"/>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Quantum.Light.Widget.Button"/>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Large"/>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Small"/>
 
 
     <!-- Preference Styles -->
-    <style name="Preference.DeviceDefault" parent="Preference.Holo">
-
-    </style>
-    <style name="Preference.DeviceDefault.Category" parent="Preference.Holo.Category">
-
-    </style>
-    <style name="Preference.DeviceDefault.CheckBoxPreference" parent="Preference.Holo.CheckBoxPreference">
-
-    </style>
-    <style name="Preference.DeviceDefault.DialogPreference" parent="Preference.Holo.DialogPreference">
-
-    </style>
-    <style name="Preference.DeviceDefault.DialogPreference.EditTextPreference" parent="Preference.Holo.DialogPreference.EditTextPreference">
-
-    </style>
-    <style name="Preference.DeviceDefault.DialogPreference.YesNoPreference" parent="Preference.Holo.DialogPreference.YesNoPreference">
-
-    </style>
-    <style name="Preference.DeviceDefault.Information" parent="Preference.Holo.Information">
-
-    </style>
-    <style name="Preference.DeviceDefault.PreferenceScreen" parent="Preference.Holo.PreferenceScreen">
-
-    </style>
-    <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Holo.RingtonePreference">
-
-    </style>
-    <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Holo.SwitchPreference">
-
-    </style>
+    <style name="Preference.DeviceDefault" parent="Preference.Quantum"/>
+    <style name="Preference.DeviceDefault.Category" parent="Preference.Quantum.Category"/>
+    <style name="Preference.DeviceDefault.CheckBoxPreference" parent="Preference.Quantum.CheckBoxPreference"/>
+    <style name="Preference.DeviceDefault.DialogPreference" parent="Preference.Quantum.DialogPreference"/>
+    <style name="Preference.DeviceDefault.DialogPreference.EditTextPreference" parent="Preference.Quantum.DialogPreference.EditTextPreference"/>
+    <style name="Preference.DeviceDefault.DialogPreference.YesNoPreference" parent="Preference.Quantum.DialogPreference.YesNoPreference"/>
+    <style name="Preference.DeviceDefault.Information" parent="Preference.Quantum.Information"/>
+    <style name="Preference.DeviceDefault.PreferenceScreen" parent="Preference.Quantum.PreferenceScreen"/>
+    <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Quantum.RingtonePreference"/>
+    <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Quantum.SwitchPreference"/>
 
 
     <!-- AlertDialog Styles -->
-    <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Holo">
-
-    </style>
-    <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.Holo.Light" >
-
-    </style>
+    <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Quantum"/>
+    <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.Quantum.Light"/>
 
     <!-- Animation Styles -->
-    <style name="Animation.DeviceDefault.Activity" parent="Animation.Holo.Activity">
-
-    </style>
-    <style name="Animation.DeviceDefault.Dialog" parent="Animation.Holo.Dialog">
-
-    </style>
+    <style name="Animation.DeviceDefault.Activity" parent="Animation.Quantum.Activity"/>
+    <style name="Animation.DeviceDefault.Dialog" parent="Animation.Quantum.Dialog"/>
 
 
     <!-- DialogWindowTitle Styles -->
-    <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Holo">
-
-    </style>
-    <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Holo.Light">
-
-    </style>
+    <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Quantum"/>
+    <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Quantum.Light"/>
 
 
     <!-- WindowTitle Styles -->
-    <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Holo">
-
-    </style>
-    <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Holo">
-
-    </style>
+    <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Quantum"/>
+    <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Quantum"/>
 
 
     <!-- Other Styles -->
-    <style name="DeviceDefault.ButtonBar" parent="Holo.ButtonBar" >
+    <style name="DeviceDefault.ButtonBar" parent="Widget.Quantum.ButtonBar"/>
+    <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Widget.Quantum.ButtonBar.AlertDialog"/>
+    <style name="DeviceDefault.SegmentedButton" parent="Widget.Quantum.SegmentedButton"/>
+    <style name="DeviceDefault.Light.ButtonBar" parent="Widget.Quantum.Light.ButtonBar"/>
+    <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Widget.Quantum.Light.ButtonBar.AlertDialog"/>
+    <style name="DeviceDefault.Light.SegmentedButton" parent="Widget.Quantum.Light.SegmentedButton"/>
 
-    </style>
-    <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Holo.ButtonBar.AlertDialog" >
+    <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton" />
+    <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Quantum.Light.MediaRouteButton" />
 
-    </style>
-    <style name="DeviceDefault.SegmentedButton" parent="Holo.SegmentedButton" >
-
-    </style>
-    <style name="DeviceDefault.Light.ButtonBar" parent="Holo.Light.ButtonBar" >
-
-    </style>
-    <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Holo.Light.ButtonBar.AlertDialog" >
-
-    </style>
-    <style name="DeviceDefault.Light.SegmentedButton" parent="Holo.Light.SegmentedButton" >
-
-    </style>
-
-    <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Holo.MediaRouteButton" />
-    <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Holo.Light.MediaRouteButton" />
-
-    <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Holo.TimePicker.TimeLabel">
-    </style>
-
-    <style name="TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel" parent="TextAppearance.Holo.Light.TimePicker.TimeLabel">
-    </style>
-
-    <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Holo.TimePicker.AmPmLabel">
-    </style>
-
-    <style name="TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel" parent="TextAppearance.Holo.Light.TimePicker.AmPmLabel">
-    </style>
-
-    <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Holo.Dialog.TimePicker">
-    </style>
-
-    <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Holo.Light.Dialog.TimePicker">
-    </style>
-
+    <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel"/>
+    <style name="TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.Light.TimePicker.TimeLabel"/>
+    <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel"/>
+    <style name="TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.Light.TimePicker.AmPmLabel"/>
+    <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Quantum.Dialog.TimePicker"/>
+    <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Quantum.Light.Dialog.TimePicker"/>
 </resources>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 2020fea..dd148c4 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -277,20 +277,36 @@
         <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
     </style>
 
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+    </style>
+
     <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Small">
         <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
     </style>
 
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+    </style>
+
     <!-- Text styles with no light versions -->
 
     <style name="TextAppearance.Quantum.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Medium">
         <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
     </style>
 
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+    </style>
+
     <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Small">
         <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
     </style>
 
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+    </style>
+
     <style name="TextAppearance.Quantum.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Small">
         <item name="fontFamily">@string/font_family_menu_quantum</item>
         <item name="textSize">@dimen/text_size_menu_quantum</item>>
@@ -298,6 +314,13 @@
         <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
     </style>
 
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+        <item name="fontFamily">@string/font_family_menu_quantum</item>
+        <item name="textSize">@dimen/text_size_menu_quantum</item>>
+        <item name="textColor">?attr/actionMenuTextColor</item>
+        <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
+    </style>
+
     <style name="TextAppearance.Quantum.WindowTitle">
         <item name="textColor">?attr/textColorPrimary</item>
         <item name="fontFamily">@string/font_family_headline_quantum</item>
@@ -317,13 +340,13 @@
 
     <style name="TextAppearance.Quantum.TimePicker.TimeLabel" parent="TextAppearance.Quantum">
         <item name="textSize">@dimen/timepicker_time_label_size</item>
-        <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+        <item name="textColor">?attr/textColorSecondary</item>
     </style>
 
     <style name="TextAppearance.Quantum.TimePicker.AmPmLabel" parent="TextAppearance.Quantum">
         <item name="textSize">@dimen/timepicker_ampm_label_size</item>
         <item name="textAllCaps">true</item>
-        <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+        <item name="textColor">?attr/textColorSecondary</item>
         <item name="textStyle">bold</item>
     </style>
 
@@ -354,11 +377,11 @@
     <style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Quantum.CalendarViewWeekDayView"/>
 
     <style name="TextAppearance.Quantum.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel">
-        <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
+        <item name="textColor">?attr/textColorSecondary</item>
     </style>
 
     <style name="TextAppearance.Quantum.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel">
-        <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
+        <item name="textColor">?attr/textColorSecondary</item>
     </style>
 
     <!-- Widget Styles -->
@@ -371,6 +394,7 @@
     <style name="Widget.Quantum.Button" parent="Widget.Button">
         <item name="background">@drawable/btn_default_quantum</item>
         <item name="textAppearance">?attr/textAppearanceButton</item>
+        <item name="textColor">?attr/textColorPrimary</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">96dip</item>
     </style>
@@ -420,23 +444,13 @@
     </style>
 
     <style name="Widget.Quantum.ButtonBar">
-        <item name="paddingTop">0dip</item>
-        <item name="paddingStart">0dip</item>
-        <item name="paddingEnd">0dip</item>
-        <item name="paddingBottom">0dip</item>
-        <item name="divider">?attr/dividerVertical</item>
-        <item name="showDividers">middle</item>
-        <item name="dividerPadding">12dip</item>
         <item name="background">@null</item>
     </style>
 
     <style name="Widget.Quantum.ButtonBar.AlertDialog">
         <item name="background">@null</item>
-        <item name="dividerPadding">0dp</item>
     </style>
 
-    <style name="Widget.Quantum.ButtonBar.Button"/>
-
     <style name="Widget.Quantum.SegmentedButton" parent="SegmentedButton">
         <item name="background">@drawable/btn_group_holo_dark</item>
     </style>
@@ -531,16 +545,16 @@
     <style name="Widget.Quantum.TimePicker" parent="Widget.TimePicker">
         <item name="legacyLayout">@layout/time_picker_legacy_holo</item>
         <item name="internalLayout">@layout/time_picker_holo</item>
-        <item name="disabledColor">@color/timepicker_default_disabled_color_quantum_dark</item>
-        <item name="headerSelectedTextColor">@color/holo_blue_light</item>
-        <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_quantum_dark</item>
-        <item name="headerBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
-        <item name="numbersTextColor">@color/timepicker_default_text_color_quantum_dark</item>
-        <item name="numbersBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
-        <item name="amPmTextColor">@color/timepicker_default_text_color_quantum_dark</item>
-        <item name="amPmUnselectedBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
-        <item name="amPmSelectedBackgroundColor">@color/holo_blue_light</item>
-        <item name="numbersSelectorColor">@color/holo_blue_light</item>
+        <item name="disabledColor">@color/bright_foreground_disabled_quantum_dark</item>
+        <item name="headerSelectedTextColor">?attr/colorControlActivated</item>
+        <item name="headerUnselectedTextColor">?attr/textColorPrimary</item>
+        <item name="headerBackgroundColor">?attr/colorBackground</item>
+        <item name="numbersTextColor">?attr/textColorSecondary</item>
+        <item name="numbersBackgroundColor">?attr/colorControlNormal</item>
+        <item name="amPmTextColor">?attr/textColorSecondary</item>
+        <item name="amPmUnselectedBackgroundColor">?attr/colorControlNormal</item>
+        <item name="amPmSelectedBackgroundColor">?attr/colorControlActivated</item>
+        <item name="numbersSelectorColor">?attr/colorControlActivated</item>
     </style>
 
     <style name="Widget.Quantum.DatePicker" parent="Widget.DatePicker">
@@ -607,8 +621,8 @@
     </style>
 
     <style name="Widget.Quantum.RatingBar" parent="Widget.RatingBar">
-        <item name="progressDrawable">@drawable/ratingbar_full_holo_dark</item>
-        <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_dark</item>
+        <item name="progressDrawable">@drawable/ratingbar_full_quantum</item>
+        <item name="indeterminateDrawable">@drawable/ratingbar_full_quantum</item>
     </style>
 
     <style name="Widget.Quantum.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
@@ -654,7 +668,7 @@
         <item name="showDividers">middle</item>
         <item name="dividerPadding">8dip</item>
         <item name="measureWithLargestChild">true</item>
-        <item name="tabLayout">@layout/tab_indicator_holo</item>
+        <item name="tabLayout">@layout/tab_indicator_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Tab" parent="Widget.Quantum.ActionBar.TabView">
@@ -708,7 +722,7 @@
     </style>
 
     <style name="Widget.Quantum.ActionButton.CloseMode">
-        <item name="background">@drawable/btn_cab_done_holo_dark</item>
+        <item name="background">@drawable/btn_cab_done_quantum</item>
     </style>
 
     <style name="Widget.Quantum.ActionButton.Overflow">
@@ -717,7 +731,7 @@
         <item name="contentDescription">@string/action_menu_overflow_description</item>
     </style>
 
-    <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar.Button"/>
+    <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/>
 
     <style name="Widget.Quantum.ActionBar.TabView" parent="Widget.ActionBar.TabView">
         <item name="background">@drawable/tab_indicator_quantum</item>
@@ -744,9 +758,9 @@
     <style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_transparent_quantum</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_transparent_dark_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_transparent_dark_holo</item>
+        <item name="background">@null</item>
+        <item name="backgroundStacked">@null</item>
+        <item name="backgroundSplit">@null</item>
         <item name="divider">?attr/dividerVertical</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -755,16 +769,9 @@
     </style>
 
     <style name="Widget.Quantum.ActionBar.Solid">
-        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
-        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_solid_dark_holo</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_solid_dark_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_solid_dark_holo</item>
-        <item name="divider">?attr/dividerVertical</item>
-        <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
-        <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
-        <item name="progressBarPadding">32dip</item>
-        <item name="itemPadding">8dip</item>
+        <item name="background">?attr/colorPrimary</item>
+        <item name="backgroundStacked">?attr/colorPrimary</item>
+        <item name="backgroundSplit">?attr/colorPrimary</item>
     </style>
 
     <style name="Widget.Quantum.ActionMode" parent="Widget.ActionMode">
@@ -786,7 +793,7 @@
 
     <style name="Widget.Quantum.MediaRouteButton">
         <item name="background">?attr/selectableItemBackground</item>
-        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_dark</item>
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
         <item name="minWidth">56dp</item>
         <item name="minHeight">48dp</item>
         <item name="focusable">true</item>
@@ -855,25 +862,16 @@
 
     <style name="Widget.Quantum.Light.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
 
-    <style name="Widget.Quantum.Light.TimePicker" parent="Widget.TimePicker">
+    <style name="Widget.Quantum.Light.TimePicker" parent="Widget.Quantum.TimePicker">
         <item name="legacyLayout">@layout/time_picker_legacy_holo</item>
         <item name="internalLayout">@layout/time_picker_holo</item>
-        <item name="disabledColor">@color/timepicker_default_disabled_color_quantum_light</item>
-        <item name="headerSelectedTextColor">@color/holo_blue_light</item>
-        <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_quantum_light</item>
-        <item name="headerBackgroundColor">@color/timepicker_default_background_quantum_light</item>
-        <item name="numbersTextColor">@color/timepicker_default_text_color_quantum_light</item>
-        <item name="numbersBackgroundColor">@color/timepicker_default_background_quantum_light</item>
-        <item name="amPmTextColor">@color/timepicker_default_text_color_quantum_light</item>
-        <item name="amPmUnselectedBackgroundColor">@color/timepicker_default_background_quantum_light</item>
-        <item name="amPmSelectedBackgroundColor">@color/holo_blue_light</item>
-        <item name="numbersSelectorColor">@color/holo_blue_light</item>
+        <item name="disabledColor">@color/bright_foreground_disabled_quantum_light</item>
     </style>
 
     <style name="Widget.Quantum.Light.DatePicker" parent="Widget.Quantum.DatePicker"/>
 
     <style name="Widget.Quantum.Light.ActivityChooserView" parent="Widget.Quantum.ActivityChooserView">
-        <item name="background">@drawable/ab_share_pack_holo_light</item>
+        <item name="background">@drawable/ab_share_pack_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Light.ImageWell" parent="Widget.Quantum.ImageWell"/>
@@ -896,10 +894,7 @@
     <style name="Widget.Quantum.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
     <style name="Widget.Quantum.Light.SeekBar" parent="Widget.Quantum.SeekBar"/>
 
-    <style name="Widget.Quantum.Light.RatingBar" parent="Widget.RatingBar">
-        <item name="progressDrawable">@drawable/ratingbar_full_holo_light</item>
-        <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_light</item>
-    </style>
+    <style name="Widget.Quantum.Light.RatingBar" parent="Widget.Quantum.RatingBar" />
 
     <style name="Widget.Quantum.Light.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
         <item name="progressDrawable">@drawable/ratingbar_holo_light</item>
@@ -968,31 +963,24 @@
     </style>
 
     <style name="Widget.Quantum.Light.ActionButton.CloseMode">
-        <item name="background">@drawable/btn_cab_done_holo_light</item>
+        <item name="background">@drawable/btn_cab_done_quantum</item>
     </style>
 
     <style name="Widget.Quantum.Light.ActionBar" parent="Widget.Quantum.ActionBar">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_transparent_quantum</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_transparent_light_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_transparent_light_holo</item>
+        <item name="background">@null</item>
+        <item name="backgroundStacked">@null</item>
+        <item name="backgroundSplit">@null</item>
         <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
         <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
     </style>
 
     <style name="Widget.Quantum.Light.ActionBar.Solid">
-        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
-        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_solid_light_holo</item>
-        <item name="backgroundStacked">@drawable/ab_stacked_solid_light_holo</item>
-        <item name="backgroundSplit">@drawable/ab_bottom_solid_light_holo</item>
-        <item name="divider">?attr/dividerVertical</item>
-        <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
-        <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
-        <item name="progressBarPadding">32dip</item>
-        <item name="itemPadding">8dip</item>
+        <item name="background">?attr/colorPrimary</item>
+        <item name="backgroundStacked">?attr/colorPrimary</item>
+        <item name="backgroundSplit">?attr/colorPrimary</item>
     </style>
 
     <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
@@ -1002,7 +990,7 @@
     <style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
 
     <style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
-        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item>
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
     </style>
 
     <!-- Animation Styles -->
@@ -1024,13 +1012,13 @@
         <item name="bottomBright">?attr/colorBackground</item>
         <item name="bottomMedium">?attr/colorBackground</item>
         <item name="centerMedium">?attr/colorBackground</item>
-        <item name="layout">@layout/alert_dialog_holo</item>
-        <item name="listLayout">@layout/select_dialog_holo</item>
-        <item name="progressLayout">@layout/progress_dialog_holo</item>
-        <item name="horizontalProgressLayout">@layout/alert_dialog_progress_holo</item>
-        <item name="listItemLayout">@layout/select_dialog_item_holo</item>
-        <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_holo</item>
-        <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_holo</item>
+        <item name="layout">@layout/alert_dialog_quantum</item>
+        <item name="listLayout">@layout/select_dialog_quantum</item>
+        <item name="progressLayout">@layout/progress_dialog_quantum</item>
+        <item name="horizontalProgressLayout">@layout/alert_dialog_progress_quantum</item>
+        <item name="listItemLayout">@layout/select_dialog_item_quantum</item>
+        <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_quantum</item>
+        <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_quantum</item>
     </style>
 
     <style name="AlertDialog.Quantum.Light"/>
@@ -1043,8 +1031,7 @@
     <style name="WindowTitle.Quantum">
         <item name="singleLine">true</item>
         <item name="textAppearance">@style/TextAppearance.Quantum.WindowTitle</item>
-        <item name="shadowColor">#BB000000</item>
-        <item name="shadowRadius">2.75</item>
+        <item name="shadowRadius">0</item>
     </style>
 
     <style name="DialogWindowTitle.Quantum">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fa84750..b011483 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1104,6 +1104,7 @@
   <java-symbol type="drawable" name="cling_button" />
   <java-symbol type="drawable" name="cling_arrow_up" />
   <java-symbol type="drawable" name="cling_bg" />
+  <java-symbol type="drawable" name="ic_corp_badge" />
 
   <java-symbol type="layout" name="action_bar_home" />
   <java-symbol type="layout" name="action_bar_title_item" />
@@ -1622,6 +1623,7 @@
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
   <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
   <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
+  <java-symbol type="string" name="config_customAdbPublicKeyActivity" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
@@ -1828,4 +1830,10 @@
   <java-symbol type="color" name="timepicker_default_ampm_selected_background_color_holo_light" />
   <java-symbol type="array" name="config_clockTickVibePattern" />
 
+  <!-- From various Quantum changes -->
+  <java-symbol type="attr" name="toolbarStyle" />
+  <java-symbol type="attr" name="titleTextAppearance" />
+  <java-symbol type="attr" name="subtitleTextAppearance" />
+  <java-symbol type="drawable" name="ic_lock_bugreport" />
+
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3c4e848..7aea814 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -352,6 +352,8 @@
         <item name="actionBarDivider">?android:attr/dividerVertical</item>
         <item name="actionBarItemBackground">?android:attr/selectableItemBackground</item>
 
+        <item name="toolbarStyle">@android:style/Widget.Toolbar</item>
+
         <item name="dividerVertical">@drawable/divider_vertical_dark</item>
         <item name="dividerHorizontal">@drawable/divider_vertical_dark</item>
         <item name="buttonBarStyle">@android:style/ButtonBar</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 19556a1..0ce5094 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -32,24 +32,24 @@
  -->
 <resources>
 
-    <!-- The default theme for apps that target API level 14 and higher.
+    <!-- The default theme for apps that target API level XX and higher.
          <p>The DeviceDefault themes are aliases for a specific device’s native look and feel. The
          DeviceDefault theme family and widget style family offer ways for you to target your app
          to a device’s native theme with all device customizations intact.</p>
-         <p>For example, when you set your app's {@code targetSdkVersion} to 14 or higher, this
+         <p>For example, when you set your app's {@code targetSdkVersion} to XX or higher, this
          theme is applied to your application by default. As such, your app might appear with the
-         {@link #Theme_Holo Holo} styles on one device, but with a different set of styles on
+         {@link #Theme_Quantum Quantum} styles on one device, but with a different set of styles on
          another device. This is great if you want your app to fit with the device's native look and
          feel. If, however, you prefer to keep your UI style the same across all devices, you should
-         apply a specific theme such as {@link #Theme_Holo Holo} or one of your own design. For more
-         information, read <a
-         href="http://android-developers.blogspot.com/2012/01/holo-everywhere.html">Holo
+         apply a specific theme such as {@link #Theme_Quantum Quantum} or one of your own design.
+         For more information, read <a
+         href="http://android-developers.blogspot.com/20XX/XX/quantum-everywhere.html">Quantum
          Everywhere</a>.</p>
          <p>Styles used by the DeviceDefault theme are named using the convention
          Type.DeviceDefault.Etc (for example, {@code Widget.DeviceDefault.Button} and
          {@code TextAppearance.DeviceDefault.Widget.PopupMenu.Large}).</p>
           -->
-    <style name="Theme.DeviceDefault" parent="Theme.Holo" >
+    <style name="Theme.DeviceDefault" parent="Theme.Quantum" >
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
@@ -210,29 +210,29 @@
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
-    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Holo.NoActionBar" >
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Quantum.NoActionBar" >
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar.  This theme
          sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Holo.NoActionBar.Fullscreen" >
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Quantum.NoActionBar.Fullscreen" >
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
     extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Holo.NoActionBar.Overscan" >
+    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Quantum.NoActionBar.Overscan" >
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Holo.NoActionBar.TranslucentDecor" >
+    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Quantum.NoActionBar.TranslucentDecor" >
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
-    <style name="Theme.DeviceDefault.Light" parent="Theme.Holo.Light" >
+    <style name="Theme.DeviceDefault.Light" parent="Theme.Quantum.Light" >
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
@@ -387,29 +387,29 @@
         <item name="mediaRouteButtonStyle">@android:style/Widget.DeviceDefault.Light.MediaRouteButton</item>
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar" >
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Quantum.Light.NoActionBar" >
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
          This theme sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Holo.Light.NoActionBar.Fullscreen" >
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Quantum.Light.NoActionBar.Fullscreen" >
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
     and extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
     <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan"
-           parent="Theme.Holo.Light.NoActionBar.Overscan" >
+           parent="Theme.Quantum.Light.NoActionBar.Overscan" >
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
     <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor"
-           parent="Theme.Holo.Light.NoActionBar.TranslucentDecor" >
+           parent="Theme.Quantum.Light.NoActionBar.TranslucentDecor" >
     </style>
     <!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
     floating (not fill the entire screen), and puts a frame around its contents. You can set this
     theme on an activity if you would like to make an activity that looks like a Dialog. -->
-    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Holo.Dialog" >
+    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Quantum.Dialog" >
         <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
 
@@ -421,16 +421,16 @@
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Holo.Dialog.MinWidth" >
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Quantum.Dialog.MinWidth" >
 
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Holo.Dialog.NoActionBar" >
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Quantum.Dialog.NoActionBar" >
 
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
     for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Dialog.NoActionBar.MinWidth" >
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Dialog.NoActionBar.MinWidth" >
 
     </style>
 
@@ -453,7 +453,7 @@
     <!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
     floating (not fill the entire screen), and puts a frame around its contents. You can set this
     theme on an activity if you would like to make an activity that looks like a Dialog.-->
-    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Holo.Light.Dialog" >
+    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Quantum.Light.Dialog" >
         <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
 
@@ -465,16 +465,16 @@
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Holo.Light.Dialog.MinWidth" >
+    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Quantum.Light.Dialog.MinWidth" >
 
     </style>
      <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Holo.Light.Dialog.NoActionBar" >
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Quantum.Light.Dialog.NoActionBar" >
 
     </style>
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
     width for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Light.Dialog.NoActionBar.MinWidth" >
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Light.Dialog.NoActionBar.MinWidth" >
 
     </style>
 
@@ -496,65 +496,65 @@
 
     <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Holo.DialogWhenLarge" >
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Quantum.DialogWhenLarge" >
 
     </style>
     <!-- DeviceDefault theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Holo.DialogWhenLarge.NoActionBar" >
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.DialogWhenLarge.NoActionBar" >
 
     </style>
     <!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Holo.Light.DialogWhenLarge" >
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Quantum.Light.DialogWhenLarge" >
 
     </style>
     <!-- DeviceDefault light theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Holo.Light.DialogWhenLarge.NoActionBar" >
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.Light.DialogWhenLarge.NoActionBar" >
 
     </style>
 
     <!-- DeviceDefault theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Holo.Dialog.Presentation">
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Quantum.Dialog.Presentation">
     </style>
 
     <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Holo.Light.Dialog.Presentation">
+    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Quantum.Light.Dialog.Presentation">
     </style>
 
     <!-- DeviceDefault theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Panel" parent="Theme.Holo.Panel" >
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Quantum.Panel" >
 
     </style>
     <!-- DeviceDefault light theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Holo.Light.Panel" >
+    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Quantum.Light.Panel" >
 
     </style>
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them. -->
-    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Holo.Wallpaper" >
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Quantum.Wallpaper" >
 
     </style>
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them and without an action bar. -->
-    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Holo.Wallpaper.NoTitleBar" >
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Quantum.Wallpaper.NoTitleBar" >
 
     </style>
     <!-- DeviceDefault style for input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.-->
-    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Holo.InputMethod" >
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Quantum.InputMethod" >
 
     </style>
     <!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
     inverse color profile. -->
-    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar" >
+    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Quantum.Light.DarkActionBar" >
         <item name="android:actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse</item>
 
         <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
@@ -569,20 +569,20 @@
 
     </style>
 
-    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Holo.Dialog.Alert">
+    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Quantum.Dialog.Alert">
         <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
     </style>
-    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Holo.Light.Dialog.Alert">
+    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Quantum.Light.Dialog.Alert">
         <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
     </style>
-    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Holo.SearchBar">
+    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Quantum.SearchBar">
 
     </style>
-    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Holo.Light.SearchBar">
+    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Quantum.Light.SearchBar">
 
     </style>
 
-    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Holo.Dialog.NoFrame">
+    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Quantum.Dialog.NoFrame">
     </style>
 
 </resources>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 24abd55..b5ac8fa 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -154,7 +154,7 @@
         <item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
         <item name="windowTitleSize">25dip</item>
         <item name="windowTitleBackgroundStyle">@style/WindowTitleBackground.Quantum</item>
-        <item name="windowContentTransitions">true</item>
+        <item name="windowContentTransitions">false</item>
         <item name="windowAnimationStyle">@style/Animation.Quantum.Activity</item>
         <item name="windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
         <item name="windowActionBar">true</item>
@@ -162,9 +162,9 @@
 
         <!-- Dialog attributes -->
         <item name="dialogTheme">@style/Theme.Quantum.Dialog</item>
-        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
-        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
-        <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item>
+        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item>
+        <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item>
 
         <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@style/Theme.Quantum.Dialog.Alert</item>
@@ -288,18 +288,19 @@
         <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="actionModeBackground">@color/theme_color_700</item>
-        <item name="actionModeSplitBackground">@color/theme_color_700</item>
+        <item name="actionModeBackground">?attr/colorPrimaryDark</item>
+        <item name="actionModeSplitBackground">?attr/colorPrimaryDark</item>
         <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
         <item name="actionBarTabStyle">@style/Widget.Quantum.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Quantum.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.Quantum.ActionBar.TabText</item>
         <item name="actionModeStyle">@style/Widget.Quantum.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.ActionButton.CloseMode</item>
-        <item name="actionBarStyle">@style/Widget.Quantum.ActionBar</item>
+        <item name="actionBarStyle">@style/Widget.Quantum.ActionBar.Solid</item>
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarTheme">@null</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -334,7 +335,7 @@
         <item name="timePickerStyle">@style/Widget.Quantum.TimePicker</item>
 
         <!-- TimePicker background color -->
-        <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_quantum_dark</item>
+        <item name="timePickerHeaderBackgroundColor">?colorBackground</item>
 
         <!-- TimePicker Header time label text appearance -->
         <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.TimePicker.TimeLabel</item>
@@ -356,13 +357,18 @@
         <item name="fastScrollOverlayPosition">atThumb</item>
 
         <!-- Color palette -->
-        <item name="colorControlNormal">@color/control_normal_foreground_quantum_dark</item>
-        <item name="colorControlActivated">@color/control_activated_foreground_quantum_dark</item>
-        <item name="colorButtonNormal">@color/btn_default_normal_quantum_dark</item>
-        <item name="colorButtonPressed">@color/btn_default_pressed_quantum_dark</item>
+        <item name="colorPrimaryDark">@color/quantum_blue_700</item>
+        <item name="colorPrimary">@color/quantum_blue_500</item>
+        <item name="colorPrimaryLight">@color/quantum_blue_100</item>
+        <item name="colorAccent">@color/quantum_teal_A200</item>
+
+        <item name="colorControlNormal">?attr/textColorSecondary</item>
+        <item name="colorControlActivated">?attr/colorPrimary</item>
+        <item name="colorButtonNormal">@color/quantum_grey_700</item>
+        <item name="colorButtonPressed">@color/quantum_grey_500</item>
         <!-- TODO: Remove these attrs and move into button style. -->
-        <item name="colorButtonNormalColored">@color/theme_color_500</item>
-        <item name="colorButtonPressedColored">@color/theme_color_300</item>
+        <item name="colorButtonNormalColored">?attr/colorPrimary</item>
+        <item name="colorButtonPressedColored">?attr/colorPrimaryLight</item>
     </style>
 
     <!-- Quantum Paper theme (light version). -->
@@ -476,7 +482,7 @@
         <item name="windowFullscreen">false</item>
         <item name="windowOverscan">false</item>
         <item name="windowIsFloating">false</item>
-        <item name="windowContentOverlay">@drawable/ab_solid_shadow_qntm</item>
+        <item name="windowContentOverlay">@drawable/ab_solid_shadow_quantum</item>
         <item name="windowShowWallpaper">false</item>
         <item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
         <item name="windowTitleSize">25dip</item>
@@ -488,9 +494,9 @@
 
         <!-- Dialog attributes -->
         <item name="dialogTheme">@style/Theme.Quantum.Light.Dialog</item>
-        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
-        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
-        <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item>
+        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item>
+        <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item>
 
         <!-- AlertDialog attributes -->
         <item name="alertDialogTheme">@style/Theme.Quantum.Light.Dialog.Alert</item>
@@ -629,6 +635,7 @@
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarTheme">@null</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -660,7 +667,7 @@
         <item name="timePickerStyle">@style/Widget.Quantum.Light.TimePicker</item>
 
         <!-- TimePicker Header background color -->
-        <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_quantum_light</item>
+        <item name="timePickerHeaderBackgroundColor">?attr/colorBackground</item>
 
         <!-- TimePicker Header time label text appearance -->
         <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Quantum.Light.TimePicker.TimeLabel</item>
@@ -681,13 +688,18 @@
         <item name="fastScrollOverlayPosition">atThumb</item>
 
         <!-- Color palette -->
-        <item name="colorControlNormal">@color/control_normal_foreground_quantum_light</item>
-        <item name="colorControlActivated">@color/control_activated_foreground_quantum_light</item>
-        <item name="colorButtonNormal">@color/btn_default_normal_quantum_light</item>
-        <item name="colorButtonPressed">@color/btn_default_pressed_quantum_light</item>
+        <item name="colorPrimaryDark">@color/quantum_blue_700</item>
+        <item name="colorPrimary">@color/quantum_blue_500</item>
+        <item name="colorPrimaryLight">@color/quantum_blue_100</item>
+        <item name="colorAccent">@color/quantum_teal_A200</item>
+
+        <item name="colorControlNormal">?attr/textColorSecondary</item>
+        <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">@color/theme_color_500</item>
-        <item name="colorButtonPressedColored">@color/theme_color_700</item>
+        <item name="colorButtonNormalColored">?attr/colorPrimary</item>
+        <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
     </style>
 
     <!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
index fc2897f..f4bab43 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerBaseTest.java
@@ -466,15 +466,16 @@
      * bytes downloaded so far.
      *
      * @param id DownloadManager download id that needs to be checked.
+     * @param bytesToReceive how many bytes do we need to wait to receive.
      * @throws Exception if timed out while waiting for the file to grow in size.
      */
-    protected void waitToReceiveData(long id) throws Exception {
+    protected void waitToReceiveData(long id, long bytesToReceive) throws Exception {
         int currentWaitTime = 0;
-        long originalSize = getBytesDownloaded(id);
+        long expectedSize = getBytesDownloaded(id) + bytesToReceive;
         long currentSize = 0;
-        while ((currentSize = getBytesDownloaded(id)) <= originalSize) {
-            Log.i(LOG_TAG, String.format("orig: %d, cur: %d. Waiting for file to be written to...",
-                    originalSize, currentSize));
+        while ((currentSize = getBytesDownloaded(id)) <= expectedSize) {
+            Log.i(LOG_TAG, String.format("expect: %d, cur: %d. Waiting for file to be written to...",
+                    expectedSize, currentSize));
             currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
                     MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to.");
         }
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
index ef48a18..bcf2e45 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
@@ -40,6 +40,9 @@
 
     protected static final String DOWNLOAD_FILENAME = "External93mb.apk";
     protected static final long DOWNLOAD_FILESIZE = 95251708;
+    // Wait until download manager actually start downloading something
+    // Will wait for 1 MB to be downloaded.
+    private static final long EXPECTED_PROGRESS = 1024 * 1024;
 
     private static final String FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX = "file";
     private static final String FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION = ".bin";
@@ -284,7 +287,7 @@
             dlRequest = mDownloadManager.enqueue(request);
             waitForDownloadToStart(dlRequest);
             // make sure we're starting to download some data...
-            waitToReceiveData(dlRequest);
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download disable
             setWiFiStateOn(false);
@@ -292,27 +295,29 @@
             // download disable
             Log.i(LOG_TAG, "Turning on airplane mode...");
             setAirplaneModeOn(true);
-            Thread.sleep(30 * 1000);  // wait 30 secs
+            Thread.sleep(5 * 1000);  // wait 5 secs
 
             // download disable
             setWiFiStateOn(true);
-            Thread.sleep(30 * 1000);  // wait 30 secs
+            Thread.sleep(5 * 1000);  // wait 5 secs
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download enable
             Log.i(LOG_TAG, "Turning off airplane mode...");
             setAirplaneModeOn(false);
             Thread.sleep(5 * 1000);  // wait 5 seconds
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download disable
             Log.i(LOG_TAG, "Turning off WiFi...");
             setWiFiStateOn(false);
-            Thread.sleep(30 * 1000);  // wait 30 secs
+            Thread.sleep(5 * 1000);  // wait 5 secs
 
             // finally, turn WiFi back on and finish up the download
             Log.i(LOG_TAG, "Turning on WiFi...");
             setWiFiStateOn(true);
-            Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
-            assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
+            Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
+            assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
             ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
             verifyFileSize(pfd, filesize);
         } finally {
@@ -358,7 +363,7 @@
             dlRequest = mDownloadManager.enqueue(request);
             waitForDownloadToStart(dlRequest);
             // are we making any progress?
-            waitToReceiveData(dlRequest);
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download disable
             Log.i(LOG_TAG, "Turning off WiFi...");
@@ -368,7 +373,7 @@
             // enable download...
             Log.i(LOG_TAG, "Turning on WiFi again...");
             setWiFiStateOn(true);
-            waitToReceiveData(dlRequest);
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download disable
             Log.i(LOG_TAG, "Turning off WiFi...");
@@ -379,8 +384,8 @@
             Log.i(LOG_TAG, "Turning on WiFi again...");
             setWiFiStateOn(true);
 
-            Log.i(LOG_TAG, "Waiting up to 3 minutes for download to complete...");
-            assertTrue(waitForDownload(dlRequest, 3 * 60 * 1000));
+            Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
+            assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
             ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
             verifyFileSize(pfd, filesize);
         } finally {
@@ -428,7 +433,7 @@
             dlRequest = mDownloadManager.enqueue(request);
             waitForDownloadToStart(dlRequest);
             // are we making any progress?
-            waitToReceiveData(dlRequest);
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // download disable
             Log.i(LOG_TAG, "Turning on Airplane mode...");
@@ -439,7 +444,7 @@
             Log.i(LOG_TAG, "Turning off Airplane mode...");
             setAirplaneModeOn(false);
             // make sure we're starting to download some data...
-            waitToReceiveData(dlRequest);
+            waitToReceiveData(dlRequest, EXPECTED_PROGRESS);
 
             // reenable the connection to start up the download again
             Log.i(LOG_TAG, "Turning on Airplane mode again...");
@@ -450,8 +455,8 @@
             Log.i(LOG_TAG, "Turning off Airplane mode again...");
             setAirplaneModeOn(false);
 
-            Log.i(LOG_TAG, "Waiting up to 3 minutes for donwload to complete...");
-            assertTrue(waitForDownload(dlRequest, 180 * 1000));  // wait up to 3 mins before timeout
+            Log.i(LOG_TAG, "Waiting up to 10 minutes for donwload to complete...");
+            assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
             ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
             verifyFileSize(pfd, filesize);
         } finally {
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 6d29c69..92ecd24 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -61,7 +61,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -92,7 +92,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -133,17 +133,17 @@
 </tr>
 <tr>
 <td>2.0</th>
-<td>91.1%</td>
+<td>89.4%</td>
 </tr>
 <tr>
 <td>3.0</th>
-<td>8.8%</td>
+<td>10.5%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014</em></p>
 
 
 
@@ -161,17 +161,17 @@
 var VERSION_DATA =
 [
   {
-    "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A1.2%2C19.0%2C0.1%2C15.2%2C62.0%2C2.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
+    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A1.1%2C17.8%2C0.1%2C14.3%2C61.4%2C5.3&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat",
     "data": [
       {
         "api": 8,
         "name": "Froyo",
-        "perc": "1.2"
+        "perc": "1.1"
       },
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "19.0"
+        "perc": "17.8"
       },
       {
         "api": 13,
@@ -181,27 +181,27 @@
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "15.2"
+        "perc": "14.3"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "35.3"
+        "perc": "34.4"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "17.1"
+        "perc": "18.1"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "9.6"
+        "perc": "8.9"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "2.5"
+        "perc": "5.3"
       }
     ]
   }
@@ -218,16 +218,15 @@
       "Large": {
         "hdpi": "0.6",
         "ldpi": "0.7",
-        "mdpi": "4.3",
+        "mdpi": "4.4",
         "tvdpi": "1.5",
         "xhdpi": "0.6"
       },
       "Normal": {
         "hdpi": "33.7",
-        "ldpi": "0.2",
-        "mdpi": "13.6",
-        "xhdpi": "19.9",
-        "xxhdpi": "11.9"
+        "mdpi": "13.2",
+        "xhdpi": "19.8",
+        "xxhdpi": "12.5"
       },
       "Small": {
         "ldpi": "8.1"
@@ -235,12 +234,12 @@
       "Xlarge": {
         "hdpi": "0.3",
         "ldpi": "0.1",
-        "mdpi": "4.3",
-        "xhdpi": "0.2"
+        "mdpi": "4.2",
+        "xhdpi": "0.3"
       }
     },
-    "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A9.1%2C22.2%2C1.5%2C34.6%2C20.7%2C11.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
-    "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.9%2C7.7%2C79.3%2C8.1&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
+    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A8.9%2C21.8%2C1.5%2C34.6%2C20.7%2C12.6&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
+    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A4.9%2C7.8%2C79.3%2C8.1&chl=Xlarge%7CLarge%7CNormal%7CSmall"
   }
 ];
 
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index c687f33..7c7c5d9 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -1,5 +1,5 @@
 page.title=Design
-page.viewport-width=970
+page.viewport_width=970
 header.hide=1
 footer.hide=1
 @jd:body
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 083b428..eb28da8 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -1,6 +1,6 @@
 fullpage=true
 page.title=Develop
-page.viewport-width=970
+page.viewport_width=970
 header.hide=1
 carousel=1
 tabbedList=1
diff --git a/docs/html/distribute/index.jd b/docs/html/distribute/index.jd
index d2534b9..6c6e113 100644
--- a/docs/html/distribute/index.jd
+++ b/docs/html/distribute/index.jd
@@ -1,5 +1,5 @@
 page.title=Distribute Apps
-page.viewport-width=970
+page.viewport_width=970
 header.hide=1
 
 @jd:body
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index b743b66..2e97d62 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -125,7 +125,7 @@
 <img src="{@docRoot}images/google/analytics.png" width="40" />
   </div>
     <h4><a class="external-link" 
-href="https://developers.google.com/analytics/devguides/collection/android/v2/"
+href="https://developers.google.com/analytics/devguides/collection/android/v4/"
   >Google Analytics</a></h4>
 
 <p>Measure your success and gain insights into how users engage with your app content
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index 506cf9d..826dcff 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -11,6 +11,18 @@
         <span class="less" style="display:none">show less</span></a></h2>
 
 <ol id="tocIntents" class="hide-nested">
+  <li><a href="#Clock">Alarm Clock</a>
+    <ol>
+      <li><a href="#CreateAlarm">Create an alarm</a></li>
+      <li><a href="#CreateTimer">Create a timer</a></li>
+      <li><a href="#ShowAlarms">Show all alarms</a></li>
+    </ol>
+  </li>
+  <li><a href="#Calendar">Calendar</a>
+    <ol>
+      <li><a href="#AddEvent">Add a calendar event</a></li>
+    </ol>
+  </li>
   <li><a href="#Camera">Camera</a>
     <ol>
       <li><a href="#ImageCapture">Capture a picture or video and return it</a></li>
@@ -116,6 +128,292 @@
 
 
 
+
+
+
+
+<h2 id="Clock">Alarm Clock</h2>
+
+
+<h3 id="CreateAlarm">Create an alarm</h3>
+
+<p>To create a new alarm, use the {@link android.provider.AlarmClock#ACTION_SET_ALARM}
+action and specify alarm details such as the time and message using extras defined below.</p>
+
+<p class="note"><strong>Note:</strong> Only the hour, minutes, and message extras are available
+since Android 2.3 (API level 9). The other extras were added in later versions of the platform.</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SET_ALARM}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+  <dl>
+    <dt>{@link android.provider.AlarmClock#EXTRA_HOUR}</dt>
+      <dd>The hour for the alarm.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_MINUTES}</dt>
+      <dd>The minutes for the alarm.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_MESSAGE}</dt>
+      <dd>A custom message to identify the alarm.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_DAYS}</dt>
+      <dd>An {@link java.util.ArrayList} including each week day on which this alarm should
+      be repeated. Each day must be declared with an integer from the {@link java.util.Calendar}
+      class such as {@link java.util.Calendar#MONDAY}.
+      <p>For a one-time alarm, do not specify this extra.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_RINGTONE}</dt>
+      <dd>A {@code content:} URI specifying a ringtone to use with the alarm, or {@link
+      android.provider.AlarmClock#VALUE_RINGTONE_SILENT} for no ringtone.
+      <p>To use the default ringtone, do not specify this extra.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_VIBRATE}</dt>
+      <dd>A boolean specifying whether to vibrate for this alarm.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_SKIP_UI}</dt>
+      <dd>A boolean specifying whether the responding app should skip its UI when setting the alarm.
+      If true, the app should bypass any confirmation UI and simply set the specified alarm.</dd>
+  </dl>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void createAlarm(String message, int hour, int minutes) {
+    Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
+            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
+            .putExtra(AlarmClock.EXTRA_HOUR, hour)
+            .putExtra(AlarmClock.EXTRA_MINUTES, minutes);
+    if (intent.resolveActivity(getPackageManager()) != null) {
+        startActivity(intent);
+    }
+}
+</pre>
+
+<div class="note"><strong>Note:</strong>
+<p>In order to invoke the {@link
+android.provider.AlarmClock#ACTION_SET_ALARM} intent, your app must have the
+{@link android.Manifest.permission#SET_ALARM} permission:</p>
+<pre>
+&lt;uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+</pre>
+</div>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+&lt;activity ...>
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.SET_ALARM" />
+        &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+
+
+<h3 id="CreateTimer">Create a timer</h3>
+
+<p>To create a countdown timer, use the {@link android.provider.AlarmClock#ACTION_SET_TIMER}
+action and specify timer details such as the duration using extras defined below.</p>
+
+<p class="note"><strong>Note:</strong> This intent was added
+in Android 4.4 (API level 19).</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SET_TIMER}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+  <dl>
+    <dt>{@link android.provider.AlarmClock#EXTRA_LENGTH}</dt>
+      <dd>The length of the timer in seconds.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_MESSAGE}</dt>
+      <dd>A custom message to identify the timer.</dd>
+    <dt>{@link android.provider.AlarmClock#EXTRA_SKIP_UI}</dt>
+      <dd>A boolean specifying whether the responding app should skip its UI when setting the timer.
+      If true, the app should bypass any confirmation UI and simply start the specified timer.</dd>
+  </dl>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void startTimer(String message, int seconds) {
+    Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER)
+            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
+            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
+            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);
+    if (intent.resolveActivity(getPackageManager()) != null) {
+        startActivity(intent);
+    }
+}
+</pre>
+
+<div class="note"><strong>Note:</strong>
+<p>In order to invoke the {@link
+android.provider.AlarmClock#ACTION_SET_TIMER} intent, your app must have the
+{@link android.Manifest.permission#SET_ALARM} permission:</p>
+<pre>
+&lt;uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+</pre>
+</div>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+&lt;activity ...>
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.SET_TIMER" />
+        &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+
+
+
+
+<h3 id="ShowAlarms">Show all alarms</h3>
+
+<p>To show the list of alarms, use the {@link android.provider.AlarmClock#ACTION_SHOW_ALARMS}
+action.</p>
+
+<p>Although not many apps will invoke this intent (it's primarily used by system apps),
+any app that behaves as an alarm clock should implement
+this intent filter and respond by showing the list of current alarms.</p>
+
+<p class="note"><strong>Note:</strong> This intent was added
+in Android 4.4 (API level 19).</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SHOW_ALARMS}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+</dl>
+
+<p><b>Example intent filter:</b></p>
+<pre>
+&lt;activity ...>
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.SHOW_ALARMS" />
+        &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+
+
+
+
+
+<h2 id="Calendar">Calendar</h2>
+
+
+<h3 id="AddEvent">Add a calendar event</h3>
+
+<p>To add a new event to the user's calendar, use the {@link android.content.Intent#ACTION_INSERT}
+action and specify the data URI with {@link android.provider.CalendarContract.Events#CONTENT_URI
+Events.CONTENT_URI}. You can then specify various event details using extras defined below.</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.content.Intent#ACTION_INSERT}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>{@link android.provider.CalendarContract.Events#CONTENT_URI
+Events.CONTENT_URI}</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>{@code "vnd.android.cursor.dir/event"}
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+  <dl>
+    <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY}</dt>
+      <dd>A boolean specifying whether this is an all-day event.</dd>
+    <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME}</dt>
+      <dd>The start time of the event (milliseconds since epoch).</dd>
+    <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME}</dt>
+      <dd>The end time of the event (milliseconds since epoch).</dd>
+    <dt>{@link android.provider.CalendarContract.EventsColumns#TITLE}</dt>
+      <dd>The event title.</dd>
+    <dt>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</dt>
+      <dd>The event description.</dd>
+    <dt>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</dt>
+      <dd>The event location.</dd>
+    <dt>{@link android.content.Intent#EXTRA_EMAIL}</dt>
+      <dd>A comma-separated list of email addresses that specify the invitees.</dd>
+  </dl>
+  <p>Many more event details can be specified using the constants defined in the
+  {@link android.provider.CalendarContract.EventsColumns} class.</p>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void addEvent(String title, String location, Calendar begin, Calendar end) {
+    Intent intent = new Intent(Intent.ACTION_INSERT)
+            .setData(Events.CONTENT_URI)
+            .putExtra(Events.TITLE, title)
+            .putExtra(Events.EVENT_LOCATION, location)
+            .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin)
+            .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end);
+    if (intent.resolveActivity(getPackageManager()) != null) {
+        startActivity(intent);
+    }
+}
+</pre>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+&lt;activity ...>
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.INSERT" />
+        &lt;data android:mimeType="vnd.android.cursor.dir/event" />
+        &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+
+
+
+
+
+
+
+
+
+
+
+
+
 <h2 id="Camera">Camera</h2>
 
 
@@ -211,6 +509,7 @@
 
 
 
+
 <h2 id="Contacts">Contacts/People App</h2>
 
 
@@ -427,7 +726,7 @@
 <dd>The type is inferred from contact URI.
 </dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>One or more of the extras defined in {@link android.provider.ContactsContract.Intents.Insert}
 so you can populate fields of the contact details.
 </dd>
@@ -469,7 +768,7 @@
 <dt><b>MIME Type</b></dt>
 <dd>{@link android.provider.ContactsContract.Contacts#CONTENT_TYPE Contacts.CONTENT_TYPE}</dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>One or more of the extras defined in {@link android.provider.ContactsContract.Intents.Insert}.
 </dd>
 </dl>
@@ -523,7 +822,7 @@
   </dl>
 </dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>
   <dl>
     <dt>{@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</dt>
@@ -648,7 +947,7 @@
 <dd>The MIME type corresponding to the file type the user should select.
 </dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>
   <dl>
     <dt>{@link android.content.Intent#EXTRA_ALLOW_MULTIPLE}
@@ -768,7 +1067,7 @@
 <dd>The MIME type corresponding to the file type the user should select.
 </dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>
   <dl>
     <dt>{@link android.content.Intent#EXTRA_MIME_TYPES}
@@ -1139,7 +1438,7 @@
   </dl>
 </dd>
 
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
 <dd>
   <dl>
     <dt><code>"subject"</code></dt>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 73d5b74..0a234aa 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -368,7 +368,10 @@
                   <span class="en">Media Playback</span></a>
                 </li>
             <li><a href="<?cs var:toroot ?>guide/topics/media/mediarouter.html">
-                  <span class="en">MediaRouter</span></a>
+                  <span class="en">Media Router</span></a>
+                </li>
+            <li><a href="<?cs var:toroot ?>guide/topics/media/mediarouteprovider.html">
+                  <span class="en">Media Route Provider</span></a>
                 </li>
             <li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
                    <span class="en">Supported Media Formats</span></a>
diff --git a/docs/html/guide/topics/media/mediarouteprovider.jd b/docs/html/guide/topics/media/mediarouteprovider.jd
new file mode 100644
index 0000000..389fbfb
--- /dev/null
+++ b/docs/html/guide/topics/media/mediarouteprovider.jd
@@ -0,0 +1,453 @@
+page.title=Media Route Provider
+page.tags="mediarouteprovider","mediacontrolintent"
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>In this document</h2>
+    <ol>
+      <li><a href="#overview">Overview</a>
+        <ol>
+          <li><a href="#dist">Distribution of route providers</a></li>
+          <li><a href="#playback-types">Types of playback</a></li>
+          <li><a href="#mr-packages">Media router packages</a></li>
+        </ol>
+      </li>
+      <li><a href="#provider-service">Creating a Provider Service</a></li>
+      <li><a href="#route-caps">Specifying Route Capabilities</a>
+        <ol>
+          <li><a href="#route-cat">Route categories</a></li>
+          <li><a href="#media-types">Media types and protocols</a></li>
+          <li><a href="#playback-ctrls">Playback controls</a></li>
+          <li><a href="#mrpd">MediaRouteProviderDescriptor</a></li>
+        </ol>
+      </li>
+      <li><a href="#ctrl-routes">Controlling Routes</a></li>
+    </ol>
+    <h2>Key Classes</h2>
+    <ol>
+      <li>{@link android.support.v7.media.MediaRouteProvider}</li>
+      <li>{@link android.support.v7.media.MediaRouteProviderDescriptor}</li>
+      <li>{@link android.support.v7.media.MediaRouteProvider.RouteController RouteController}</li>
+    </ol>
+    <h2>Related Samples</h2>
+    <ol>
+      <li><a href="{@docRoot}samples/MediaRouter/index.html">MediaRouter</a></li>
+    </ol>
+  </div>
+</div>
+
+<p>Users want to play media content from their Android devices bigger, brighter, and louder on
+  connected playback devices such as televisions, stereos,
+  and home theater equipment. As a manufacturer of these devices, allowing Android users to
+  instantly show a picture, play a song, or share a video for friends and family using your product
+  can make it much more compelling and engaging.</p>
+
+<p>The Android media router framework allows manufacturers to enable playback on their devices
+  through a standardized interface called a {@link android.support.v7.media.MediaRouteProvider}.
+  A route provider defines a common interface for playing media on a receiver device, making it
+  possible to play media on your equipment from any Android application that supports media
+  routes.</p>
+
+<p>This guide discusses how to create a media route provider for a receiver device and make it
+  available to other media playback applications that run on Android.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>The Android media router framework enables media app developers and media playback device
+  manufacturers to connect through a common API and common user interface. App developers that
+  implement a {@link android.support.v7.media.MediaRouter} interface can then connect to the
+  framework and play content to devices that participate in the media router framework. Media
+  playback device manufacturers can participate in the framework by publishing a {@link
+  android.support.v7.media.MediaRouteProvider} that allows other applications to connect to and
+  play media on the receiver devices. Figure 1 illustrates how an app connects to a receiving
+  device through the media router framework.</p>
+
+<img src="{@docRoot}images/mediarouter/media-route-provider-framework.png" alt="" id="figure1"/>
+<p class="img-caption">
+  <strong>Figure 1.</strong> Overview of how media route provider classes provide communication
+  from a media app to a receiver device.
+</p>
+
+<p>When you build a media route provider for your receiver device, the provider serves the
+following purposes:</p>
+
+<ul>
+  <li>Describe and publish the capabilities of the receiver device so other apps can discover it
+    and use its playback features.</li>
+  <li>Wrap the programming interface of the receiver device and its communication
+    transport mechanisms to make the device compatible with the media router framework.</li>
+</ul>
+
+
+<h3 id="dist">Distribution of route providers</h3>
+
+<p>A media route provider is distributed as part of an Android app. Your route provider can be
+  made available to other apps by extending
+  {@link android.support.v7.media.MediaRouteProviderService} or wrapping your implementation of
+  {@link android.support.v7.media.MediaRouteProvider} with your own service and declaring an intent
+  filter for the media route provider. These steps allow other apps to discover and make use of
+  your media route.</p>
+
+<p>
+  <strong>Note:</strong> The app containing the media route provider can also include a
+  <a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a> interface to the
+  route provider, but this is not required.
+</p>
+
+
+<h3 id="playback-types">Types of playback</h3>
+
+<p>There are two main types of playback supported by the media router framework. A media route
+  provider can support one or both types of playback, depending on the capabilities of your playback
+  equipment and the functionality you want to support:</p>
+
+<ul>
+  <li><strong>Remote Playback</strong> — This approach uses the receiver device to handle the
+    content data retrieval, decoding, and playback, while an Android device in the user's hand is
+    used as a remote control. This approach is used by Android apps that support
+    <a href="https://developers.google.com/cast/">Google Cast</a>.</li>
+  <li><strong>Secondary Output</strong> — With this approach, the Android media application
+    retrieves, renders and streams video or music directly to the receiver device. This approach is
+    used to support Wireless Display output on Android.</li>
+</ul>
+
+
+<h3 id="mr-packages">Media router packages</h3>
+
+<p>
+  The media router APIs are provided as part of the Android Support Library version 18 and higher,
+  in the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
+  support library. You should use the classes in the
+  {@link android.support.v7.media} package for media route provider functions.
+  These APIs are compatible with devices running Android 2.1 (API level 7) and higher.
+</p>
+
+<p class="caution">
+  <strong>Caution:</strong> There is another set of media router APIs provided in the
+  {@link android.media} class package that have been superseded by the
+  <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
+  support library. You <em>should not</em> use the {@link android.media} classes for
+  implementing media route provider functions.
+</p>
+
+<p>In order to use the {@link android.support.v7.media} media router classes, you
+  must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter"
+  >v7-mediarouter support library package</a> to your app development project. For more
+  information on adding support libraries to your app development project, see
+  <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
+</p>
+
+
+<h2 id="provider-service">Creating a Provider Service</h2>
+
+<p>The media router framework must be able to discover and connect to your media route provider
+  to allow other applications to use your route. In order to do this, the media router framework
+  looks for apps that declare a media route provider intent action. When another app wants to
+  connect to your provider, the framework must be able to invoke and connect to it, so your provider
+  must be encapsulated in a {@link android.app.Service}.</p>
+
+<p>The following example code shows the declaration of a media route provider service and the
+  intent filter in a manifest, which allows it to be discovered and used by the media router
+  framework:</p>
+
+<pre>
+&lt;service android:name=".provider.SampleMediaRouteProviderService"
+    android:label="&#64;string/sample_media_route_provider_service"
+    android:process=":mrp"&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.media.MediaRouteProviderService" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/service&gt;
+</pre>
+
+<p>This manifest example declares a service that wraps the actual media route provider classes.
+  The Android media router framework provides the
+  {@link android.support.v7.media.MediaRouteProviderService} class for use as a service wrapper for
+  media route providers. The following example code demonstrates how to use this wrapper
+  class:</p>
+
+<pre>
+public class SampleMediaRouteProviderService extends MediaRouteProviderService {
+
+    &#64;Override
+    public MediaRouteProvider onCreateMediaRouteProvider() {
+        return new SampleMediaRouteProvider(this);
+    }
+}
+</pre>
+
+
+<h2 id="route-caps">Specifying Route Capabilities</h2>
+
+<p>Apps connecting to the media router framework can discover your media route through your
+  app's manifest declarations, but they also need to know the capabilities of the media routes you
+  are providing. Media routes can be of different types and have different features, and other apps
+  need to be able to discover these details to determine if they are compatible with your route.</p>
+
+<p>The media router framework allows you to define and publish the capabilities of your media
+  route through {@link android.content.IntentFilter} objects, {@link
+  android.support.v7.media.MediaRouteDescriptor} objects and a {@link
+  android.support.v7.media.MediaRouteProviderDescriptor}. This section explains how to use these
+  classes to publish the details of your media route for other apps.</p>
+
+
+<h3 id="route-cat">Route categories</h3>
+
+<p>As part of the programmatic description of your media route provider, you must specify
+  whether your provider supports remote playback, secondary output, or both. These are the route
+  categories provided by the media router framework:</p>
+
+<ul>
+  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_AUDIO CATEGORY_LIVE_AUDIO}
+    &mdash; Output of audio to a secondary output device, such as a wireless-enabled music system.
+    </li>
+  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_VIDEO CATEGORY_LIVE_VIDEO}
+    &mdash; Output of video to a secondary output device, such as Wireless Display devices.</li>
+  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
+    CATEGORY_REMOTE_PLAYBACK} &mdash; Play video or audio on a separate device which handles media
+    retrieval, decoding, and playback, such as
+    <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
+    </li>
+</ul>
+
+<p>In order to include these settings in a description of your media route, you insert them into
+  an {@link android.content.IntentFilter} object, which you later add to a
+  {@link android.support.v7.media.MediaRouteDescriptor} object:</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
+    static {
+        IntentFilter videoPlayback = new IntentFilter();
+        <strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong>
+        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
+        CONTROL_FILTERS_BASIC.add(videoPlayback);
+    }
+}
+
+</pre>
+
+<p>If you specify the {@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
+  CATEGORY_REMOTE_PLAYBACK} intent, you must also define what media types and
+  playback controls are supported by your media route provider. The next section describes how to
+  specify these settings for your device.</p>
+
+
+<h3 id="media-types">Media types and protocols</h3>
+
+<p>A media route provider for a remote playback device must specify the media types and transfer
+  protocols it supports. You specify these settings using the {@link android.content.IntentFilter}
+  class and the {@link android.content.IntentFilter#addDataScheme addDataScheme()} and
+  {@link android.content.IntentFilter#addDataType addDataType()} methods of that object. The
+  following code snippet demonstrates how to define an intent filter for supporting remote video
+  playback using http, https, and Real Time Streaming Protocol (RTSP):</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+
+    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
+
+    static {
+        IntentFilter videoPlayback = new IntentFilter();
+        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
+        videoPlayback.addDataScheme("http");
+        videoPlayback.addDataScheme("https");
+        videoPlayback.addDataScheme("rtsp");
+        addDataTypeUnchecked(videoPlayback, "video/*");
+        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
+        CONTROL_FILTERS_BASIC.add(videoPlayback);
+    }
+    ...
+
+    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
+        try {
+            filter.addDataType(type);
+        } catch (MalformedMimeTypeException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
+
+</pre>
+
+
+<h3 id="playback-ctrls">Playback controls</h3>
+
+<p>A media route provider that offers remote playback must specify the types of media controls
+  it supports. These are the general types of control that media routes can provide:</p>
+
+<ul>
+  <li><strong>Playback controls</strong>, such as play, pause, rewind, and fast-forward.</li>
+  <li><strong>Queuing features</strong>, which allow the sending app to add and remove items
+    from a playlist which is maintained by the receiver device.</li>
+  <li><strong>Session features</strong>, which prevent sending apps from interfering with each
+    other by having the receiver device provide a session id to the requesting app and then checking
+    that id with each subsequent playback control request.</li>
+</ul>
+
+<p>The following code example demonstrates how to construct an intent filter for supporting
+  basic media route playback controls:</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
+    static {
+        ...
+        IntentFilter playControls = new IntentFilter();
+        playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+        playControls.addAction(MediaControlIntent.ACTION_SEEK);
+        playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
+        playControls.addAction(MediaControlIntent.ACTION_PAUSE);
+        playControls.addAction(MediaControlIntent.ACTION_RESUME);
+        playControls.addAction(MediaControlIntent.ACTION_STOP);
+        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
+        CONTROL_FILTERS_BASIC.add(videoPlayback);
+        CONTROL_FILTERS_BASIC.add(playControls);
+    }
+    ...
+}
+</pre>
+
+<p>For more information about the available playback control intents, see the
+  {@link android.support.v7.media.MediaControlIntent} class.</p>
+
+
+<h3 id="mrpd">MediaRouteProviderDescriptor</h3>
+
+<p>After defining the capabilities of your media route using {@link
+  android.content.IntentFilter} objects, you can then create a descriptor object for publishing to
+  the Android media router framework. This descriptor object contains the specifics of your media
+  route's capabilities so that other applications can determine how to interact with your media
+  route.</p>
+
+<p>The following example code demonstrates how to add the previously created intent filters to a
+  {@link android.support.v7.media.MediaRouteProviderDescriptor} and set the descriptor for use by
+  the media router framework:</p>
+
+<pre>
+public SampleMediaRouteProvider(Context context) {
+    super(context);
+    publishRoutes();
+}
+
+private void publishRoutes() {
+    Resources r = getContext().getResources();
+    // Create a route descriptor using previously created IntentFilters
+    MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
+            VARIABLE_VOLUME_BASIC_ROUTE_ID,
+            r.getString(R.string.variable_volume_basic_route_name))
+            .setDescription(r.getString(R.string.sample_route_description))
+            .addControlFilters(CONTROL_FILTERS_BASIC)
+            .setPlaybackStream(AudioManager.STREAM_MUSIC)
+            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
+            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
+            .setVolumeMax(VOLUME_MAX)
+            .setVolume(mVolume)
+            .build();
+    // Add the route descriptor to the provider descriptor
+    MediaRouteProviderDescriptor providerDescriptor =
+            new MediaRouteProviderDescriptor.Builder()
+            .addRoute(routeDescriptor)
+            .build();
+
+    // Publish the descriptor to the framework
+    setDescriptor(providerDescriptor);
+}
+</pre>
+
+<p>For more information on the available descriptor settings, see the reference documentation
+  for {@link android.support.v7.media.MediaRouteDescriptor} and {@link
+  android.support.v7.media.MediaRouteProviderDescriptor}.</p>
+
+
+<h2 id="ctrl-routes">Controlling Routes</h2>
+
+<p>When an application connects to your media route provider, the provider receives playback
+  commands through the media router framework sent to your route by other apps. To handle these
+  requests, you must provide an implementation of a {@link
+  android.support.v7.media.MediaRouteProvider.RouteController} class, which processes the commands
+  and handles the actual communication to your receiver device.</p>
+
+<p>The media router framework calls the {@link
+  android.support.v7.media.MediaRouteProvider#onCreateRouteController onCreateRouteController()}
+  method of your route provider to obtain an instance of this class and then routes requests to it.
+  These are the key methods of the {@link
+  android.support.v7.media.MediaRouteProvider.RouteController} class, which you must implement for
+  your media route provider:</p>
+
+<ul>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSelect onSelect()}
+    &mdash; Called when an application selects your route for playback. You use this method to do
+    any preparation work that may be required before media playback begins.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest
+    onControlRequest()} &mdash; Sends specific playback commands to the receiving device.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume
+    onSetVolume()} &mdash; Sends a request to the receiving device to set the playback volume to a
+    specific value.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUpdateVolume
+    onUpdateVolume()} &mdash; Sends a request to the receiving device to modify the playback
+    volume by a specified amount.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUnselect
+    onUnselect()} &mdash; Called when an application unselects a route.</li>
+  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()}
+    &mdash; Called when the route is no longer needed by the framework, allowing it to free its
+    resources.</li>
+</ul>
+
+<p>All playback control requests, except for volume changes, are directed to the {@link
+  android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest onControlRequest()}
+  method. Your implementation of this method must parse the control requests and respond to them
+  appropriately. Here is an example implementation of this method which processes commands for a
+  remote playback media route:</p>
+
+<pre>
+private final class SampleRouteController extends
+        MediaRouteProvider.RouteController {
+    ...
+
+    &#64;Override
+    public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
+
+        String action = intent.getAction();
+
+        if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+            boolean success = false;
+            if (action.equals(MediaControlIntent.ACTION_PLAY)) {
+                success = handlePlay(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
+                success = handleEnqueue(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
+                success = handleRemove(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
+                success = handleSeek(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
+                success = handleGetStatus(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
+                success = handlePause(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
+                success = handleResume(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
+                success = handleStop(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
+                success = handleStartSession(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
+                success = handleGetSessionStatus(intent, callback);
+            } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
+                success = handleEndSession(intent, callback);
+            }
+
+            Log.d(TAG, mSessionManager.toString());
+            return success;
+        }
+        return false;
+    }
+    ...
+}
+</pre>
+
+<p>It is important to understand that the {@link
+  android.support.v7.media.MediaRouteProvider.RouteController} class is intended to act as a wrapper
+  for the API to your media playback equipment. The implementation of the methods in this class is
+  entirely dependent on the programmatic interface provided by your receiving device.</p>
diff --git a/docs/html/guide/topics/media/mediarouter.jd b/docs/html/guide/topics/media/mediarouter.jd
index 1b10265..e0bf889 100644
--- a/docs/html/guide/topics/media/mediarouter.jd
+++ b/docs/html/guide/topics/media/mediarouter.jd
@@ -1,5 +1,5 @@
-page.title=MediaRouter
-page.tags="cast","chromecast","wireless display","miracast"
+page.title=Media Router
+page.tags="mediarouter","cast","chromecast","wireless display","miracast"
 @jd:body
 
 <div id="qv-wrapper">
@@ -36,6 +36,10 @@
       <li>{@link android.support.v7.media.MediaRouter.Callback}</li>
       <li>{@link android.support.v7.media.MediaRouteProvider}</li>
     </ol>
+    <h2>Related Samples</h2>
+    <ol>
+      <li><a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a></li>
+    </ol>
   </div>
 </div>
 
@@ -105,15 +109,17 @@
   (API level 7) and higher.
 </p>
 
-<p class="note">
-  <strong>Note:</strong> There is another set of media router APIs provided in the
+<p class="caution">
+  <strong>Caution:</strong> There is another set of media router APIs provided in the
   {@link android.media} that have been superseded by the v7-mediarouter support library.
   You <em>should not</em> use the {@link android.media} classes for media router functions.
 </p>
 
 <p>In order to use the {@link android.support.v7.media} media router classes, you must add
   the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter
-  support library package</a> to your app development project.
+  support library package</a> to your app development project.  For more
+  information on adding support libraries to your app development project, see
+  <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
 </p>
 
 
@@ -211,9 +217,9 @@
     CATEGORY_LIVE_VIDEO} &mdash; Output of video to a secondary output device, such as Wireless
     Display devices.</li>
   <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
-    CATEGORY_REMOTE_PLAYBACK} &mdash; Play video or audio on a separate device that supports the
-    <a href="https://developers.google.com/cast/">Google Cast</a> remote control protocol, such
-    as <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a>.
+    CATEGORY_REMOTE_PLAYBACK} &mdash; Play video or audio on a separate device that handles media
+    retrieval, decoding, and playback, such as
+    <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
     </li>
 </ul>
 
@@ -279,7 +285,7 @@
 <p>In order to connect to a media route selected by the user, your app must obtain the {@link
   android.support.v7.media.MediaRouter} framework object and then attach a {@link
   android.support.v7.media.MediaRouter.Callback} object. The callback object receives messages
-  from the media router framework when a route selected, changed or disconnected by the user.</p>
+  from the media router framework when a route is selected, changed, or disconnected by the user.</p>
 
 <p>To obtain an instance of the {@link android.support.v7.media.MediaRouter} framework object,
   call {@link android.support.v7.media.MediaRouter#getInstance MediaRouter.getInstance()}
@@ -299,11 +305,11 @@
 <p>The media router framework communicates with an app through a callback object that
   you attach to the {@link android.support.v7.media.MediaRouter} framework object. An app
   that uses the media router framework must extend the {@link
-  android.support.v7.media.MediaRouter.Callback} object to receive messages when a media route is
-  connected and provide content to the connected device through that route.</p>
+  android.support.v7.media.MediaRouter.Callback} object in order to receive messages when a
+  media route is connected.</p>
 
-<p>There are several methods in the callback that can be overwritten to receive messages about
-  media router events. At the minimum, your implementation of the {@link
+<p>There are several methods in the callback that you can override to receive information about
+  media router events. At minimum, your implementation of the {@link
   android.support.v7.media.MediaRouter.Callback} class should override the following
   methods:</p>
 
@@ -440,12 +446,12 @@
 
 <p class="note">
   <strong>Note:</strong> The media route framework also provides a
-  {@link android.support.v7.app.MediaRouteDiscoveryFragment} class which takes care of adding and
-  removing the call back for an activity.
+  {@link android.support.v7.app.MediaRouteDiscoveryFragment} class, which takes care of adding and
+  removing the callback for an activity.
 </p>
 
 <p>Now when you run your application, you should see a Cast button appear in your activity.
-  When you press the button the media router framework, a route selection dialog appears as shown
+  When you touch the button, a route selection dialog appears as shown
   in figure 3, allowing your user to select an available media route. Make sure you have a
   supported device available on your local network when testing this interface.</p>
 
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index aec7fa7..bf16630 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -562,6 +562,7 @@
         <code>desk</code><br/>
         <code>television<br/>
         <code>appliance</code>
+        <code>watch</code>
       </td>
       <td>
         <ul class="nolist">
@@ -573,8 +574,9 @@
           non-pointer interaction</li>
           <li>{@code appliance}: Device is serving as an appliance, with
           no display</li>
+          <li>{@code watch}: Device has a display and is worn on the wrist</li>
         </ul>
-        <p><em>Added in API level 8, television added in API 13.</em></p>
+        <p><em>Added in API level 8, television added in API 13, watch added in API 20.</em></p>
         <p>For information about how your app can respond when the device is inserted into or
         removed from a dock, read <a 
         href="{@docRoot}training/monitoring-device-state/docking-monitoring.html">Determining
diff --git a/docs/html/images/mediarouter/media-route-provider-framework.png b/docs/html/images/mediarouter/media-route-provider-framework.png
new file mode 100644
index 0000000..60cc29a
--- /dev/null
+++ b/docs/html/images/mediarouter/media-route-provider-framework.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index d645246..99a469a 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -1,5 +1,5 @@
 fullpage=true
-page.viewport-width=970
+page.viewport_width=970
 no_footer_links=true
 carousel=true
 excludeFromSuggestions=true
diff --git a/docs/html/sdk/installing/studio-build.jd b/docs/html/sdk/installing/studio-build.jd
index 41ad5de..2a616a0 100644
--- a/docs/html/sdk/installing/studio-build.jd
+++ b/docs/html/sdk/installing/studio-build.jd
@@ -1,4 +1,4 @@
-page.title=Building your Project
+page.title=Building Your Project with Gradle
 
 @jd:body
 
@@ -23,6 +23,7 @@
             <li><a href="#addLibModule">Add a library module</a></li>
             <li><a href="#buildProject">Build the project</a></li>
             <li><a href="#buildCmd">Build from the command line</a></li>
+            <li><a href="#buildRelease">Build a release version</a></li>
         </ol>
     </li>
     <li><a href="#configBuild">Configure the Build</a>
@@ -463,6 +464,24 @@
 </pre>
 
 
+<h3 id="buildRelease">Build a release version</h3>
+
+<p>You can build the release version of your application from the command line or using Android
+Studio. To build it from the command line, invoke the <code>assembleRelease</code> build task using
+the Gradle wrapper script (<code>gradlew assembleRelease</code>). To build it from Android
+Studio:</p>
+
+<ol>
+    <li>Click <strong>Gradle</strong> on the right side of the IDE window.</li>
+    <li>On the <em>All tasks</em> section of the sidebar that appears, expand
+        <strong>BuildSystemExample</strong>.</li>
+    <li>Expand <strong>:app</strong> and double-click <strong>assembleRelease</strong>.</li>
+</ol>
+
+<p>You can use this procedure to invoke any build task from Android Studio.</p>
+
+
+
 <h2 id="configBuild">Configure the Build</h2>
 
 <p>This section uses the <code>BuildSystemExample</code> project from the previous section and
@@ -643,20 +662,6 @@
 <code>proguard-rules.txt</code> at the root of the module, where you can add custom ProGuard
 rules.</p>
 
-<p>You can build the release version of your application from the command line or using Android
-Studio. To build it from the command line, invoke the <code>assembleRelease</code> build task using
-the Gradle wrapper script (<code>gradlew assembleRelease</code>). To build it from Android
-Studio:</p>
-
-<ol>
-    <li>Click <strong>Gradle</strong> on the right side of the IDE window.</li>
-    <li>On the <em>All tasks</em> section of the sidebar that appears, expand
-        <strong>BuildSystemExample</strong>.</li>
-    <li>Expand <strong>:app</strong> and double-click <strong>assembleRelease</strong>.</li>
-</ol>
-
-<p>You can use this procedure to invoke any build task from Android Studio.</p>
-
 <h3 id="configureSigning">Configure signing settings</h3>
 
 <p>The debug and the release versions of the app differ on whether the application can be
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index a1fb817..ccd5903 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -30,9 +30,8 @@
 you don't yet have a device, check with the service providers in your area to determine which
 Android-powered devices are available.</p>
 
-<p>If you want a SIM-unlocked phone, then you might consider a Nexus phone. To find a place
-to purchase the Nexus S and other Android-powered devices, visit <a
-href="http://www.google.com/phone/detail/nexus-s">google.com/phone</a>.</p>
+<p>If you want a SIM-unlocked phone, then you might consider a Nexus phone. To purchase a
+Nexus phone, visit the <a href="https://play.google.com/store/devices">Google Play</a> store.</p>
 
 <p class="note"><strong>Note:</strong> When developing on a device, keep in mind that you should
 still use the <a
@@ -90,11 +89,11 @@
             <p>Use this format to add each vendor to the file:<br/>
               <code>SUBSYSTEM==&quot;usb&quot;, ATTR{idVendor}==&quot;0bb4&quot;, MODE=&quot;0666&quot;, GROUP=&quot;plugdev&quot;</code>
               <br /><br />
-              
+
               In this example, the vendor ID is for HTC. The <code>MODE</code>
 assignment specifies read/write permissions, and <code>GROUP</code> defines
 which Unix group  owns the device node. </p>
-            
+
             <p class="note"><strong>Note:</strong> The rule syntax
 may vary slightly depending on your  environment. Consult the <code>udev</code>
 documentation for your system as needed. For an overview of rule syntax, see
@@ -138,7 +137,7 @@
 
 <p>This table provides a reference to the vendor IDs needed in order to add USB
 device support on Linux. The USB Vendor ID is the value given to the
-<code>ATTR{idVendor}</code> property in the rules file, as described 
+<code>ATTR{idVendor}</code> property in the rules file, as described
 above.</p>
 
 <table>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 0e543e4..c281644 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -37,7 +37,7 @@
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
               Using the Layout Editor</a></li>
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
-              Building your Project</a></li>
+              Building Your Project with Gradle</a></li>
           </ul>
       </li>
       <li><a href="<?cs var:toroot ?>sdk/exploring.html">
diff --git a/docs/html/training/basics/actionbar/styling.jd b/docs/html/training/basics/actionbar/styling.jd
index 1f76e03..4128a97 100644
--- a/docs/html/training/basics/actionbar/styling.jd
+++ b/docs/html/training/basics/actionbar/styling.jd
@@ -144,13 +144,13 @@
 &lt;resources>
     &lt;!-- the theme applied to the application or activity -->
     &lt;style name="CustomActionBarTheme"
-           parent="&#64;style/Theme.Holo.Light.DarkActionBar">
+           parent="&#64;android:style/Theme.Holo.Light.DarkActionBar">
         &lt;item name="android:actionBarStyle">&#64;style/MyActionBar&lt;/item>
     &lt;/style>
 
     &lt;!-- ActionBar styles -->
     &lt;style name="MyActionBar"
-           parent="&#64;style/Widget.Holo.Light.ActionBar.Solid.Inverse">
+           parent="&#64;android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
         &lt;item name="android:background">&#64;drawable/actionbar_background&lt;/item>
     &lt;/style>
 &lt;/resources>
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 50485db..c4cb362 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -10,9 +10,9 @@
 
 
 <!-- This is the training bar -->
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
+<div id="tb-wrapper">
+<div id="tb">
+
 <h2>This lesson teaches you to</h2>
 
 <ol>
@@ -27,10 +27,10 @@
 SDK</a></li>
   <li><a href="{@docRoot}tools/projects/index.html">Managing Projects</a></li>
 </ul>
- 
- 
-</div> 
-</div> 
+
+
+</div>
+</div>
 
 <p>An Android project contains all the files that comprise the source code for your Android
 app. The Android SDK tools make it easy to start a new Android project with a set of
@@ -42,7 +42,7 @@
 
 <p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if
 you're using Eclipse, you should also have the <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
-plugin</a> installed (version 21.0.0 or higher). If you don't have these, follow the guide to <a
+plugin</a> installed (version 22.6.2 or higher). If you don't have these, follow the guide to <a
 href="{@docRoot}sdk/installing/index.html">Installing the Android SDK</a> before you start this
 lesson.</p>
 
@@ -50,7 +50,7 @@
 <h2 id="Eclipse">Create a Project with Eclipse</h2>
 
 <ol>
-  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png" 
+  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
   style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
   <li>In the window that appears, open the <strong>Android</strong> folder,
   select <strong>Android Application Project</strong>, and click <strong>Next</strong>.</li>
@@ -116,11 +116,11 @@
   <li>Now you can select an activity template from which to begin building your app.
     <p>For this project, select <strong>BlankActivity</strong> and click <strong>Next</strong>.</p>
   </li>
-  <li>Leave all the details for the activity in their default state and click 
+  <li>Leave all the details for the activity in their default state and click
     <strong>Finish</strong>.</li>
 </ol>
 
-<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
 To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 
@@ -155,7 +155,7 @@
 projects.</p></li>
 </ol>
 
-<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
 To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 <p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index 4c1a0dc3..1b49096 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -8,21 +8,21 @@
 
 @jd:body
 
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
-<h2>Dependencies and prerequisites</h2> 
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
 
 <ul>
   <li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
-  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 20.0.0 or higher
+  <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 22.6.2 or higher
     (if you're using Eclipse)</li>
 </ul>
- 
-</div> 
-</div> 
- 
-<p>Welcome to Android application development!</p> 
+
+</div>
+</div>
+
+<p>Welcome to Android application development!</p>
 
 <p>This class teaches you how to build your first Android app. You’ll learn how to create an Android
 project and run a debuggable version of the app. You'll also learn some fundamentals of Android app
@@ -36,6 +36,10 @@
   <li>Download the latest SDK tools and platforms using the SDK Manager.</li>
 </ol>
 
+<p class="note"><strong>Note:</strong> Make sure you install the most recent versions of the ADT
+plugin and the Android SDK before you start this class. The procedures described in this class may
+not apply to earlier versions.</p>
+
 <p>If you haven't already done these tasks, start by downloading the
   <a href="{@docRoot}sdk/index.html">Android SDK</a> and following the install steps.
   Once you've finished the setup, you're ready to begin this class.</p>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 9aa25a3..27d2c10 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -10,9 +10,9 @@
 
 
 <!-- This is the training bar -->
-<div id="tb-wrapper"> 
-<div id="tb"> 
- 
+<div id="tb-wrapper">
+<div id="tb">
+
 <h2>This lesson teaches you to</h2>
 
 <ol>
@@ -30,10 +30,10 @@
   <li><a href="{@docRoot}sdk/installing/index.html">Installing the
 SDK</a></li>
 </ul>
- 
- 
-</div> 
-</div> 
+
+
+</div>
+</div>
 
 
 
@@ -151,7 +151,7 @@
 </pre>
 
 <p class="note"><strong>Note:</strong>
-You now need an import statement for <code>android.widget.EditText</code>. 
+You now need an import statement for <code>android.widget.EditText</code>.
 You'll define the <code>EXTRA_MESSAGE</code> constant in a moment.</p>
 
 <p>An {@link android.content.Intent} can carry a collection of various data types as key-value
@@ -212,7 +212,7 @@
 <p>To create a new activity using Eclipse:</p>
 
 <ol>
-  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png" 
+  <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
   style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
   <li>In the window that appears, open the <strong>Android</strong> folder
   and select <strong>Android Activity</strong>. Click <strong>Next</strong>.</li>
@@ -247,15 +247,19 @@
   <li>There's also an implementation of {@link android.app.Activity#onOptionsItemSelected
   onOptionsItemSelected()} which handles the behavior for the action bar's <em>Up</em> behavior.
   Keep this one the way it is.</li>
-  <li>There's also a <code>PlaceholderFragment</code> class that extends 
+  <li>There's also a <code>PlaceholderFragment</code> class that extends
 {@link android.app.Fragment}. You will not need this class in the final version of this
 activity.</li>
 </ul>
 
-<p>Fragments decompose application functionality and UI into reusable modules. For more 
-information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments 
+<p>Fragments decompose application functionality and UI into reusable modules. For more
+information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments
 API Guide</a>. The final version of this activity does not use fragments.</p>
 
+<p class="note"><strong>Note:</strong> Your activity may look different if you did not use
+the latest version of the ADT plugin. Make sure you install the latest version of the
+<a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT plugin</a> to complete this tutorial.</p>
+
 <p>The {@code DisplayMessageActivity} class should now look like this:</p>
 
 <pre>
diff --git a/docs/html/training/game-controllers/controller-input.jd b/docs/html/training/game-controllers/controller-input.jd
index 2c50ae1..c9517ba 100644
--- a/docs/html/training/game-controllers/controller-input.jd
+++ b/docs/html/training/game-controllers/controller-input.jd
@@ -236,26 +236,33 @@
   </tr>
   <tr>
     <td>Start game in main menu, or pause/unpause during game</td>
-    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_START BUTTON_START}</td>
+    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_START BUTTON_START}<sup>*</sup></td>
   </tr>
   <tr>
     <td>Display menu</td>
-    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_SELECT BUTTON_SELECT} and
-{@link android.view.KeyEvent#KEYCODE_MENU}</td>
+    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_SELECT BUTTON_SELECT}<sup>*</sup>
+      and {@link android.view.KeyEvent#KEYCODE_MENU}<sup>*</sup></td>
   </tr>
   <tr>
     <td>Same as Android <em>Back</em></td>
-    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_B BUTTON_B}<sup>*</sup> and
-{@link android.view.KeyEvent#KEYCODE_BACK KEYCODE_BACK}</td>
+    <td>{@link android.view.KeyEvent#KEYCODE_BACK KEYCODE_BACK}</td>
+  </tr>
+  <tr>
+    <td>Navigate back to a previous item in a menu</td>
+    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_B BUTTON_B}<sup>**</sup></td>
   </tr>
   <tr>
     <td>Confirm selection, or perform primary game action</td>
-    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_A BUTTON_A}<sup>*</sup> and
+    <td>{@link android.view.KeyEvent#KEYCODE_BUTTON_A BUTTON_A}<sup>**</sup> and
 {@link android.view.KeyEvent#KEYCODE_DPAD_CENTER DPAD_CENTER}</td>
   </tr>
 </table>
 <p>
-<em>* This could be the opposite button (A/B), depending on the locale that
+<em>* Your game should not rely on the presence of the Start, Select, or Menu
+  buttons.</em>
+</p>
+<p>
+<em>** This could be the opposite button (A/B), depending on the locale that
 you are supporting.</em>
 </p>
 
diff --git a/docs/html/training/notify-user/display-progress.jd b/docs/html/training/notify-user/display-progress.jd
index 2b2b3ae..c00576c 100644
--- a/docs/html/training/notify-user/display-progress.jd
+++ b/docs/html/training/notify-user/display-progress.jd
@@ -80,6 +80,7 @@
     setProgress(0, 0, false)}. For example:
 </p>
 <pre>
+int id = 1;
 ...
 mNotifyManager =
         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -100,7 +101,7 @@
                     // state
                     mBuilder.setProgress(100, incr, false);
                     // Displays the progress bar for the first time.
-                    mNotifyManager.notify(0, mBuilder.build());
+                    mNotifyManager.notify(id, mBuilder.build());
                         // Sleeps the thread, simulating an operation
                         // that takes time
                         try {
@@ -114,7 +115,7 @@
             mBuilder.setContentText("Download complete")
             // Removes the progress bar
                     .setProgress(0,0,false);
-            mNotifyManager.notify(ID, mBuilder.build());
+            mNotifyManager.notify(id, mBuilder.build());
         }
     }
 // Starts the thread by calling the run() method in its Runnable
@@ -157,7 +158,7 @@
 // percentage, and "determinate" state
 mBuilder.setProgress(100, incr, false);
 // Issues the notification
-mNotifyManager.notify(0, mBuilder.build());
+mNotifyManager.notify(id, mBuilder.build());
 </pre>
 <p>
     Replace the lines you've found with the following lines. Notice that the third parameter
@@ -169,7 +170,7 @@
  // Sets an activity indicator for an operation of indeterminate length
 mBuilder.setProgress(0, 0, true);
 // Issues the notification
-mNotifyManager.notify(0, mBuilder.build());
+mNotifyManager.notify(id, mBuilder.build());
 </pre>
 <p>
     The resulting indicator is shown in figure 2:
diff --git a/docs/html/training/notify-user/navigation.jd b/docs/html/training/notify-user/navigation.jd
index ac4689a..fc950131 100644
--- a/docs/html/training/notify-user/navigation.jd
+++ b/docs/html/training/notify-user/navigation.jd
@@ -95,6 +95,7 @@
         {@link android.app.Activity}. For example:
 </p>
 <pre>
+int id = 1;
 ...
 Intent resultIntent = new Intent(this, ResultActivity.class);
 TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
diff --git a/docs/html/wear/images/laptop-bridge.png b/docs/html/wear/images/laptop-bridge.png
index b481224..083b82b 100644
--- a/docs/html/wear/images/laptop-bridge.png
+++ b/docs/html/wear/images/laptop-bridge.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index b977554..a6a6460 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -1,5 +1,5 @@
 page.title=Android Wear
-page.viewport-width=970
+page.viewport_width=970
 fullpage=true
 no_footer_links=true
 page.customHeadTag=<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
diff --git a/docs/html/wear/notifications/creating.jd b/docs/html/wear/notifications/creating.jd
index 133d057..ce9e117 100644
--- a/docs/html/wear/notifications/creating.jd
+++ b/docs/html/wear/notifications/creating.jd
@@ -37,7 +37,7 @@
 <h2 id="Import">Import the Necessary Classes</h2>
 
 <p>To begin development, you must first complete the instructions in the <a
-href="{@docRoot}wear/preview/start">Get Started with the Developer Preview</a> document.
+href="{@docRoot}wear/preview/start.html">Get Started with the Developer Preview</a> document.
 As mentioned in that document, your app must include
 both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
 library</a> and the Developer Preview support library. So to get started,
@@ -252,7 +252,7 @@
 will not work.</p>
 
 <p>To continue enhancing your notifications for wearables using
-  <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder"
+  <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
   ><code>WearableNotifications.Builder</code></a> and other APIs in the
   preview support library, see the following developer guides:</p>
 
diff --git a/docs/html/wear/notifications/remote-input.jd b/docs/html/wear/notifications/remote-input.jd
index 8243896..1668363 100644
--- a/docs/html/wear/notifications/remote-input.jd
+++ b/docs/html/wear/notifications/remote-input.jd
@@ -138,7 +138,7 @@
 <p>If the "Reply" action is not your notification's primary action and you want to enable
 voice input for a secondary action, add the
   <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
-  <a href="{@docRoot}reference/android/preview/support/wearable/notifications/Action.html">
+  <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
 <code>Action</code></a> object.</p>
 
 <p>You should instantiate the
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist
new file mode 100644
index 0000000..d82ea05
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png
new file mode 100644
index 0000000..3435e35
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist
new file mode 100644
index 0000000..07791df
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
new file mode 100644
index 0000000..ffd8212
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
Binary files differ
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index c8bcf26..66bf75c 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -352,13 +352,19 @@
     }
 
     /**
-     * Set the matrix to the concatenation of the two specified matrices,
-     * returning true if the the result can be represented. Either of the two
-     * matrices may also be the target matrix. this = a * b
+     * Set the matrix to the concatenation of the two specified matrices and
+     * return true.
+     *
+     * <p>Either of the two matrices may also be the target matrix, that is
+     * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.</p>
+     *
+     * <p class="note">In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this
+     * function returns true only if the result can be represented. In
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true.</p>
      */
     public boolean setConcat(Matrix a, Matrix b) {
-        return native_setConcat(native_instance, a.native_instance,
-                                b.native_instance);
+        native_setConcat(native_instance, a.native_instance, b.native_instance);
+        return true;
     }
 
     /**
@@ -366,7 +372,8 @@
      * M' = M * T(dx, dy)
      */
     public boolean preTranslate(float dx, float dy) {
-        return native_preTranslate(native_instance, dx, dy);
+        native_preTranslate(native_instance, dx, dy);
+        return true;
     }
 
     /**
@@ -374,7 +381,8 @@
      * M' = M * S(sx, sy, px, py)
      */
     public boolean preScale(float sx, float sy, float px, float py) {
-        return native_preScale(native_instance, sx, sy, px, py);
+        native_preScale(native_instance, sx, sy, px, py);
+        return true;
     }
 
     /**
@@ -382,7 +390,8 @@
      * M' = M * S(sx, sy)
      */
     public boolean preScale(float sx, float sy) {
-        return native_preScale(native_instance, sx, sy);
+        native_preScale(native_instance, sx, sy);
+        return true;
     }
 
     /**
@@ -390,7 +399,8 @@
      * M' = M * R(degrees, px, py)
      */
     public boolean preRotate(float degrees, float px, float py) {
-        return native_preRotate(native_instance, degrees, px, py);
+        native_preRotate(native_instance, degrees, px, py);
+        return true;
     }
 
     /**
@@ -398,7 +408,8 @@
      * M' = M * R(degrees)
      */
     public boolean preRotate(float degrees) {
-        return native_preRotate(native_instance, degrees);
+        native_preRotate(native_instance, degrees);
+        return true;
     }
 
     /**
@@ -406,7 +417,8 @@
      * M' = M * K(kx, ky, px, py)
      */
     public boolean preSkew(float kx, float ky, float px, float py) {
-        return native_preSkew(native_instance, kx, ky, px, py);
+        native_preSkew(native_instance, kx, ky, px, py);
+        return true;
     }
 
     /**
@@ -414,7 +426,8 @@
      * M' = M * K(kx, ky)
      */
     public boolean preSkew(float kx, float ky) {
-        return native_preSkew(native_instance, kx, ky);
+        native_preSkew(native_instance, kx, ky);
+        return true;
     }
 
     /**
@@ -422,7 +435,8 @@
      * M' = M * other
      */
     public boolean preConcat(Matrix other) {
-        return native_preConcat(native_instance, other.native_instance);
+        native_preConcat(native_instance, other.native_instance);
+        return true;
     }
 
     /**
@@ -430,7 +444,8 @@
      * M' = T(dx, dy) * M
      */
     public boolean postTranslate(float dx, float dy) {
-        return native_postTranslate(native_instance, dx, dy);
+        native_postTranslate(native_instance, dx, dy);
+        return true;
     }
 
     /**
@@ -438,7 +453,8 @@
      * M' = S(sx, sy, px, py) * M
      */
     public boolean postScale(float sx, float sy, float px, float py) {
-        return native_postScale(native_instance, sx, sy, px, py);
+        native_postScale(native_instance, sx, sy, px, py);
+        return true;
     }
 
     /**
@@ -446,7 +462,8 @@
      * M' = S(sx, sy) * M
      */
     public boolean postScale(float sx, float sy) {
-        return native_postScale(native_instance, sx, sy);
+        native_postScale(native_instance, sx, sy);
+        return true;
     }
 
     /**
@@ -454,7 +471,8 @@
      * M' = R(degrees, px, py) * M
      */
     public boolean postRotate(float degrees, float px, float py) {
-        return native_postRotate(native_instance, degrees, px, py);
+        native_postRotate(native_instance, degrees, px, py);
+        return true;
     }
 
     /**
@@ -462,7 +480,8 @@
      * M' = R(degrees) * M
      */
     public boolean postRotate(float degrees) {
-        return native_postRotate(native_instance, degrees);
+        native_postRotate(native_instance, degrees);
+        return true;
     }
 
     /**
@@ -470,7 +489,8 @@
      * M' = K(kx, ky, px, py) * M
      */
     public boolean postSkew(float kx, float ky, float px, float py) {
-        return native_postSkew(native_instance, kx, ky, px, py);
+        native_postSkew(native_instance, kx, ky, px, py);
+        return true;
     }
 
     /**
@@ -478,7 +498,8 @@
      * M' = K(kx, ky) * M
      */
     public boolean postSkew(float kx, float ky) {
-        return native_postSkew(native_instance, kx, ky);
+        native_postSkew(native_instance, kx, ky);
+        return true;
     }
 
     /**
@@ -486,7 +507,8 @@
      * M' = other * M
      */
     public boolean postConcat(Matrix other) {
-        return native_postConcat(native_instance, other.native_instance);
+        native_postConcat(native_instance, other.native_instance);
+        return true;
     }
 
     /** Controlls how the src rect should align into the dst rect for
@@ -828,41 +850,41 @@
                                         float kx, float ky, float px, float py);
     private static native void native_setSkew(long native_object,
                                               float kx, float ky);
-    private static native boolean native_setConcat(long native_object,
-                                                   long native_a,
-                                                   long native_b);
-    private static native boolean native_preTranslate(long native_object,
-                                                      float dx, float dy);
-    private static native boolean native_preScale(long native_object,
-                                        float sx, float sy, float px, float py);
-    private static native boolean native_preScale(long native_object,
-                                                  float sx, float sy);
-    private static native boolean native_preRotate(long native_object,
-                                            float degrees, float px, float py);
-    private static native boolean native_preRotate(long native_object,
-                                                   float degrees);
-    private static native boolean native_preSkew(long native_object,
-                                        float kx, float ky, float px, float py);
-    private static native boolean native_preSkew(long native_object,
-                                                 float kx, float ky);
-    private static native boolean native_preConcat(long native_object,
-                                                   long native_other_matrix);
-    private static native boolean native_postTranslate(long native_object,
-                                                       float dx, float dy);
-    private static native boolean native_postScale(long native_object,
-                                        float sx, float sy, float px, float py);
-    private static native boolean native_postScale(long native_object,
-                                                   float sx, float sy);
-    private static native boolean native_postRotate(long native_object,
-                                            float degrees, float px, float py);
-    private static native boolean native_postRotate(long native_object,
-                                                    float degrees);
-    private static native boolean native_postSkew(long native_object,
-                                        float kx, float ky, float px, float py);
-    private static native boolean native_postSkew(long native_object,
-                                                  float kx, float ky);
-    private static native boolean native_postConcat(long native_object,
-                                                    long native_other_matrix);
+    private static native void native_setConcat(long native_object,
+                                                long native_a,
+                                                long native_b);
+    private static native void native_preTranslate(long native_object,
+                                                   float dx, float dy);
+    private static native void native_preScale(long native_object,
+                                               float sx, float sy, float px, float py);
+    private static native void native_preScale(long native_object,
+                                               float sx, float sy);
+    private static native void native_preRotate(long native_object,
+                                                float degrees, float px, float py);
+    private static native void native_preRotate(long native_object,
+                                                float degrees);
+    private static native void native_preSkew(long native_object,
+                                              float kx, float ky, float px, float py);
+    private static native void native_preSkew(long native_object,
+                                              float kx, float ky);
+    private static native void native_preConcat(long native_object,
+                                                long native_other_matrix);
+    private static native void native_postTranslate(long native_object,
+                                                    float dx, float dy);
+    private static native void native_postScale(long native_object,
+                                                float sx, float sy, float px, float py);
+    private static native void native_postScale(long native_object,
+                                                float sx, float sy);
+    private static native void native_postRotate(long native_object,
+                                                 float degrees, float px, float py);
+    private static native void native_postRotate(long native_object,
+                                                 float degrees);
+    private static native void native_postSkew(long native_object,
+                                               float kx, float ky, float px, float py);
+    private static native void native_postSkew(long native_object,
+                                               float kx, float ky);
+    private static native void native_postConcat(long native_object,
+                                                 long native_other_matrix);
     private static native boolean native_setRectToRect(long native_object,
                                                 RectF src, RectF dst, int stf);
     private static native boolean native_setPolyToPoly(long native_object,
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e320c67..077db7a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -121,20 +121,6 @@
  * document.</p></div>
  */
 public abstract class Drawable {
-    /**
-     * Hotspot identifier mask for tracking touch points.
-     *
-     * @hide until hotspot APIs are finalized
-     */
-    public static final int HOTSPOT_TOUCH_MASK = 0xFF;
-
-    /**
-     * Hotspot identifier for tracking keyboard focus.
-     *
-     * @hide until hotspot APIs are finalized
-     */
-    public static final int HOTSPOT_FOCUS = 0x100;
-
     private static final Rect ZERO_BOUNDS_RECT = new Rect();
 
     private int[] mStateSet = StateSet.WILD_CARD;
@@ -499,14 +485,13 @@
 
     /**
      * Indicates whether the drawable supports hotspots. Hotspots are uniquely
-     * identifiable coordinates the may be added, updated and removed within the
+     * identifiable coordinates the may be added, updated and removed within a
      * drawable.
      *
      * @return true if hotspots are supported
      * @see #setHotspot(int, float, float)
      * @see #removeHotspot(int)
      * @see #clearHotspots()
-     * @hide until hotspot APIs are finalized
      */
     public boolean supportsHotspots() {
         return false;
@@ -514,33 +499,33 @@
 
     /**
      * Specifies a hotspot's location within the drawable.
+     * <p>
+     * The specified key should be an id declared in the resources of the
+     * application to ensure it is unique (see the <a
+     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
      *
-     * @param id unique identifier for the hotspot
-     * @param x x-coordinate
-     * @param y y-coordinate
-     * @hide until hotspot APIs are finalized
+     * @param key The key identifying the hotspot
+     * @param x The X coordinate of the center of the hotspot
+     * @param y The Y coordinate of the center of the hotspot
      */
-    public void setHotspot(int id, float x, float y) {}
+    public void setHotspot(int key, float x, float y) {}
 
     /**
-     * Removes the specified hotspot from the drawable.
+     * Removes the hotspot with the specified key from the drawable.
      *
-     * @param id unique identifier for the hotspot
-     * @hide until hotspot APIs are finalized
+     * @param key The key identifying the hotspot
      */
-    public void removeHotspot(int id) {}
+    public void removeHotspot(int key) {}
 
     /**
      * Removes all hotspots from the drawable.
-     *
-     * @hide until hotspot APIs are finalized
      */
     public void clearHotspots() {}
 
     /**
      * Whether this drawable requests projection.
      *
-     * @hide
+     * @hide until we finalize these APIs
      */
     public boolean isProjected() {
         return false;
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 2eb7b90..6ab33f8 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -118,33 +118,21 @@
         return mWrappedDrawable.getDirtyBounds();
     }
 
-    /**
-     * @hide
-     */
     @Override
     public boolean supportsHotspots() {
         return mWrappedDrawable.supportsHotspots();
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void setHotspot(int id, float x, float y) {
         mWrappedDrawable.setHotspot(id, x, y);
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void removeHotspot(int id) {
         mWrappedDrawable.removeHotspot(id);
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void clearHotspots() {
         mWrappedDrawable.clearHotspots();
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 59a0c93..9384caf 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -183,33 +183,21 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public boolean supportsHotspots() {
         return mInsetState.mDrawable.supportsHotspots();
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void setHotspot(int id, float x, float y) {
         mInsetState.mDrawable.setHotspot(id, x, y);
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void removeHotspot(int id) {
         mInsetState.mDrawable.removeHotspot(id);
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void clearHotspots() {
         mInsetState.mDrawable.clearHotspots();
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 3c3c841..b366987 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -80,8 +80,8 @@
     }
 
     /**
-     * Create a new layer drawable with the specified list of layers and the specified
-     * constant state.
+     * Create a new layer drawable with the specified list of layers and the
+     * specified constant state.
      *
      * @param layers The list of layers to add to this drawable.
      * @param state The constant drawable state.
@@ -326,6 +326,7 @@
         childDrawable.mInsetR = right;
         childDrawable.mInsetB = bottom;
         st.mNum++;
+        st.invalidateCache();
 
         layer.setCallback(this);
     }
@@ -419,6 +420,7 @@
                 }
 
                 childDrawable.mDrawable = drawable;
+                mLayerState.invalidateCache();
                 return true;
             }
         }
@@ -527,58 +529,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public boolean supportsHotspots() {
-        final ChildDrawable[] array = mLayerState.mChildren;
-        final int N = mLayerState.mNum;
-        for (int i = 0; i < N; i++) {
-            if (array[i].mDrawable.supportsHotspots()) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void setHotspot(int id, float x, float y) {
-        final ChildDrawable[] array = mLayerState.mChildren;
-        final int N = mLayerState.mNum;
-        for (int i = 0; i < N; i++) {
-            array[i].mDrawable.setHotspot(id, x, y);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void removeHotspot(int id) {
-        final ChildDrawable[] array = mLayerState.mChildren;
-        final int N = mLayerState.mNum;
-        for (int i = 0; i < N; i++) {
-            array[i].mDrawable.removeHotspot(id);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void clearHotspots() {
-        final ChildDrawable[] array = mLayerState.mChildren;
-        final int N = mLayerState.mNum;
-        for (int i = 0; i < N; i++) {
-            array[i].mDrawable.clearHotspots();
-        }
-    }
-
     private void computeStackedPadding(Rect padding) {
         padding.left = 0;
         padding.top = 0;
@@ -599,6 +549,46 @@
     }
 
     @Override
+    public boolean supportsHotspots() {
+        final ChildDrawable[] array = mLayerState.mChildren;
+        final int N = mLayerState.mNum;
+        for (int i = 0; i < N; i++) {
+            if (array[i].mDrawable.supportsHotspots()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public void setHotspot(int id, float x, float y) {
+        final ChildDrawable[] array = mLayerState.mChildren;
+        final int N = mLayerState.mNum;
+        for (int i = 0; i < N; i++) {
+            array[i].mDrawable.setHotspot(id, x, y);
+        }
+    }
+
+    @Override
+    public void removeHotspot(int id) {
+        final ChildDrawable[] array = mLayerState.mChildren;
+        final int N = mLayerState.mNum;
+        for (int i = 0; i < N; i++) {
+            array[i].mDrawable.removeHotspot(id);
+        }
+    }
+
+    @Override
+    public void clearHotspots() {
+        final ChildDrawable[] array = mLayerState.mChildren;
+        final int N = mLayerState.mNum;
+        for (int i = 0; i < N; i++) {
+            array[i].mDrawable.clearHotspots();
+        }
+    }
+
+    @Override
     public boolean setVisible(boolean visible, boolean restart) {
         final boolean changed = super.setVisible(visible, restart);
         final ChildDrawable[] array = mLayerState.mChildren;
@@ -632,7 +622,8 @@
     public int getAlpha() {
         final ChildDrawable[] array = mLayerState.mChildren;
         if (mLayerState.mNum > 0) {
-            // All layers should have the same alpha set on them - just return the first one
+            // All layers should have the same alpha set on them - just return
+            // the first one
             return array[0].mDrawable.getAlpha();
         } else {
             return super.getAlpha();
@@ -649,12 +640,11 @@
     }
 
     /**
-     * Sets the opacity of this drawable directly, instead of collecting the states from
-     * the layers
+     * Sets the opacity of this drawable directly, instead of collecting the
+     * states from the layers
      *
-     * @param opacity The opacity to use, or {@link PixelFormat#UNKNOWN PixelFormat.UNKNOWN}
-     * for the default behavior
-     *
+     * @param opacity The opacity to use, or {@link PixelFormat#UNKNOWN
+     *            PixelFormat.UNKNOWN} for the default behavior
      * @see PixelFormat#UNKNOWN
      * @see PixelFormat#TRANSLUCENT
      * @see PixelFormat#TRANSPARENT
@@ -702,7 +692,7 @@
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             final ChildDrawable r = array[i];
-            if (r.mDrawable.setState(state)) {
+            if (r.mDrawable.isStateful() && r.mDrawable.setState(state)) {
                 changed = true;
             }
 
@@ -890,7 +880,7 @@
         public int[] mThemeAttrs;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
         public int mId;
-        
+
         ChildDrawable() {
             // Default empty constructor.
         }
@@ -920,14 +910,11 @@
         int mChangingConfigurations;
         int mChildrenChangingConfigurations;
 
-        private boolean mHaveOpacity = false;
+        private boolean mHaveOpacity;
         private int mOpacity;
 
-        private boolean mHaveStateful = false;
-        private boolean mStateful;
-
-        private boolean mCheckedConstantState;
-        private boolean mCanConstantState;
+        private boolean mHaveIsStateful;
+        private boolean mIsStateful;
 
         private boolean mAutoMirrored;
 
@@ -951,9 +938,8 @@
 
                 mHaveOpacity = orig.mHaveOpacity;
                 mOpacity = orig.mOpacity;
-                mHaveStateful = orig.mHaveStateful;
-                mStateful = orig.mStateful;
-                mCheckedConstantState = mCanConstantState = true;
+                mHaveIsStateful = orig.mHaveIsStateful;
+                mIsStateful = orig.mIsStateful;
                 mAutoMirrored = orig.mAutoMirrored;
                 mPaddingMode = orig.mPaddingMode;
                 mThemeAttrs = orig.mThemeAttrs;
@@ -993,49 +979,54 @@
                 return mOpacity;
             }
 
+            final ChildDrawable[] array = mChildren;
             final int N = mNum;
-            int op = N > 0 ? mChildren[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
+            int op = N > 0 ? array[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
             for (int i = 1; i < N; i++) {
-                op = Drawable.resolveOpacity(op, mChildren[i].mDrawable.getOpacity());
+                op = Drawable.resolveOpacity(op, array[i].mDrawable.getOpacity());
             }
+
             mOpacity = op;
             mHaveOpacity = true;
             return op;
         }
 
         public final boolean isStateful() {
-            if (mHaveStateful) {
-                return mStateful;
+            if (mHaveIsStateful) {
+                return mIsStateful;
             }
 
-            boolean stateful = false;
+            final ChildDrawable[] array = mChildren;
             final int N = mNum;
+            boolean isStateful = false;
             for (int i = 0; i < N; i++) {
-                if (mChildren[i].mDrawable.isStateful()) {
-                    stateful = true;
+                if (array[i].mDrawable.isStateful()) {
+                    isStateful = true;
                     break;
                 }
             }
 
-            mStateful = stateful;
-            mHaveStateful = true;
-            return stateful;
+            mIsStateful = isStateful;
+            mHaveIsStateful = true;
+            return isStateful;
         }
 
-        public boolean canConstantState() {
-            if (!mCheckedConstantState && mChildren != null) {
-                mCanConstantState = true;
-                final int N = mNum;
-                for (int i = 0; i < N; i++) {
-                    if (mChildren[i].mDrawable.getConstantState() == null) {
-                        mCanConstantState = false;
-                        break;
-                    }
+        public final boolean canConstantState() {
+            final ChildDrawable[] array = mChildren;
+            final int N = mNum;
+            for (int i = 0; i < N; i++) {
+                if (array[i].mDrawable.getConstantState() == null) {
+                    return false;
                 }
-                mCheckedConstantState = true;
             }
 
-            return mCanConstantState;
+            // Don't cache the result, this method is not called very often.
+            return true;
+        }
+
+        public void invalidateCache() {
+            mHaveOpacity = false;
+            mHaveIsStateful = false;
         }
     }
 }
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index b66d86d..3323a25 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -39,7 +39,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.ArrayList;
 
 /**
  * Documentation pending.
@@ -98,7 +97,7 @@
     protected boolean onStateChange(int[] stateSet) {
         super.onStateChange(stateSet);
 
-        if (mRipplePaint != null) {
+        if (mRipplePaint != null && mState.mTint != null) {
             final ColorStateList stateList = mState.mTint;
             final int newColor = stateList.getColorForState(stateSet, 0);
             final int oldColor = mRipplePaint.getColor();
@@ -122,7 +121,7 @@
 
     @Override
     public boolean isStateful() {
-        return super.isStateful() || mState.mTint.isStateful();
+        return super.isStateful() || mState.mTint != null && mState.mTint.isStateful();
     }
 
     @Override
@@ -150,10 +149,6 @@
 
         if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tint] == 0) {
             mState.mTint = a.getColorStateList(R.styleable.TouchFeedbackDrawable_tint);
-
-            if (mState.mTint == null) {
-                throw new RuntimeException("<touch-feedback> tag requires a 'tint' attribute");
-            }
         }
 
         if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tintMode] == 0) {
@@ -222,20 +217,11 @@
         return super.canApplyTheme() || mState != null && mState.mTouchThemeAttrs != null;
     }
 
-    /**
-     * @hide until hotspot APIs are finalized
-     */
     @Override
     public boolean supportsHotspots() {
         return true;
     }
 
-    /**
-     * TODO: Maybe we should set hotspots for state/id combinations? So touch
-     * would be state_pressed and the pointer ID.
-     *
-     * @hide until hotspot APIs are finalized
-     */
     @Override
     public void setHotspot(int id, float x, float y) {
         if (mTouchedRipples == null) {
@@ -266,9 +252,6 @@
         scheduleAnimation();
     }
 
-    /**
-     * @hide until hotspot APIs are finalized
-     */
     @Override
     public void removeHotspot(int id) {
         if (mTouchedRipples == null) {
@@ -284,9 +267,6 @@
         }
     }
 
-    /**
-     * @hide until hotspot APIs are finalized
-     */
     @Override
     public void clearHotspots() {
         if (mTouchedRipples == null) {
@@ -400,9 +380,11 @@
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
             mRipplePaint.setAntiAlias(true);
-            
-            final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
-            mRipplePaint.setColor(color);
+
+            if (mState.mTint != null) {
+                final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+                mRipplePaint.setColor(color);
+            }
         }
         return mRipplePaint;
     }
@@ -488,7 +470,10 @@
         } else if (state == null) {
             ns = new TouchFeedbackState(null, this, res);
         } else {
-            ns = state;
+            // We always need a new state since child drawables contain local
+            // state but live within the parent's constant state.
+            // TODO: Move child drawables into local state.
+            ns = new TouchFeedbackState(state, this, res);
         }
 
         if (res != null) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index f3dd2fc..6c0b722 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -14,7 +14,6 @@
 
 package android.graphics.drawable;
 
-import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.res.Resources;
@@ -28,11 +27,7 @@
 import android.graphics.PathMeasure;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.Region;
-import android.location.Address;
-import android.net.ParseException;
-import android.sax.StartElementListener;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
@@ -47,7 +42,6 @@
 import org.xmlpull.v1.XmlPullParserFactory;
 
 import java.io.IOException;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -60,9 +54,11 @@
  * The vector drawable has 6 elements:
  * <p/>
  * <dl>
- * <dt><code>&lt;vector></code></dt><dd>
- * The attribute <code>android:trigger</code> which defines a state change that
+ * <dt><code>&lt;vector></code></dt>
+ * <dd>The attribute <code>android:trigger</code> defines a state change that
  * will drive the animation </dd>
+ * <dd>The attribute <code>android:versionCode</code> defines the version of
+ * VectorDrawable </dd>
  * <dt><code>&lt;size></code></dt>
  * <dd>Used to defined the intrinsic Width Height size of the drawable using
  * <code>android:width</code> and <code>android:height</code> </dd>
@@ -155,8 +151,8 @@
  * </dd>
  */
 public class VectorDrawable extends Drawable {
-    private static final String LOGTAG = "VectorDrawable";
-    public static final int INFINITE = ValueAnimator.INFINITE;
+    private static final String LOGTAG = VectorDrawable.class.getSimpleName();
+
     private static final String SHAPE_SIZE = "size";
     private static final String SHAPE_VIEWPORT = "viewport";
     private static final String SHAPE_GROUP = "group";
@@ -168,23 +164,32 @@
     private static final int LINECAP_BUTT = 0;
     private static final int LINECAP_ROUND = 1;
     private static final int LINECAP_SQUARE = 2;
+
     private static final int LINEJOIN_MITER = 0;
     private static final int LINEJOIN_ROUND = 1;
     private static final int LINEJOIN_BEVEL = 2;
+
     private static final int DEFAULT_DURATION = 1000;
     private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
+
     private VectorDrawableState mVectorState;
     private int mAlpha = 0xFF;
 
     public VectorDrawable() {
-        mVectorState = new VectorDrawableState();
+        mVectorState = new VectorDrawableState(null);
         mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+
         setDuration(DEFAULT_DURATION);
     }
 
-    private VectorDrawable(VectorDrawableState state) {
+    private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
         mVectorState = new VectorDrawableState(state);
         mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+
+        if (theme != null && canApplyTheme()) {
+            applyTheme(theme);
+        }
+
         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
@@ -194,71 +199,38 @@
         setDuration(duration);
     }
 
-    final static class VectorDrawableState extends ConstantState {
-        int mChangingConfigurations;
-        ValueAnimator mBasicAnimator;
-        VAnimatedPath mVAnimatedPath = new VAnimatedPath();
-        Rect mPadding;
-        int mIntrinsicHeight;
-        int mIntrinsicWidth;
-
-        public VectorDrawableState(){
-        }
-
-        public VectorDrawableState(VectorDrawableState copy){
-            mChangingConfigurations = copy.mChangingConfigurations;
-            mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
-            mPadding = new Rect(copy.mPadding);
-            mIntrinsicHeight = copy.mIntrinsicHeight;
-            mIntrinsicWidth = copy.mIntrinsicWidth;
-        }
-
-        @Override
-        public Drawable newDrawable() {
-            return new VectorDrawable(this);
-        }
-
-        @Override
-        public int getChangingConfigurations() {
-            return mChangingConfigurations;
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see android.graphics.drawable.Drawable#getConstantState()
-     */
     @Override
     public ConstantState getConstantState() {
         return mVectorState;
     }
 
     /**
-     * start the animation
+     * Starts the animation.
      */
     public void start() {
         mVectorState.mBasicAnimator.start();
     }
 
     /**
-     * Stop the animation.
+     * Stops the animation.
      */
     public void stop() {
         mVectorState.mBasicAnimator.end();
     }
 
     /**
-     * Get the current time point in the animation
+     * Returns the current completion value for the animation.
      *
-     * @return the current point on the animation
+     * @return the current point on the animation, typically between 0 and 1
      */
     public float geAnimationFraction() {
         return mVectorState.mVAnimatedPath.getValue();
     }
 
     /**
-     * set the time point in the animation
+     * Set the current completion value for the animation.
      *
-     * @param value the point along the animation typically between 0 and 1
+     * @param value the point along the animation, typically between 0 and 1
      */
     public void setAnimationFraction(float value) {
         mVectorState.mVAnimatedPath.setAnimationFraction(value);
@@ -275,8 +247,12 @@
     }
 
     /**
-     * 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 #INFINITE}.
+     * 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);
@@ -292,7 +268,8 @@
     }
 
     /**
-     * @return True if this drawable repeats its animation
+     * @return the animation repeat count, either a value greater than 0 or
+     *         {@link ValueAnimator#INFINITE}
      */
     public int getRepeatCount() {
         return mVectorState.mBasicAnimator.getRepeatCount();
@@ -345,10 +322,6 @@
         }
     }
 
-    /**
-     * Not implemented yet
-     * @hide
-     */
     @Override
     public void setColorFilter(ColorFilter colorFilter) {
         // TODO: support color filter
@@ -457,29 +430,49 @@
     @Override
     public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-        setAnimatedPath(inflateInternal(res, parser, attrs));
+        final VAnimatedPath p = inflateInternal(res, parser, attrs, theme);
+        setAnimatedPath(p);
     }
 
-    private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
-            throws XmlPullParserException, IOException {
+    @Override
+    public boolean canApplyTheme() {
+        return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        super.applyTheme(t);
+
+        final VectorDrawableState state = mVectorState;
+        final VAnimatedPath path = state.mVAnimatedPath;
+        if (path != null && path.canApplyTheme()) {
+            path.applyTheme(t);
+        }
+    }
+
+    private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        final VAnimatedPath animatedPath = new VAnimatedPath();
+
         boolean noSizeTag = true;
         boolean noViewportTag = true;
         boolean noGroupTag = true;
         boolean noPathTag = true;
-        final VAnimatedPath animatedPath = new VAnimatedPath();
-        VectorDrawable.VGroup currentGroup = null;
+
+        VGroup currentGroup = null;
 
         int eventType = parser.getEventType();
         while (eventType != XmlPullParser.END_DOCUMENT) {
             if (eventType == XmlPullParser.START_TAG) {
-                String tagName = parser.getName();
+                final String tagName = parser.getName();
                 if (SHAPE_PATH.equals(tagName)) {
-                    VectorDrawable.VPath p = new VPath(res, attrs);
-                    currentGroup.add(p);
+                    final VPath path = new VPath();
+                    path.inflate(res, attrs, theme);
+                    currentGroup.add(path);
                     noPathTag = false;
                 } else if (SHAPE_ANIMATION.equals(tagName)) {
-                    VectorDrawable.VAnimation anim =
-                            new VAnimation(res, attrs, animatedPath.mGroupList);
+                    final VAnimation anim = new VAnimation();
+                    anim.inflate(animatedPath.mGroupList, res, attrs, theme);
                     animatedPath.addAnimation(anim);
                 } else if (SHAPE_SIZE.equals(tagName)) {
                     animatedPath.parseSize(res, attrs);
@@ -488,42 +481,60 @@
                     animatedPath.parseViewport(res, attrs);
                     noViewportTag = false;
                 } else if (SHAPE_GROUP.equals(tagName)) {
-                    currentGroup = new VectorDrawable.VGroup();
+                    currentGroup = new VGroup();
                     animatedPath.mGroupList.add(currentGroup);
                     noGroupTag = false;
                 }  else if (SHAPE_VECTOR.equals(tagName)) {
-                    TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
+                    final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
                     animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
+
+                    // Parsing the version information.
+                    // Right now, we only support version "1".
+                    // If the xml didn't specify the version number, the default version is "1".
+                    final int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1);
+                    if (versionCode != 1) {
+                        throw new IllegalArgumentException(
+                                "So far, VectorDrawable only support version 1");
+                    }
+
                     a.recycle();
                 }
             }
+
             eventType = parser.next();
         }
+
         if (noSizeTag || noViewportTag || noGroupTag || noPathTag) {
-            StringBuffer tag = new StringBuffer();
+            final StringBuffer tag = new StringBuffer();
+
             if (noSizeTag) {
-                tag.append("size");
+                tag.append(SHAPE_SIZE);
             }
+
             if  (noViewportTag){
                 if (tag.length()>0) {
                     tag.append(" & ");
                 }
-                tag.append("size");
+                tag.append(SHAPE_SIZE);
             }
+
             if  (noGroupTag){
                 if (tag.length()>0) {
                     tag.append(" & ");
                 }
-                tag.append("group");
+                tag.append(SHAPE_GROUP);
             }
+
             if  (noPathTag){
                 if (tag.length()>0) {
                     tag.append(" or ");
                 }
-                tag.append("path");
+                tag.append(SHAPE_PATH);
             }
-            throw new XmlPullParserException("no "+tag+" defined");
+
+            throw new XmlPullParserException("no " + tag + " defined");
         }
+
         // post parse cleanup
         animatedPath.parseFinish();
         return animatedPath;
@@ -531,16 +542,18 @@
 
     private void setAnimatedPath(VAnimatedPath animatedPath) {
         mVectorState.mVAnimatedPath = animatedPath;
+
         setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
         setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
+
         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);
 
+        setDuration(duration);
         setAnimationFraction(0);
     }
 
@@ -557,9 +570,48 @@
         return changed;
     }
 
-    private static class VAnimatedPath {
-        private static final String LOGTAG = "VAnimatedPath";
+    private static class VectorDrawableState extends ConstantState {
+        int mChangingConfigurations;
+        ValueAnimator mBasicAnimator;
+        VAnimatedPath mVAnimatedPath;
+        Rect mPadding;
+        int mIntrinsicHeight;
+        int mIntrinsicWidth;
 
+        public VectorDrawableState(VectorDrawableState copy) {
+            if (copy != null) {
+                mChangingConfigurations = copy.mChangingConfigurations;
+                mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+                mPadding = new Rect(copy.mPadding);
+                mIntrinsicHeight = copy.mIntrinsicHeight;
+                mIntrinsicWidth = copy.mIntrinsicWidth;
+            } else {
+                mVAnimatedPath = new VAnimatedPath();
+            }
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return new VectorDrawable(this, null, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new VectorDrawable(this, res, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res, Theme theme) {
+            return new VectorDrawable(this, res, theme);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConfigurations;
+        }
+    }
+
+    private static class VAnimatedPath {
         private ArrayList<VAnimation> mCurrentAnimList = null;
         private VPath[] mCurrentPaths;
         private float mAnimationValue = 0; // value goes from 0 to 1
@@ -573,7 +625,9 @@
         private int[] mCurrentState = new int[0];
         private int mTrigger;
         private boolean mTriggerState;
-        ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+
+        final ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+
         float mBaseWidth = 1;
         float mBaseHeight = 1;
         float mViewportWidth;
@@ -582,10 +636,11 @@
         public VAnimatedPath() {
             setup();
         }
+
         public VAnimatedPath(VAnimatedPath copy) {
             setup();
             mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
-            mGroupList = new ArrayList<VGroup>(copy.mGroupList);
+            mGroupList.addAll(copy.mGroupList);
             if (copy.mCurrentPaths != null) {
                 mCurrentPaths = new VPath[copy.mCurrentPaths.length];
                 for (int i = 0; i < mCurrentPaths.length; i++) {
@@ -603,8 +658,53 @@
             mCurrentState = new int[0];
         }
 
+        public boolean canApplyTheme() {
+            final ArrayList<VGroup> groups = mGroupList;
+            for (int i = groups.size() - 1; i >= 0; i--) {
+                final ArrayList<VPath> paths = groups.get(i).mVGList;
+                for (int j = paths.size() - 1; j >= 0; j--) {
+                    final VPath path = paths.get(j);
+                    if (path.canApplyTheme()) {
+                        return true;
+                    }
+                }
+            }
+
+            final ArrayList<VAnimation> anims = mCurrentAnimList;
+            for (int i = anims.size() - 1; i >= 0; i--) {
+                final VAnimation anim = anims.get(i);
+                if (anim.canApplyTheme()) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        public void applyTheme(Theme t) {
+            final ArrayList<VGroup> groups = mGroupList;
+            for (int i = groups.size() - 1; i >= 0; i--) {
+                final ArrayList<VPath> paths = groups.get(i).mVGList;
+                for (int j = paths.size() - 1; j >= 0; j--) {
+                    final VPath path = paths.get(j);
+                    if (path.canApplyTheme()) {
+                        path.applyTheme(t);
+                    }
+                }
+            }
+
+            final ArrayList<VAnimation> anims = mCurrentAnimList;
+            for (int i = anims.size() - 1; i >= 0; i--) {
+                final VAnimation anim = anims.get(i);
+                if (anim.canApplyTheme()) {
+                    anim.applyTheme(t);
+                }
+            }
+        }
+
         public void setTrigger(int trigger){
-            int []lut = { 0,
+            final int [] lut = {
+                    0,
                     R.attr.state_pressed,
                     R.attr.state_focused,
                     R.attr.state_hovered,
@@ -614,6 +714,7 @@
                     R.attr.state_activated,
                     R.attr.state_focused
             };
+
             mTrigger = lut[trigger];
          }
 
@@ -651,23 +752,27 @@
          * @return true if you need to keep repeating
          */
         public boolean setAnimationFraction(float value) {
-            int len = mCurrentPaths.length;
             getTotalAnimationDuration();
+
             long animationTime = (long) (value * mTotalDuration);
 
+            final int len = mCurrentPaths.length;
             for (int i = 0; i < len; i++) {
-                VPath path = mCurrentPaths[i];
                 animationTime =
                         (long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
-                int size = mCurrentAnimList.size();
+
+                final VPath path = mCurrentPaths[i];
+                final int size = mCurrentAnimList.size();
                 for (int j = 0; j < size; j++) {
-                    VAnimation vAnimation = mCurrentAnimList.get(j);
+                    final VAnimation vAnimation = mCurrentAnimList.get(j);
                     if (vAnimation.doesAdjustPath(path)) {
                         mCurrentPaths[i] =  vAnimation.getPathAtTime(animationTime, path);
                     }
                 }
             }
-            this.mAnimationValue = value;
+
+            mAnimationValue = value;
+
             if (mTotalDuration == -1) {
                 return true;
             } else {
@@ -676,16 +781,15 @@
         }
 
         public void draw(Canvas canvas) {
-            int w = canvas.getWidth();
-            int h = canvas.getHeight();
-            float scale = w / mViewportWidth;
-            scale = Math.min(h / mViewportHeight, scale);
-
             if (mCurrentPaths == null) {
                 Log.e(LOGTAG,"mCurrentPaths == null");
                 return;
             }
 
+            // TODO: This should probably use getBounds().
+            final int w = canvas.getWidth();
+            final int h = canvas.getHeight();
+
             for (int i = 0; i < mCurrentPaths.length; i++) {
                 if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
                     drawPath(mCurrentPaths[i], canvas, w, h);
@@ -694,8 +798,7 @@
         }
 
         private void drawPath(VPath vPath, Canvas canvas, int w, int h) {
-            float scale = w / mViewportWidth;
-            scale = Math.min(h / mViewportHeight, scale);
+            final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
 
             vPath.toPath(mPath);
             Path path = mPath;
@@ -734,18 +837,20 @@
             if (vPath.mClip) {
                 canvas.clipPath(mRenderPath, Region.Op.REPLACE);
             }
+
             if (vPath.mFillColor != 0) {
                 mFillPaint.setColor(vPath.mFillColor);
                 int alpha = 0xFF & (vPath.mFillColor >> 24);
                 mFillPaint.setAlpha(alpha);
                 canvas.drawPath(mRenderPath, mFillPaint);
             }
+
             if (vPath.mStrokeColor != 0) {
-                if (vPath.mStrokelineJoin != null) {
-                    mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
+                if (vPath.mStrokeLineJoin != null) {
+                    mStrokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
                 }
-                if (vPath.mStrokelineCap != null) {
-                    mStrokePaint.setStrokeCap(vPath.mStrokelineCap);
+                if (vPath.mStrokeLineCap != null) {
+                    mStrokePaint.setStrokeCap(vPath.mStrokeLineCap);
                 }
                 mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
                 mStrokePaint.setColor(vPath.mStrokeColor);
@@ -761,7 +866,7 @@
          * TODO: improve memory use & performance or move to C++
          */
         public void parseFinish() {
-            HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
+            final HashMap<String, VAnimation> newAnimations = new HashMap<String, VAnimation>();
             for (VGroup group : mGroupList) {
                 for (VPath vPath : group.getPaths()) {
                     if (!vPath.mAnimated) {
@@ -772,16 +877,19 @@
                         } else {
                             ap = newAnimations.get(vPath.getID());
                         }
+
                         ap.addPath(vPath);
                         vPath.mAnimated = true;
                     }
                 }
             }
+
             if (mCurrentAnimList == null) {
                 mCurrentAnimList = new ArrayList<VectorDrawable.VAnimation>();
             }
             mCurrentAnimList.addAll(newAnimations.values());
-            Collection<VPath> paths = mGroupList.get(0).getPaths();
+
+            final Collection<VPath> paths = mGroupList.get(0).getPaths();
             mCurrentPaths = paths.toArray(new VPath[paths.size()]);
             for (int i = 0; i < mCurrentPaths.length; i++) {
                 mCurrentPaths[i] = new VPath(mCurrentPaths[i]);
@@ -842,45 +950,49 @@
     }
 
     private static class VAnimation {
-        private static final String LOGTAG = "VAnimation";
-        private VPath[] mPaths = new VPath[0];
+        private static final String SEPARATOR = ",";
+
+        private static final int DIRECTION_FORWARD = 0;
+        private static final int DIRECTION_IN_AND_OUT = 1;
 
         public enum Style {
             INTERPOLATE, CROSSFADE, WIPE
         }
-        Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+
+        private final HashSet<String> mSeqMap = new HashSet<String>();
+
+        private Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+        private VPath[] mPaths = new VPath[0];
+        private long[] mDuration = { DEFAULT_DURATION };
+
+        private int[] mThemeAttrs;
         private Style mStyle;
         private int mLimitProperty = 0;
-        private long[] mDuration = {DEFAULT_DURATION};
         private long mStartOffset;
         private long mRepeat = 1;
-        private HashSet<String>mSeqMap = new HashSet<String>();
         private long mWipeDirection;
-        private int mMode = 0; // forward = 0 inAndOut = 1;
+        private int mMode = DIRECTION_FORWARD;
         private int mInterpolatorType;
         private String mId;
-        private final static int DIRECTION_FORWARD = 0;
-        private final static int DIRECTION_IN_AND_OUT = 1;
 
         public VAnimation() {
+            // Empty constructor.
         }
 
-        public boolean doesAdjustPath(VPath path) {
-            return mSeqMap.contains(path.getID());
-        }
-
-        public VAnimation(Resources r, AttributeSet attrs, ArrayList<VGroup> groups)
+        public void inflate(ArrayList<VGroup> groups, Resources r, AttributeSet attrs, Theme theme)
                 throws XmlPullParserException {
             String value;
             String[] sp;
             int name;
 
-            TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+            final int[] themeAttrs = a.extractThemeAttrs();
+            mThemeAttrs = themeAttrs;
 
             value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
             if (value != null) {
-                sp = value.split(",");
-                VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
+                sp = value.split(SEPARATOR);
+                final VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
 
                 for (int j = 0; j < sp.length; j++) {
                     mSeqMap.add(sp[j].trim());
@@ -888,38 +1000,52 @@
                     path.mAnimated = true;
                     paths[j] = path;
                 }
+
                 setPaths(paths);
             }
 
-            setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
-
             name = R.styleable.VectorDrawableAnimation_durations;
             value = a.getString(name);
             if (value != null) {
                 long totalDuration = 0;
-                sp = value.split(",");
-                long[] dur = new long[sp.length];
+                sp = value.split(SEPARATOR);
+
+                final long[] dur = new long[sp.length];
                 for (int j = 0; j < dur.length; j++) {
                     dur[j] = Long.parseLong(sp[j]);
                     totalDuration +=  dur[j];
                 }
+
                 if (totalDuration == 0){
-                    throw new XmlPullParserException(a.getPositionDescription()+
-                            "total duration must not be zero");
+                    throw new XmlPullParserException(a.getPositionDescription()
+                            + " total duration must not be zero");
                 }
+
                 setDuration(dur);
             }
 
+            setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
             setRepeat(a.getInt(R.styleable.VectorDrawableAnimation_repeatCount, 1));
-
             setStartOffset(a.getInt(R.styleable.VectorDrawableAnimation_startDelay, 0));
-
             setMode(a.getInt(R.styleable.VectorDrawableAnimation_repeatStyle, 0));
 
             fixMissingParameters();
+
             a.recycle();
         }
 
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null;
+        }
+
+        public void applyTheme(Theme t) {
+            // TODO: Apply theme.
+        }
+
+        public boolean doesAdjustPath(VPath path) {
+            return mSeqMap.contains(path.getID());
+        }
+
         public String getId() {
             if (mId == null) {
                 mId = mPaths[0].getID();
@@ -939,7 +1065,7 @@
         }
 
         public void setStyle(Style style) {
-            this.mStyle = style;
+            mStyle = style;
         }
 
         public int getLimitProperty() {
@@ -947,7 +1073,7 @@
         }
 
         public void setLimitProperty(int limitProperty) {
-            this.mLimitProperty = limitProperty;
+            mLimitProperty = limitProperty;
         }
 
         public long[] getDuration() {
@@ -955,7 +1081,7 @@
         }
 
         public void setDuration(long[] duration) {
-            this.mDuration = duration;
+            mDuration = duration;
         }
 
         public long getRepeat() {
@@ -963,7 +1089,7 @@
         }
 
         public void setRepeat(long repeat) {
-            this.mRepeat = repeat;
+            mRepeat = repeat;
         }
 
         public long getStartOffset() {
@@ -971,7 +1097,7 @@
         }
 
         public void setStartOffset(long startOffset) {
-            this.mStartOffset = startOffset;
+            mStartOffset = startOffset;
         }
 
         public long getWipeDirection() {
@@ -979,7 +1105,7 @@
         }
 
         public void setWipeDirection(long wipeDirection) {
-            this.mWipeDirection = wipeDirection;
+            mWipeDirection = wipeDirection;
         }
 
         public int getMode() {
@@ -987,7 +1113,7 @@
         }
 
         public void setMode(int mode) {
-            this.mMode = mode;
+            mMode = mode;
         }
 
         public int getInterpolator() {
@@ -995,7 +1121,7 @@
         }
 
         public void setInterpolator(int interpolator) {
-            this.mInterpolatorType = interpolator;
+            mInterpolatorType = interpolator;
         }
 
         /**
@@ -1019,7 +1145,7 @@
         }
 
         public void setPaths(VPath[] paths) {
-            this.mPaths = paths;
+            mPaths = paths;
         }
 
         public void addPath(VPath path) {
@@ -1037,7 +1163,7 @@
         }
 
         public void interpolate(VPath p1, VPath p2, float time, VPath dest) {
-            dest.interpolate(time, p1, p2, dest, mLimitProperty);
+            VPath.interpolate(time, p1, p2, dest, mLimitProperty);
         }
 
         public VPath getPathAtTime(long milliseconds, VPath dest) {
@@ -1138,8 +1264,8 @@
     }
 
     private static class VGroup {
-        private HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
-        private ArrayList<VPath> mVGList = new ArrayList<VPath>();
+        private final HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
+        private final ArrayList<VPath> mVGList = new ArrayList<VPath>();
 
         public void add(VPath path) {
             String id = path.getID();
@@ -1171,34 +1297,52 @@
         private static final int LIMIT_TRIM_PATH_START = 3;
         private static final int LIMIT_TRIM_PATH_OFFSET = 5;
         private static final int LIMIT_TRIM_PATH_END = 4;
+
         private static final int STATE_UNDEFINED=0;
         private static final int STATE_TRUE=1;
         private static final int STATE_FALSE=2;
+
         private static final int MAX_STATES = 10;
-        private VNode[] mNode = null;
-        private String mId;
+
+        private int[] mThemeAttrs;
+
         int mStrokeColor = 0;
         float mStrokeWidth = 0;
         float mStrokeOpacity = Float.NaN;
+
         int mFillColor = 0;
         int mFillRule;
         float mFillOpacity = Float.NaN;
+
         float mRotate = 0;
         float mPivotX = 0;
         float mPivotY = 0;
+
         float mTrimPathStart = 0;
         float mTrimPathEnd = 1;
         float mTrimPathOffset = 0;
+
         boolean mAnimated = false;
         boolean mClip = false;
-        public Paint.Cap mStrokelineCap = null;
-        public Paint.Join mStrokelineJoin = null;
+        Paint.Cap mStrokeLineCap = null;
+        Paint.Join mStrokeLineJoin = null;
         float mStrokeMiterlimit = 4;
+
+        private VNode[] mNode = null;
+        private String mId;
         private int[] mCheckState = new int[MAX_STATES];
         private boolean[] mCheckValue = new boolean[MAX_STATES];
         private int mNumberOfStates = 0;
         private int mNumberOfTrue = 0;
 
+        public VPath() {
+            // Empty constructor.
+        }
+
+        public VPath(VPath p) {
+            copyFrom(p);
+        }
+
         public void addStateFilter(int state, boolean condition) {
             int k = 0;
             while (k < mNumberOfStates) {
@@ -1216,7 +1360,7 @@
             }
         }
 
-        int getState(int state){
+        private int getState(int state){
             for (int i = 0; i < mNumberOfStates; i++) {
                 if (mCheckState[mNumberOfStates] == state){
                     return (mCheckValue[i])?STATE_TRUE:STATE_FALSE;
@@ -1238,70 +1382,126 @@
             }
         }
 
-        public VPath() {
-            mId = this.toString(); // to ensure paths have unique names
-        }
-
-        public VPath(VPath p) {
-            copyFrom(p);
-        }
-
-        public String getID(){
+        public String getID() {
             return mId;
         }
 
-        public VPath(Resources r, AttributeSet attrs) {
-            TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawablePath);
-            mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
-            mId = a.getString(R.styleable.VectorDrawablePath_name);
-            mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
-            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
-            mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
-
-            if (!Float.isNaN(mFillOpacity)) {
-                mFillColor &= 0x00FFFFFF;
-                mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
-            }
-            mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
-            mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
-            mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
-            int lineCap  = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
-            switch (lineCap) {
+        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
+            switch (id) {
                 case LINECAP_BUTT:
-                    mStrokelineCap = Paint.Cap.BUTT;
-                    break;
+                    return Paint.Cap.BUTT;
                 case LINECAP_ROUND:
-                    mStrokelineCap = Paint.Cap.ROUND;
-                    break;
+                    return Paint.Cap.ROUND;
                 case LINECAP_SQUARE:
-                    mStrokelineCap = Paint.Cap.SQUARE;
-                    break;
+                    return Paint.Cap.SQUARE;
+                default:
+                    return defValue;
             }
-            int lineJoin =  a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
-            switch (lineJoin) {
+        }
+
+        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
+            switch (id) {
                 case LINEJOIN_MITER:
-                    mStrokelineJoin = Paint.Join.MITER;
-                    break;
+                    return Paint.Join.MITER;
                 case LINEJOIN_ROUND:
-                    mStrokelineJoin = Paint.Join.ROUND;
-                    break;
+                    return Paint.Join.ROUND;
                 case LINEJOIN_BEVEL:
-                    mStrokelineJoin = Paint.Join.BEVEL;
-                    break;
+                    return Paint.Join.BEVEL;
+                default:
+                    return defValue;
             }
-            mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
-                    mStrokeMiterlimit);
-            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
-            mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
-            if (!Float.isNaN(mStrokeOpacity)) {
-                mStrokeColor &= 0x00FFFFFF;
-                mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+        }
+
+        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
+            final int[] themeAttrs = a.extractThemeAttrs();
+            mThemeAttrs = themeAttrs;
+
+            // NOTE: The set of attributes loaded here MUST match the
+            // set of attributes loaded in applyTheme.
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_clipToPath] == 0) {
+                mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
             }
-            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
-            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
-            mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
-            mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
-            int[] states = {R.styleable.VectorDrawablePath_state_activated,
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_name] == 0) {
+                mId = a.getString(R.styleable.VectorDrawablePath_name);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pathData] == 0) {
+                mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fill] == 0) {
+                mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fillOpacity] == 0) {
+                mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_rotation] == 0) {
+                mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, mRotate);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pivotX] == 0) {
+                mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, mPivotX);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pivotY] == 0) {
+                mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, mPivotY);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_strokeLineCap] == 0) {
+                mStrokeLineCap = getStrokeLineCap(
+                        a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_strokeLineJoin] == 0) {
+                mStrokeLineJoin = getStrokeLineJoin(
+                        a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_strokeMiterLimit] == 0) {
+                mStrokeMiterlimit = a.getFloat(
+                        R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_stroke] == 0) {
+                mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_strokeOpacity] == 0) {
+                mStrokeOpacity = a.getFloat(
+                        R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_strokeWidth] == 0) {
+                mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+            }
+
+            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_trimPathEnd] == 0) {
+                mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_trimPathOffset] == 0) {
+                mTrimPathOffset = a.getFloat(
+                        R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+            }
+
+            if (themeAttrs == null
+                    || themeAttrs[R.styleable.VectorDrawablePath_trimPathStart] == 0) {
+                mTrimPathStart = a.getFloat(
+                        R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
+            }
+
+            // TODO: Consider replacing this with existing state attributes.
+            final int[] states = {
+                    R.styleable.VectorDrawablePath_state_activated,
                     R.styleable.VectorDrawablePath_state_checkable,
                     R.styleable.VectorDrawablePath_state_checked,
                     R.styleable.VectorDrawablePath_state_enabled,
@@ -1309,15 +1509,83 @@
                     R.styleable.VectorDrawablePath_state_hovered,
                     R.styleable.VectorDrawablePath_state_pressed,
                     R.styleable.VectorDrawablePath_state_selected,
-                    R.styleable.VectorDrawablePath_state_window_focused};
-            for (int state : states) {
+                    R.styleable.VectorDrawablePath_state_window_focused
+            };
+
+            final int N = states.length;
+            for (int i = 0; i < N; i++) {
+                final int state = states[i];
                 if (a.hasValue(state)) {
                     addStateFilter(state, a.getBoolean(state, false));
                 }
             }
+
+            updateColorAlphas();
+
             a.recycle();
         }
 
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null;
+        }
+
+        public void applyTheme(Theme t) {
+            if (mThemeAttrs == null) {
+                return;
+            }
+
+            final TypedArray a = t.resolveAttributes(
+                    mThemeAttrs, R.styleable.VectorDrawablePath, 0, 0);
+
+            mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
+
+            if (a.hasValue(R.styleable.VectorDrawablePath_name)) {
+                mId = a.getString(R.styleable.VectorDrawablePath_name);
+            }
+
+            if (a.hasValue(R.styleable.VectorDrawablePath_pathData)) {
+                mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+            }
+
+            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
+            mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
+
+            mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, mRotate);
+            mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, mPivotX);
+            mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, mPivotY);
+
+            mStrokeLineCap = getStrokeLineCap(a.getInt(
+                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
+            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
+                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
+            mStrokeMiterlimit = a.getFloat(
+                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
+            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+            mStrokeOpacity = a.getFloat(
+                    R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
+            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+
+            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
+            mTrimPathOffset = a.getFloat(
+                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+            mTrimPathStart = a.getFloat(
+                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
+
+            updateColorAlphas();
+        }
+
+        private void updateColorAlphas() {
+            if (!Float.isNaN(mFillOpacity)) {
+                mFillColor &= 0x00FFFFFF;
+                mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+            }
+
+            if (!Float.isNaN(mStrokeOpacity)) {
+                mStrokeColor &= 0x00FFFFFF;
+                mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+            }
+        }
+
         private static int nextStart(String s, int end) {
             char c;
 
@@ -1423,8 +1691,8 @@
             mTrimPathStart = p1.mTrimPathStart;
             mTrimPathEnd = p1.mTrimPathEnd;
             mTrimPathOffset = p1.mTrimPathOffset;
-            mStrokelineCap = p1.mStrokelineCap;
-            mStrokelineJoin = p1.mStrokelineJoin;
+            mStrokeLineCap = p1.mStrokeLineCap;
+            mStrokeLineJoin = p1.mStrokeLineJoin;
             mStrokeMiterlimit = p1.mStrokeMiterlimit;
             mNumberOfStates = p1.mNumberOfStates;
             for (int i = 0; i < mNumberOfStates; i++) {
@@ -1461,13 +1729,13 @@
                     returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
                     returnPath.mStrokeMiterlimit =
                             t1 * p1.mStrokeMiterlimit + t * p2.mStrokeMiterlimit;
-                    returnPath.mStrokelineCap = p1.mStrokelineCap;
-                    if (returnPath.mStrokelineCap == null) {
-                        returnPath.mStrokelineCap = p2.mStrokelineCap;
+                    returnPath.mStrokeLineCap = p1.mStrokeLineCap;
+                    if (returnPath.mStrokeLineCap == null) {
+                        returnPath.mStrokeLineCap = p2.mStrokeLineCap;
                     }
-                    returnPath.mStrokelineJoin = p1.mStrokelineJoin;
-                    if (returnPath.mStrokelineJoin == null) {
-                        returnPath.mStrokelineJoin = p2.mStrokelineJoin;
+                    returnPath.mStrokeLineJoin = p1.mStrokeLineJoin;
+                    if (returnPath.mStrokeLineJoin == null) {
+                        returnPath.mStrokeLineJoin = p2.mStrokeLineJoin;
                     }
                     returnPath.mFillRule = p1.mFillRule;
 
@@ -1552,49 +1820,49 @@
     }
 
     private static class VNode {
-        char type;
-        float[] params;
-        private static float[] current = new float[4];
+        private char mType;
+        private float[] mParams;
+
         public VNode(char type, float[] params) {
-            this.type = type;
-            this.params = params;
+            mType = type;
+            mParams = params;
         }
 
         public VNode(VNode n) {
-            this.type = n.type;
-            this.params = Arrays.copyOf(n.params, n.params.length);
+            mType = n.mType;
+            mParams = Arrays.copyOf(n.mParams, n.mParams.length);
         }
 
         public VNode(VNode n1, VNode n2, float t) {
-            this.type = n1.type;
-            this.params = new float[n1.params.length];
+            mType = n1.mType;
+            mParams = new float[n1.mParams.length];
             interpolate(n1, n2, t);
         }
 
         private boolean match(VNode n) {
-            if (n.type != type) {
+            if (n.mType != mType) {
                 return false;
             }
-            return (params.length == n.params.length);
+            return (mParams.length == n.mParams.length);
         }
 
         public void interpolate(VNode n1, VNode n2, float t) {
-            for (int i = 0; i < n1.params.length; i++) {
-                params[i] = n1.params[i] * (1 - t) + n2.params[i] * t;
+            for (int i = 0; i < n1.mParams.length; i++) {
+                mParams[i] = n1.mParams[i] * (1 - t) + n2.mParams[i] * t;
             }
         }
 
         private void nodeListToPath(VNode[] node, Path path) {
             float[] current = new float[4];
             for (int i = 0; i < node.length; i++) {
-                addCommand(path, current, node[i].type, node[i].params);
+                addCommand(path, current, node[i].mType, node[i].mParams);
             }
         }
 
         public static void createPath(VNode[] node, Path path) {
-            Arrays.fill(current,0);
+            float[] current = new float[4];
             for (int i = 0; i < node.length; i++) {
-                addCommand(path, current, node[i].type, node[i].params);
+                addCommand(path, current, node[i].mType, node[i].mParams);
             }
         }
 
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 649f4c3..6f2af90 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -34,7 +34,7 @@
 class AndroidRuntime
 {
 public:
-    AndroidRuntime();
+    AndroidRuntime(char* argBlockStart, size_t argBlockSize);
     virtual ~AndroidRuntime();
 
     enum StartMode {
@@ -44,6 +44,8 @@
         Tool,
     };
 
+    void setArgv0(const char* argv0);
+
     /**
      * Register a set of methods in the specified class.
      */
@@ -120,6 +122,8 @@
 
     Vector<JavaVMOption> mOptions;
     bool mExitWithoutCleanup;
+    char* const mArgBlockStart;
+    const size_t mArgBlockLength;
 
     /* JNI JavaVM pointer */
     static JavaVM* mJavaVM;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 7cc10be87..4d8e512 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1054,6 +1054,7 @@
         UI_MODE_TYPE_CAR = ACONFIGURATION_UI_MODE_TYPE_CAR,
         UI_MODE_TYPE_TELEVISION = ACONFIGURATION_UI_MODE_TYPE_TELEVISION,
         UI_MODE_TYPE_APPLIANCE = ACONFIGURATION_UI_MODE_TYPE_APPLIANCE,
+        UI_MODE_TYPE_WATCH = ACONFIGURATION_UI_MODE_TYPE_WATCH,
 
         // uiMode bits for the night switch.
         MASK_UI_MODE_NIGHT = 0x30,
diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h
index fc810be..a357a01 100644
--- a/include/private/hwui/DrawGlInfo.h
+++ b/include/private/hwui/DrawGlInfo.h
@@ -55,7 +55,10 @@
         kModeDraw,
         // Indicates the the functor is called only to perform
         // processing and that no draw should be attempted
-        kModeProcess
+        kModeProcess,
+        // Same as kModeProcess, however there is no GL context because it was
+        // lost or destroyed
+        kModeProcessNoContext
     };
 
     /**
@@ -65,14 +68,6 @@
     enum Status {
         // The functor is done
         kStatusDone = 0x0,
-        // The functor is requesting a redraw (the clip rect
-        // used by the redraw is specified by DrawGlInfo.)
-        // The rest of the UI might redraw too.
-        kStatusDraw = 0x1,
-        // The functor needs to be invoked again but will
-        // not redraw. Only the functor is invoked again
-        // (unless another functor requests a redraw.)
-        kStatusInvoke = 0x2,
         // DisplayList actually issued GL drawing commands.
         // This is used to signal the HardwareRenderer that the
         // buffers should be flipped - otherwise, there were no
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 7616ab0..098753b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2557,6 +2557,9 @@
             case ResTable_config::UI_MODE_TYPE_APPLIANCE:
                 res.append("appliance");
                 break;
+            case ResTable_config::UI_MODE_TYPE_WATCH:
+                res.append("watch");
+                break;
             default:
                 res.appendFormat("uiModeType=%d",
                         dtohs(screenLayout&ResTable_config::MASK_UI_MODE_TYPE));
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 477d691..df2123b 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -315,24 +315,15 @@
     pathCache.clearGarbage();
     patchCache.clearGarbage();
 
-    Vector<RenderNode*> displayLists;
     Vector<Layer*> layers;
 
     { // scope for the lock
         Mutex::Autolock _l(mGarbageLock);
-        displayLists = mDisplayListGarbage;
         layers = mLayerGarbage;
-        mDisplayListGarbage.clear();
         mLayerGarbage.clear();
     }
 
-    size_t count = displayLists.size();
-    for (size_t i = 0; i < count; i++) {
-        RenderNode* displayList = displayLists.itemAt(i);
-        delete displayList;
-    }
-
-    count = layers.size();
+    size_t count = layers.size();
     for (size_t i = 0; i < count; i++) {
         Layer* layer = layers.itemAt(i);
         delete layer;
@@ -345,11 +336,6 @@
     mLayerGarbage.push(layer);
 }
 
-void Caches::deleteDisplayListDeferred(RenderNode* displayList) {
-    Mutex::Autolock _l(mGarbageLock);
-    mDisplayListGarbage.push(displayList);
-}
-
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 50c5fef..ba3ccaf 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -166,11 +166,6 @@
      */
     void deleteLayerDeferred(Layer* layer);
 
-    /*
-     * Can be used to delete a display list from a non EGL thread.
-     */
-    void deleteDisplayListDeferred(RenderNode* layer);
-
     /**
      * Binds the VBO used to render simple textured quads.
      */
@@ -420,7 +415,6 @@
 
     mutable Mutex mGarbageLock;
     Vector<Layer*> mLayerGarbage;
-    Vector<RenderNode*> mDisplayListGarbage;
 
     DebugLevel mDebugLevel;
     bool mInitialized;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 5b4e03f..ce711b6 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -68,13 +68,13 @@
     mLayer->setColorFilter(mColorFilter);
     mLayer->setAlpha(mAlpha, mMode);
 
-    if (mDisplayList) {
+    if (mDisplayList.get()) {
         if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) {
             success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
         }
         mLayer->setBlend(mBlend);
         mDisplayList->updateProperties();
-        mLayer->updateDeferred(mDisplayList,
+        mLayer->updateDeferred(mDisplayList.get(),
                 mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
         mDirtyRect.setEmpty();
         mDisplayList = 0;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 10fa264..ce08c2d 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -101,7 +101,7 @@
     // Layer type specific properties
     // displayList and surfaceTexture are mutually exclusive, only 1 may be set
     // dirtyRect is only valid if displayList is set
-    RenderNode* mDisplayList;
+    sp<RenderNode> mDisplayList;
     Rect mDirtyRect;
     sp<GLConsumer> mSurfaceTexture;
     SkMatrix* mTransform;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 9e6a96d..a5d8dcb 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -29,6 +29,13 @@
 namespace android {
 namespace uirenderer {
 
+DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {
+}
+
+DisplayListData::~DisplayListData() {
+    cleanupResources();
+}
+
 void DisplayListData::cleanupResources() {
     Caches& caches = Caches::getInstance();
     caches.unregisterFunctors(functorCount);
@@ -91,5 +98,12 @@
     layers.clear();
 }
 
+void DisplayListData::addChild(DrawDisplayListOp* op) {
+    LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!");
+
+    mChildren.push(op);
+    mReferenceHolders.push(op->renderNode());
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index df5cba6..fe70d13 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -41,6 +41,7 @@
 #include "Matrix.h"
 #include "DeferredDisplayList.h"
 #include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
 
 class SkBitmap;
 class SkPaint;
@@ -106,8 +107,8 @@
  */
 class DisplayListData {
 public:
-    DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {}
-    virtual ~DisplayListData() { cleanupResources(); }
+    DisplayListData();
+    ~DisplayListData();
 
     // allocator into which all ops were allocated
     LinearAllocator allocator;
@@ -115,9 +116,6 @@
     // pointers to all ops within display list, pointing into allocator data
     Vector<DisplayListOp*> displayListOps;
 
-    // list of children display lists for quick, non-drawing traversal
-    Vector<DrawDisplayListOp*> children;
-
     // index of DisplayListOp restore, after which projected descendents should be drawn
     int projectionReceiveIndex;
 
@@ -139,7 +137,15 @@
         return !displayListOps.size();
     }
 
+    void addChild(DrawDisplayListOp* childOp);
+    const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+
 private:
+    Vector< sp<VirtualLightRefBase> > mReferenceHolders;
+
+    // list of children display lists for quick, non-drawing traversal
+    Vector<DrawDisplayListOp*> mChildren;
+
     void cleanupResources();
 };
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9e367fc..06f675e 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1499,13 +1499,13 @@
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) {
         if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
-            mDisplayList->defer(deferStruct, level + 1);
+            mDisplayList->deferNodeInParent(deferStruct, level + 1);
         }
     }
     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
             bool useQuickReject) {
         if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
-            mDisplayList->replay(replayStruct, level + 1);
+            mDisplayList->replayNodeInParent(replayStruct, level + 1);
         }
     }
 
@@ -1523,6 +1523,8 @@
 
     virtual const char* name() { return "DrawDisplayList"; }
 
+    RenderNode* renderNode() { return mDisplayList; }
+
 private:
     RenderNode* mDisplayList;
     const int mFlags;
@@ -1548,14 +1550,16 @@
 };
 
 /**
- * Not a canvas operation, used only by 3d / z ordering logic in DisplayList::iterate()
+ * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
  */
 class DrawShadowOp : public DrawOp {
 public:
-    DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha,
+    DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
+            float casterAlpha, bool casterUnclipped,
             float fallbackWidth, float fallbackHeight,
             const SkPath* outline, const SkPath* revealClip)
-            : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), mAlpha(alpha),
+            : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
+            mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped),
             mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight),
             mOutline(outline), mRevealClip(revealClip) {}
 
@@ -1572,7 +1576,8 @@
             Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter);
         }
 
-        return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &casterPerimeter);
+        return renderer.drawShadow(mTransformXY, mTransformZ,
+                mCasterAlpha, mCasterUnclipped, &casterPerimeter);
     }
 
     virtual void output(int level, uint32_t logFlags) const {
@@ -1584,7 +1589,8 @@
 private:
     const mat4 mTransformXY;
     const mat4 mTransformZ;
-    const float mAlpha;
+    const float mCasterAlpha;
+    const bool mCasterUnclipped;
     const float mFallbackWidth;
     const float mFallbackHeight;
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 78c97e1..a84aa6b 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -191,7 +191,7 @@
     DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
             flags, *currentTransform());
     addDrawOp(op);
-    mDisplayListData->children.push(op);
+    mDisplayListData->addChild(op);
     if (displayList->isProjectionReceiver()) {
         mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
     }
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 4457c61..bfe4eda 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -140,6 +140,15 @@
     }
 }
 
+void Layer::updateDeferred(RenderNode* displayList,
+        int left, int top, int right, int bottom) {
+    requireRenderer();
+    this->displayList = displayList;
+    const Rect r(left, top, right, bottom);
+    dirtyRect.unionWith(r);
+    deferredUpdateScheduled = true;
+}
+
 void Layer::setPaint(const SkPaint* paint) {
     OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
     setColorFilter((paint) ? paint->getColorFilter() : NULL);
@@ -209,7 +218,7 @@
             dirtyRect.right, dirtyRect.bottom, !isBlend());
 
     displayList->computeOrdering();
-    displayList->defer(deferredState, 0);
+    displayList->deferNodeTree(deferredState);
 
     deferredUpdateScheduled = false;
 }
@@ -244,7 +253,7 @@
     renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
             !isBlend());
 
-    renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren);
+    renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
 
     renderer->finish();
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b428404..5375b45 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -19,6 +19,7 @@
 
 #include <cutils/compiler.h>
 #include <sys/types.h>
+#include <utils/StrongPointer.h>
 
 #include <GLES2/gl2.h>
 
@@ -85,13 +86,7 @@
     }
 
     void updateDeferred(RenderNode* displayList,
-            int left, int top, int right, int bottom) {
-        requireRenderer();
-        this->displayList = displayList;
-        const Rect r(left, top, right, bottom);
-        dirtyRect.unionWith(r);
-        deferredUpdateScheduled = true;
-    }
+            int left, int top, int right, int bottom);
 
     inline uint32_t getWidth() const {
         return texture.width;
@@ -294,7 +289,7 @@
      */
     bool deferredUpdateScheduled;
     OpenGLRenderer* renderer;
-    RenderNode* displayList;
+    sp<RenderNode> displayList;
     Rect dirtyRect;
     bool debugDrawUpdate;
     bool hasDrawnSinceUpdate;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d808735..9dbcd36 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -409,15 +409,6 @@
         for (size_t i = 0; i < count; i++) {
             Functor* f = functors.itemAt(i);
             result |= (*f)(DrawGlInfo::kModeProcess, &info);
-
-            if (result & DrawGlInfo::kStatusDraw) {
-                Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
-                dirty.unionWith(localDirty);
-            }
-
-            if (result & DrawGlInfo::kStatusInvoke) {
-                mFunctors.add(f);
-            }
         }
         resume();
     }
@@ -461,19 +452,10 @@
     interrupt();
 
     // call functor immediately after GL state setup
-    status_t result = (*functor)(DrawGlInfo::kModeDraw, &info);
-
-    if (result != DrawGlInfo::kStatusDone) {
-        Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
-        dirty.unionWith(localDirty);
-
-        if (result & DrawGlInfo::kStatusInvoke) {
-            mFunctors.add(functor);
-        }
-    }
+    (*functor)(DrawGlInfo::kModeDraw, &info);
 
     resume();
-    return result | DrawGlInfo::kStatusDrew;
+    return DrawGlInfo::kStatusDrew;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -555,7 +537,7 @@
 
 bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
     if (layer->deferredUpdateScheduled && layer->renderer &&
-            layer->displayList && layer->displayList->isRenderable()) {
+            layer->displayList.get() && layer->displayList->isRenderable()) {
         ATRACE_CALL();
 
         Rect& dirty = layer->dirtyRect;
@@ -1924,14 +1906,14 @@
         if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             status = startFrame();
             ReplayStateStruct replayStruct(*this, dirty, replayFlags);
-            displayList->replay(replayStruct, 0);
+            displayList->replayNodeTree(replayStruct);
             return status | replayStruct.mDrawGlStatus;
         }
 
         bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
         DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
         DeferStateStruct deferStruct(deferredList, *this, replayFlags);
-        displayList->defer(deferStruct, 0);
+        displayList->deferNodeTree(deferStruct);
 
         flushLayers();
         status = startFrame();
@@ -3203,7 +3185,7 @@
 }
 
 status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
-        float casterAlpha, const SkPath* casterPerimeter) {
+        float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter) {
     if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
     // TODO: use quickRejectWithScissor. For now, always force enable scissor.
@@ -3260,7 +3242,7 @@
     Rect casterBounds(casterPerimeter->getBounds());
     casterTransformXY.mapRect(casterBounds);
 
-    bool isCasterOpaque = (casterAlpha == 1.0f);
+    bool isCasterOpaque = (casterAlpha == 1.0f) && casterUnclipped;
     // draw caster's shadows
     if (mCaches.propertyAmbientShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 054767e..2debd2e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -210,7 +210,7 @@
     virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
 
     status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
-            float casterAlpha, const SkPath* casterPerimeter);
+            float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 675b215..5010076 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -59,13 +59,6 @@
     delete mDisplayListData;
 }
 
-void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) {
-    if (displayList) {
-        DISPLAY_LIST_LOGD("Deferring display list destruction");
-        Caches::getInstance().deleteDisplayListDeferred(displayList);
-    }
-}
-
 void RenderNode::setData(DisplayListData* data) {
     delete mDisplayListData;
     mDisplayListData = data;
@@ -100,8 +93,8 @@
     }
 
     if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
-            RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+            RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
             childNode->updateProperties();
         }
     }
@@ -114,8 +107,8 @@
         return true;
     }
 
-    for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
-        RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+    for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+        RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
         if (childNode->hasFunctors()) {
             return true;
         }
@@ -132,10 +125,9 @@
 #define PROPERTY_SAVECOUNT 0
 
 template <class T>
-void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
-        const int level) {
+void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
 #if DEBUG_DISPLAY_LIST
-    properties().debugOutputProperties(level);
+    properties().debugOutputProperties(handler.level() + 1);
 #endif
     if (properties().getLeft() != 0 || properties().getTop() != 0) {
         renderer.translate(properties().getLeft(), properties().getTop());
@@ -245,8 +237,8 @@
     // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
     // transform properties are applied correctly to top level children
     if (mDisplayListData == NULL) return;
-    for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children[i];
+    for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         childOp->mDisplayList->computeOrderingImpl(childOp,
                 &mProjectedNodes, &mat4::identity());
     }
@@ -274,11 +266,11 @@
         opState->mSkipInOrderDraw = false;
     }
 
-    if (mDisplayListData->children.size() > 0) {
+    if (mDisplayListData->children().size() > 0) {
         const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
         bool haveAppliedPropertiesToProjection = false;
-        for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-            DrawDisplayListOp* childOp = mDisplayListData->children[i];
+        for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+            DrawDisplayListOp* childOp = mDisplayListData->children()[i];
             RenderNode* child = childOp->mDisplayList;
 
             Vector<DrawDisplayListOp*>* projectionChildren = NULL;
@@ -302,7 +294,6 @@
             child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
         }
     }
-
 }
 
 class DeferOperationHandler {
@@ -313,15 +304,25 @@
         operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds);
     }
     inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); }
+    inline void startMark(const char* name) {} // do nothing
+    inline void endMark() {}
+    inline int level() { return mLevel; }
+    inline int replayFlags() { return mDeferStruct.mReplayFlags; }
 
 private:
     DeferStateStruct& mDeferStruct;
     const int mLevel;
 };
 
-void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
+void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
+    DeferOperationHandler handler(deferStruct, 0);
+    if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+    issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
+}
+
+void RenderNode::deferNodeInParent(DeferStateStruct& deferStruct, const int level) {
     DeferOperationHandler handler(deferStruct, level);
-    iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
+    issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
 }
 
 class ReplayOperationHandler {
@@ -335,28 +336,38 @@
         operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
     }
     inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); }
+    inline void startMark(const char* name) {
+        mReplayStruct.mRenderer.startMark(name);
+    }
+    inline void endMark() {
+        mReplayStruct.mRenderer.endMark();
+        DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
+                mReplayStruct.mDrawGlStatus);
+    }
+    inline int level() { return mLevel; }
+    inline int replayFlags() { return mReplayStruct.mReplayFlags; }
 
 private:
     ReplayStateStruct& mReplayStruct;
     const int mLevel;
 };
 
-void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
+void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
+    ReplayOperationHandler handler(replayStruct, 0);
+    if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+    issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
+}
+
+void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int level) {
     ReplayOperationHandler handler(replayStruct, level);
-
-    replayStruct.mRenderer.startMark(mName.string());
-    iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
-    replayStruct.mRenderer.endMark();
-
-    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
-            replayStruct.mDrawGlStatus);
+    issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
 }
 
 void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
-    if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return;
+    if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
 
-    for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children[i];
+    for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         RenderNode* child = childOp->mDisplayList;
         float childZ = child->properties().getTranslationZ();
 
@@ -373,10 +384,42 @@
     std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
 }
 
+template <class T>
+void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
+    if (properties().getAlpha() <= 0.0f) return;
+
+    mat4 shadowMatrixXY(transformFromParent);
+    applyViewPropertyTransforms(shadowMatrixXY);
+
+    // Z matrix needs actual 3d transformation, so mapped z values will be correct
+    mat4 shadowMatrixZ(transformFromParent);
+    applyViewPropertyTransforms(shadowMatrixZ, true);
+
+    const SkPath* outlinePath = properties().getOutline().getPath();
+    const RevealClip& revealClip = properties().getRevealClip();
+    const SkPath* revealClipPath = revealClip.hasConvexClip()
+            ?  revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
+
+    /**
+     * The drawing area of the caster is always the same as the its perimeter (which
+     * the shadow system uses) *except* in the inverse clip case. Inform the shadow
+     * system that the caster's drawing area (as opposed to its perimeter) has been
+     * clipped, so that it knows the caster can't be opaque.
+     */
+    bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip();
+
+    DisplayListOp* shadowOp  = new (handler.allocator()) DrawShadowOp(
+            shadowMatrixXY, shadowMatrixZ,
+            properties().getAlpha(), casterUnclipped,
+            properties().getWidth(), properties().getHeight(),
+            outlinePath, revealClipPath);
+    handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+}
+
 #define SHADOW_DELTA 0.1f
 
 template <class T>
-void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
         ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
     const int size = zTranslatedNodes.size();
     if (size == 0
@@ -386,12 +429,6 @@
         return;
     }
 
-    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
-    LinearAllocator& alloc = handler.allocator();
-    ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
-            SkRegion::kIntersect_Op); // clip to 3d root bounds
-    handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
     /**
      * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
      * with very similar Z heights to draw together.
@@ -419,26 +456,7 @@
             // attempt to render the shadow if the caster about to be drawn is its caster,
             // OR if its caster's Z value is similar to the previous potential caster
             if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
-
-                if (caster->properties().getAlpha() > 0.0f) {
-                    mat4 shadowMatrixXY(casterOp->mTransformFromParent);
-                    caster->applyViewPropertyTransforms(shadowMatrixXY);
-
-                    // Z matrix needs actual 3d transformation, so mapped z values will be correct
-                    mat4 shadowMatrixZ(casterOp->mTransformFromParent);
-                    caster->applyViewPropertyTransforms(shadowMatrixZ, true);
-
-                    const SkPath* outlinePath = caster->properties().getOutline().getPath();
-                    const RevealClip& revealClip = caster->properties().getRevealClip();
-                    const SkPath* revealClipPath = revealClip.hasConvexClip()
-                            ?  revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
-
-                    DisplayListOp* shadowOp  = new (alloc) DrawShadowOp(
-                            shadowMatrixXY, shadowMatrixZ, caster->properties().getAlpha(),
-                            caster->properties().getWidth(), caster->properties().getHeight(),
-                            outlinePath, revealClipPath);
-                    handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-                }
+                caster->issueDrawShadowOperation(casterOp->mTransformFromParent, handler);
 
                 lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
                 shadowIndex++;
@@ -461,17 +479,10 @@
         renderer.restoreToCount(restoreTo);
         drawIndex++;
     }
-    handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
 
 template <class T>
-void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
-    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
-    LinearAllocator& alloc = handler.allocator();
-    ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
-            SkRegion::kReplace_Op); // clip to projection surface root bounds
-    handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
+void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
     for (size_t i = 0; i < mProjectedNodes.size(); i++) {
         DrawDisplayListOp* childOp = mProjectedNodes[i];
 
@@ -483,7 +494,6 @@
         childOp->mSkipInOrderDraw = true;
         renderer.restoreToCount(restoreTo);
     }
-    handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
 }
 
 /**
@@ -496,7 +506,8 @@
  * defer vs replay logic, per operation
  */
 template <class T>
-void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
+void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
+    const int level = handler.level();
     if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
         ALOGW("Error: %s is drawing after destruction", mName.string());
         CRASH();
@@ -506,6 +517,8 @@
         return;
     }
 
+    handler.startMark(mName.string());
+
 #if DEBUG_DISPLAY_LIST
     Rect* clipRect = renderer.getClipRect();
     DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f",
@@ -521,7 +534,7 @@
     DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
 
-    setViewProperties<T>(renderer, handler, level + 1);
+    setViewProperties<T>(renderer, handler);
 
     bool quickRejected = properties().getClipToBounds()
             && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
@@ -530,7 +543,7 @@
         buildZSortedChildList(zTranslatedNodes);
 
         // for 3d root, draw children with negative z values
-        iterate3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
+        issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
 
         DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
         const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -541,23 +554,24 @@
 #if DEBUG_DISPLAY_LIST
             op->output(level + 1);
 #endif
-
             logBuffer.writeCommand(level, op->name());
             handler(op, saveCountOffset, properties().getClipToBounds());
 
             if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
-                iterateProjectedChildren(renderer, handler, level);
+                issueOperationsOfProjectedChildren(renderer, handler);
             }
         }
 
         // for 3d root, draw children with positive z values
-        iterate3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
+        issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
     }
 
     DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
     handler(new (alloc) RestoreToCountOp(restoreTo),
             PROPERTY_SAVECOUNT, properties().getClipToBounds());
     renderer.setOverrideLayerAlpha(1.0f);
+
+    handler.endMark();
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 291d03d..fd0fabc 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -41,6 +41,7 @@
 #include "DeferredDisplayList.h"
 #include "DisplayList.h"
 #include "RenderProperties.h"
+#include "utils/VirtualLightRefBase.h"
 
 class SkBitmap;
 class SkPaint;
@@ -76,7 +77,7 @@
  * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay
  * attached.
  */
-class RenderNode {
+class RenderNode : public VirtualLightRefBase {
 public:
     ANDROID_API RenderNode();
     ANDROID_API ~RenderNode();
@@ -86,14 +87,17 @@
         kReplayFlag_ClipChildren = 0x1
     };
 
-    ANDROID_API static void destroyDisplayListDeferred(RenderNode* displayList);
     ANDROID_API static void outputLogBuffer(int fd);
 
     ANDROID_API void setData(DisplayListData* newData);
 
     void computeOrdering();
-    void defer(DeferStateStruct& deferStruct, const int level);
-    void replay(ReplayStateStruct& replayStruct, const int level);
+
+    void deferNodeTree(DeferStateStruct& deferStruct);
+    void deferNodeInParent(DeferStateStruct& deferStruct, const int level);
+
+    void replayNodeTree(ReplayStateStruct& replayStruct);
+    void replayNodeInParent(ReplayStateStruct& replayStruct, const int level);
 
     ANDROID_API void output(uint32_t level = 1);
 
@@ -164,19 +168,26 @@
             const mat4* transformFromProjectionSurface);
 
     template <class T>
-    inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
+    inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
 
     void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes);
 
+    template<class T>
+    inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
+
     template <class T>
-    inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+    inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
             ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
 
     template <class T>
-    inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level);
+    inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
 
+    /**
+     * Issue the RenderNode's operations into a handler, recursing for subtrees through
+     * DrawDisplayListOp's defer() or replay() methods
+     */
     template <class T>
-    inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
+    inline void issueOperations(OpenGLRenderer& renderer, T& handler);
 
     class TextContainer {
     public:
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 3975a76..e7e7768 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -45,28 +45,24 @@
         , mPrevWidth(-1), mPrevHeight(-1)
         , mPivotExplicitlySet(false)
         , mMatrixDirty(false)
-        , mMatrixIsIdentity(true)
         , mMatrixFlags(0)
         , mCaching(false) {
 }
 
 RenderProperties::ComputedFields::ComputedFields()
         : mTransformMatrix(NULL)
-        , mTransformCamera(NULL)
         , mTransformMatrix3D(NULL)
         , mClipPath(NULL) {
 }
 
 RenderProperties::ComputedFields::~ComputedFields() {
     delete mTransformMatrix;
-    delete mTransformCamera;
     delete mTransformMatrix3D;
     delete mClipPath;
 }
 
 RenderProperties::RenderProperties()
-        : mCameraDistance(0)
-        , mStaticMatrix(NULL)
+        : mStaticMatrix(NULL)
         , mAnimationMatrix(NULL) {
 }
 
@@ -82,9 +78,12 @@
         setAnimationMatrix(other.getAnimationMatrix());
         setCameraDistance(other.getCameraDistance());
 
-        // Update the computed fields
-        updateMatrix();
+        // Update the computed clip path
         updateClipPath();
+
+        // Force recalculation of the matrix, since other's dirty bit may be clear
+        mPrimitiveFields.mMatrixDirty = true;
+        updateMatrix();
     }
     return *this;
 }
@@ -106,8 +105,8 @@
             ALOGD("%*sTranslate %.2f, %.2f, %.2f",
                     level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ);
         } else {
-            ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING,
-                    level * 2, "", mComputedFields.mTransformMatrix, MATRIX_4_ARGS(mComputedFields.mTransformMatrix));
+            ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING,
+                    level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
         }
     }
 
@@ -141,7 +140,7 @@
         if (mPrimitiveFields.mMatrixFlags && mPrimitiveFields.mMatrixFlags != TRANSLATION) {
             if (!mComputedFields.mTransformMatrix) {
                 // only allocate a mPrimitiveFields.matrix if we have a complex transform
-                mComputedFields.mTransformMatrix = new Matrix4();
+                mComputedFields.mTransformMatrix = new SkMatrix();
             }
             if (!mPrimitiveFields.mPivotExplicitlySet) {
                 if (mPrimitiveFields.mWidth != mPrimitiveFields.mPrevWidth || mPrimitiveFields.mHeight != mPrimitiveFields.mPrevHeight) {
@@ -153,33 +152,31 @@
             }
 
             if ((mPrimitiveFields.mMatrixFlags & ROTATION_3D) == 0) {
-                mComputedFields.mTransformMatrix->loadTranslate(
-                        mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
-                        mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY,
-                        0);
-                mComputedFields.mTransformMatrix->rotate(mPrimitiveFields.mRotation, 0, 0, 1);
-                mComputedFields.mTransformMatrix->scale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, 1);
-                mComputedFields.mTransformMatrix->translate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
+                mComputedFields.mTransformMatrix->setTranslate(
+                        mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY);
+                mComputedFields.mTransformMatrix->preRotate(mPrimitiveFields.mRotation,
+                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
+                mComputedFields.mTransformMatrix->preScale(
+                        mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
+                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
             } else {
-                if (!mComputedFields.mTransformCamera) {
-                    mComputedFields.mTransformCamera = new Sk3DView();
+                if (!mComputedFields.mTransformMatrix3D) {
                     mComputedFields.mTransformMatrix3D = new SkMatrix();
                 }
-                SkMatrix transformMatrix;
-                transformMatrix.reset();
-                mComputedFields.mTransformCamera->save();
-                transformMatrix.preScale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
-                mComputedFields.mTransformCamera->rotateX(mPrimitiveFields.mRotationX);
-                mComputedFields.mTransformCamera->rotateY(mPrimitiveFields.mRotationY);
-                mComputedFields.mTransformCamera->rotateZ(-mPrimitiveFields.mRotation);
-                mComputedFields.mTransformCamera->getMatrix(mComputedFields.mTransformMatrix3D);
+                mComputedFields.mTransformMatrix->reset();
+                mComputedFields.mTransformCamera.save();
+                mComputedFields.mTransformMatrix->preScale(
+                        mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
+                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
+                mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX);
+                mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY);
+                mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation);
+                mComputedFields.mTransformCamera.getMatrix(mComputedFields.mTransformMatrix3D);
                 mComputedFields.mTransformMatrix3D->preTranslate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
                 mComputedFields.mTransformMatrix3D->postTranslate(mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
                         mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY);
-                transformMatrix.postConcat(*mComputedFields.mTransformMatrix3D);
-                mComputedFields.mTransformCamera->restore();
-
-                mComputedFields.mTransformMatrix->load(transformMatrix);
+                mComputedFields.mTransformMatrix->postConcat(*mComputedFields.mTransformMatrix3D);
+                mComputedFields.mTransformCamera.restore();
             }
         }
         mPrimitiveFields.mMatrixDirty = false;
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 061e469..dd68210 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -258,20 +258,20 @@
         return mPrimitiveFields.mPivotY;
     }
 
+    bool isPivotExplicitlySet() const {
+        return mPrimitiveFields.mPivotExplicitlySet;
+    }
+
     void setCameraDistance(float distance) {
-        if (distance != mCameraDistance) {
-            mCameraDistance = distance;
+        if (distance != getCameraDistance()) {
             mPrimitiveFields.mMatrixDirty = true;
-            if (!mComputedFields.mTransformCamera) {
-                mComputedFields.mTransformCamera = new Sk3DView();
-                mComputedFields.mTransformMatrix3D = new SkMatrix();
-            }
-            mComputedFields.mTransformCamera->setCameraLocation(0, 0, distance);
+            mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
         }
     }
 
     float getCameraDistance() const {
-        return mCameraDistance;
+        // TODO: update getCameraLocationZ() to be const
+        return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
     }
 
     void setLeft(int left) {
@@ -396,7 +396,7 @@
         return mPrimitiveFields.mMatrixFlags;
     }
 
-    const Matrix4* getTransformMatrix() const {
+    const SkMatrix* getTransformMatrix() const {
         return mComputedFields.mTransformMatrix;
     }
 
@@ -481,13 +481,11 @@
         int mPrevWidth, mPrevHeight;
         bool mPivotExplicitlySet;
         bool mMatrixDirty;
-        bool mMatrixIsIdentity;
         uint32_t mMatrixFlags;
         bool mCaching;
     } mPrimitiveFields;
 
     // mCameraDistance isn't in mPrimitiveFields as it has a complex setter
-    float mCameraDistance;
     SkMatrix* mStaticMatrix;
     SkMatrix* mAnimationMatrix;
 
@@ -502,11 +500,12 @@
          * Stores the total transformation of the DisplayList based upon its scalar
          * translate/rotate/scale properties.
          *
-         * In the common translation-only case, the matrix isn't allocated and the mTranslation
-         * properties are used directly.
+         * In the common translation-only case, the matrix isn't necessarily allocated,
+         * and the mTranslation properties are used directly.
          */
-        Matrix4* mTransformMatrix;
-        Sk3DView* mTransformCamera;
+        SkMatrix* mTransformMatrix;
+
+        Sk3DView mTransformCamera;
         SkMatrix* mTransformMatrix3D;
         SkPath* mClipPath; // TODO: remove this, create new ops for efficient/special case clipping
         SkRegion::Op mClipPathOp;
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index cc6d0cd..5bdb18a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -108,7 +108,7 @@
      * Returns the current clip in local coordinates. The clip rect is
      * transformed by the inverse transform matrix.
      */
-    const Rect& getLocalClip();
+    ANDROID_API const Rect& getLocalClip();
 
     /**
      * Resets the clip to the specified rect.
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8ebffc2..c231f6f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -82,6 +82,8 @@
     // Returns true on success, false on failure
     void initialize();
 
+    bool hasContext();
+
     void usePBufferSurface();
     EGLSurface createSurface(EGLNativeWindowType window);
     void destroySurface(EGLSurface surface);
@@ -138,7 +140,7 @@
 }
 
 void GlobalContext::initialize() {
-    if (mEglDisplay != EGL_NO_DISPLAY) return;
+    if (hasContext()) return;
 
     mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
@@ -157,6 +159,10 @@
     initAtlas();
 }
 
+bool GlobalContext::hasContext() {
+    return mEglDisplay != EGL_NO_DISPLAY;
+}
+
 void GlobalContext::loadConfig() {
     EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
     EGLint attribs[] = {
@@ -411,7 +417,6 @@
 
     Rect outBounds;
     status |= mCanvas->drawDisplayList(displayList, outBounds);
-    handleFunctorStatus(status, outBounds);
 
     // TODO: Draw debug info
     // TODO: Performance tracking
@@ -441,6 +446,15 @@
     mCanvas->detachFunctor(functor);
 }
 
+void CanvasContext::invokeFunctor(Functor* functor) {
+    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
+    if (mGlobalContext->hasContext()) {
+        requireGlContext();
+        mode = DrawGlInfo::kModeProcess;
+    }
+    (*functor)(mode, NULL);
+}
+
 void CanvasContext::invokeFunctors() {
     mInvokeFunctorsPending = false;
 
@@ -448,22 +462,7 @@
 
     makeCurrent();
     Rect dirty;
-    int status = mCanvas->invokeFunctors(dirty);
-    handleFunctorStatus(status, dirty);
-}
-
-void CanvasContext::handleFunctorStatus(int status, const Rect& redrawClip) {
-    if (status & DrawGlInfo::kStatusDraw) {
-        // TODO: Invalidate the redrawClip
-        // Do we need to post to ViewRootImpl like the current renderer?
-        // Can we just enqueue ourselves to re-invoke the same display list?
-        // Something else entirely? Does ChromiumView still want this in a
-        // RenderThread world?
-    }
-
-    if (status & DrawGlInfo::kStatusInvoke) {
-        queueFunctorsTask();
-    }
+    mCanvas->invokeFunctors(dirty);
 }
 
 void CanvasContext::removeFunctorsTask() {
@@ -491,6 +490,16 @@
     task->run();
 }
 
+Layer* CanvasContext::createRenderLayer(int width, int height) {
+    requireGlContext();
+    return LayerRenderer::createRenderLayer(width, height);
+}
+
+Layer* CanvasContext::createTextureLayer() {
+    requireGlContext();
+    return LayerRenderer::createTextureLayer();
+}
+
 void CanvasContext::requireGlContext() {
     if (mEglSurface != EGL_NO_SURFACE) {
         mGlobalContext->makeCurrent(mEglSurface);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e3fdf97..6f1c37f 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -35,6 +35,7 @@
 class DisplayListData;
 class OpenGLRenderer;
 class Rect;
+class Layer;
 
 namespace renderthread {
 
@@ -72,9 +73,13 @@
 
     void attachFunctor(Functor* functor);
     void detachFunctor(Functor* functor);
+    void invokeFunctor(Functor* functor);
 
     void runWithGlContext(RenderTask* task);
 
+    Layer* createRenderLayer(int width, int height);
+    Layer* createTextureLayer();
+
 private:
     void setSurface(EGLNativeWindowType window);
     void swapBuffers();
@@ -82,7 +87,6 @@
 
     friend class InvokeFunctorsTask;
     void invokeFunctors();
-    void handleFunctorStatus(int status, const Rect& redrawClip);
     void removeFunctorsTask();
     void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
 
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e9089a..7b509a2 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,7 +30,19 @@
 namespace uirenderer {
 namespace renderthread {
 
-DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
+SetDisplayListData::SetDisplayListData() : mNewData(0) {}
+
+SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData)
+        : mTargetNode(node), mNewData(newData) {
+}
+
+SetDisplayListData::~SetDisplayListData() {}
+
+void SetDisplayListData::apply() const {
+    mTargetNode->setData(mNewData);
+}
+
+DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
 }
 
 DrawFrameTask::~DrawFrameTask() {
@@ -41,13 +53,15 @@
 }
 
 void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
-    SetDisplayListData setter;
-    setter.targetNode = renderNode;
-    setter.newData = newData;
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!");
+
+    SetDisplayListData setter(renderNode, newData);
     mDisplayListDataUpdates.push(setter);
 }
 
 void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
+
     mLayers.push(layer);
 }
 
@@ -61,6 +75,8 @@
 }
 
 void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setRenderNode with!");
+
     mRenderNode = renderNode;
 }
 
@@ -69,37 +85,55 @@
 }
 
 void DrawFrameTask::drawFrame(RenderThread* renderThread) {
-    LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!");
+    LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
-    AutoMutex _lock(mLock);
-    renderThread->queue(this);
-    mSignal.wait(mLock);
+    postAndWait(renderThread, MODE_FULL);
 
     // Reset the single-frame data
     mDirty.setEmpty();
     mRenderNode = 0;
 }
 
+void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
+    LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
+
+    postAndWait(renderThread, MODE_STATE_ONLY);
+}
+
+void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
+    LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
+
+    mTaskMode = mode;
+    AutoMutex _lock(mLock);
+    renderThread->queue(this);
+    mSignal.wait(mLock);
+}
+
 void DrawFrameTask::run() {
     ATRACE_NAME("DrawFrame");
 
     syncFrameState();
 
+    if (mTaskMode == MODE_STATE_ONLY) {
+        unblockUiThread();
+        return;
+    }
+
     // Grab a copy of everything we need
     Rect dirtyCopy(mDirty);
-    RenderNode* renderNode = mRenderNode;
+    sp<RenderNode> renderNode = mRenderNode;
     CanvasContext* context = mContext;
 
     // This is temporary until WebView has a solution for syncing frame state
-    bool canUnblockUiThread = !requiresSynchronousDraw(renderNode);
+    bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get());
 
     // From this point on anything in "this" is *UNSAFE TO ACCESS*
     if (canUnblockUiThread) {
         unblockUiThread();
     }
 
-    drawRenderNode(context, renderNode, &dirtyCopy);
+    drawRenderNode(context, renderNode.get(), &dirtyCopy);
 
     if (!canUnblockUiThread) {
         unblockUiThread();
@@ -111,12 +145,16 @@
 
     for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
         const SetDisplayListData& setter = mDisplayListDataUpdates[i];
-        setter.targetNode->setData(setter.newData);
+        setter.apply();
     }
     mDisplayListDataUpdates.clear();
 
     mContext->processLayerUpdates(&mLayers);
-    mRenderNode->updateProperties();
+
+    // If we don't have an mRenderNode this is a state flush only
+    if (mRenderNode.get()) {
+        mRenderNode->updateProperties();
+    }
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 5450dd5..4e9b244 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -18,6 +18,7 @@
 
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
 #include <utils/Vector.h>
 
 #include "RenderTask.h"
@@ -36,9 +37,16 @@
 class CanvasContext;
 class RenderThread;
 
-struct SetDisplayListData {
-    RenderNode* targetNode;
-    DisplayListData* newData;
+class SetDisplayListData {
+public:
+    // This ctor exists for Vector's usage
+    SetDisplayListData();
+    SetDisplayListData(RenderNode* node, DisplayListData* newData);
+    ~SetDisplayListData();
+    void apply() const;
+private:
+    sp<RenderNode> mTargetNode;
+    DisplayListData* mNewData;
 };
 
 /*
@@ -61,10 +69,18 @@
     void setRenderNode(RenderNode* renderNode);
     void setDirty(int left, int top, int right, int bottom);
     void drawFrame(RenderThread* renderThread);
+    void flushStateChanges(RenderThread* renderThread);
 
     virtual void run();
 
 private:
+    enum TaskMode {
+        MODE_INVALID,
+        MODE_FULL,
+        MODE_STATE_ONLY,
+    };
+
+    void postAndWait(RenderThread* renderThread, TaskMode mode);
     void syncFrameState();
     void unblockUiThread();
     static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
@@ -81,7 +97,8 @@
     /*********************************************
      *  Single frame data
      *********************************************/
-    RenderNode* mRenderNode;
+    TaskMode mTaskMode;
+    sp<RenderNode> mRenderNode;
     Rect mDirty;
     Vector<SetDisplayListData> mDisplayListDataUpdates;
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 16b93c3..e817e61 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -48,7 +48,7 @@
     LOG_ALWAYS_FATAL_IF( METHOD_INVOKE_PAYLOAD_SIZE < sizeof(ARGS(method)), \
         "METHOD_INVOKE_PAYLOAD_SIZE %d is smaller than sizeof(" #method "Args) %d", \
                 METHOD_INVOKE_PAYLOAD_SIZE, sizeof(ARGS(method))); \
-    MethodInvokeRenderTask* task = createTask((RunnableMethod) Bridge_ ## method); \
+    MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     ARGS(method) *args = (ARGS(method) *) task->payload()
 
 CREATE_BRIDGE1(createContext, bool translucent) {
@@ -75,6 +75,9 @@
 
 void RenderProxy::destroyContext() {
     if (mContext) {
+        // Flush any pending changes to ensure all garbage is destroyed
+        mDrawFrameTask.flushStateChanges(&mRenderThread);
+
         SETUP_TASK(destroyContext);
         args->context = mContext;
         mContext = 0;
@@ -138,6 +141,10 @@
 }
 
 void RenderProxy::destroyCanvas() {
+    // If the canvas is being destroyed we won't be drawing again anytime soon
+    // So flush any pending state changes to allow for resource cleanup.
+    mDrawFrameTask.flushStateChanges(&mRenderThread);
+
     SETUP_TASK(destroyCanvas);
     args->context = mContext;
     post(task);
@@ -167,6 +174,22 @@
     post(task);
 }
 
+CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
+    args->context->invokeFunctor(args->functor);
+    return NULL;
+}
+
+void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
+    SETUP_TASK(invokeFunctor);
+    args->context = mContext;
+    args->functor = functor;
+    if (waitForCompletion) {
+        postAndWait(task);
+    } else {
+        post(task);
+    }
+}
+
 CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
     args->context->runWithGlContext(args->task);
     return NULL;
@@ -179,10 +202,9 @@
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(createDisplayListLayer, int width, int height) {
-    Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height);
+CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
+    Layer* layer = args->context->createRenderLayer(args->width, args->height);
     if (!layer) return 0;
-
     return new DeferredLayerUpdater(layer);
 }
 
@@ -190,20 +212,22 @@
     SETUP_TASK(createDisplayListLayer);
     args->width = width;
     args->height = height;
+    args->context = mContext;
     void* retval = postAndWait(task);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
     mDrawFrameTask.addLayer(layer);
     return layer;
 }
 
-CREATE_BRIDGE0(createTextureLayer) {
-    Layer* layer = LayerRenderer::createTextureLayer();
+CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
+    Layer* layer = args->context->createTextureLayer();
     if (!layer) return 0;
     return new DeferredLayerUpdater(layer);
 }
 
 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
     SETUP_TASK(createTextureLayer);
+    args->context = mContext;
     void* retval = postAndWait(task);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
     mDrawFrameTask.addLayer(layer);
@@ -236,9 +260,14 @@
     post(task);
 }
 
-MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) {
-    // TODO: Consider having a small pool of these to avoid alloc churn
-    return new MethodInvokeRenderTask(method);
+CREATE_BRIDGE0(fence) {
+    // Intentionally empty
+    return NULL;
+}
+
+void RenderProxy::fence() {
+    SETUP_TASK(fence);
+    postAndWait(task);
 }
 
 void RenderProxy::post(RenderTask* task) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index ee7a4c7..c50da79 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,6 +69,7 @@
 
     ANDROID_API void attachFunctor(Functor* functor);
     ANDROID_API void detachFunctor(Functor* functor);
+    ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
 
     ANDROID_API void runWithGlContext(RenderTask* task);
 
@@ -77,6 +78,8 @@
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     ANDROID_API void destroyLayer(DeferredLayerUpdater* layer);
 
+    ANDROID_API void fence();
+
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
@@ -88,7 +91,6 @@
 
     void destroyContext();
 
-    MethodInvokeRenderTask* createTask(RunnableMethod method);
     void post(RenderTask* task);
     void* postAndWait(MethodInvokeRenderTask* task);
 
diff --git a/libs/hwui/utils/VirtualLightRefBase.h b/libs/hwui/utils/VirtualLightRefBase.h
new file mode 100644
index 0000000..b545aab
--- /dev/null
+++ b/libs/hwui/utils/VirtualLightRefBase.h
@@ -0,0 +1,34 @@
+/*
+ * 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 VIRTUALLIGHTREFBASE_H
+#define VIRTUALLIGHTREFBASE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+namespace uirenderer {
+
+// This is a wrapper around LightRefBase that simply enforces a virtual
+// destructor to eliminate the template requirement of LightRefBase
+class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
+public:
+    virtual ~VirtualLightRefBase() {}
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* VIRTUALLIGHTREFBASE_H */
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 2667a72..3f6ccc9 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -402,7 +402,7 @@
 
     uint32_t dirty;
     if (icon.isValid()) {
-        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, SkBitmap::kARGB_8888_Config);
+        icon.bitmap.copyTo(&mLocked.state.icon.bitmap, kNative_8888_SkColorType);
 
         if (!mLocked.state.icon.isValid()
                 || mLocked.state.icon.hotSpotX != icon.hotSpotX
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 75e4843..797efd7 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -65,7 +65,7 @@
 
     inline SpriteIcon copy() const {
         SkBitmap bitmapCopy;
-        bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
+        bitmap.copyTo(&bitmapCopy, kNative_8888_SkColorType);
         return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
     }
 
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 26e9cc5..04c6e97 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -56,7 +56,7 @@
     /** Default audio channel mask */
     public static final int CHANNEL_OUT_DEFAULT = 1;
 
-    // Channel mask definitions below are translated to the native values defined in
+    // Output channel mask definitions below are translated to the native values defined in
     //  in /system/core/include/system/audio.h in the JNI code of AudioTrack
     public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
     public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
@@ -94,17 +94,21 @@
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER);
     public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+    // different from AUDIO_CHANNEL_OUT_7POINT1
     public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
             CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
     /** @hide */
+    // matches AUDIO_CHANNEL_OUT_7POINT1
     public static final int CHANNEL_OUT_7POINT1_SURROUND = (
             CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
             CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
             CHANNEL_OUT_LOW_FREQUENCY);
+    // CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
 
     public static final int CHANNEL_IN_DEFAULT = 1;
+    // These directly match native
     public static final int CHANNEL_IN_LEFT = 0x4;
     public static final int CHANNEL_IN_RIGHT = 0x8;
     public static final int CHANNEL_IN_FRONT = 0x10;
@@ -121,5 +125,8 @@
     public static final int CHANNEL_IN_VOICE_DNLINK = 0x8000;
     public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
     public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
+    /** @hide */
+    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
 
 }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index fe510f6..7f1c5c7 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1689,7 +1689,7 @@
     private static final String ASSET_FILE_VERSION = "1.0";
     private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
 
-    private static final int SOUND_EFECTS_LOAD_TIMEOUT_MS = 5000;
+    private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
 
     class LoadSoundEffectReply {
         public int mStatus = 1;
@@ -1801,7 +1801,7 @@
             sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
             while ((reply.mStatus == 1) && (attempts-- > 0)) {
                 try {
-                    reply.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+                    reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                 } catch (InterruptedException e) {
                     Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
                 }
@@ -3289,7 +3289,7 @@
                 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
                     try {
                         // Wait for mSoundPoolCallBack to be set by the other thread
-                        mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+                        mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                     } catch (InterruptedException e) {
                         Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
                     }
@@ -3353,7 +3353,7 @@
                     status = 1;
                     while ((status == 1) && (attempts-- > 0)) {
                         try {
-                            mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+                            mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
                             status = mSoundPoolCallBack.status();
                         } catch (InterruptedException e) {
                             Log.w(TAG, "Interrupted while waiting sound pool callback.");
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 40c6797..17840f2 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -77,10 +77,14 @@
     //---------------------------------------------------------
     // Constants
     //--------------------
-    /** Minimum value for a channel volume */
-    private static final float VOLUME_MIN = 0.0f;
-    /** Maximum value for a channel volume */
-    private static final float VOLUME_MAX = 1.0f;
+    /** Minimum value for a linear gain or auxiliary effect level.
+     *  This value must be exactly equal to 0.0f; do not change it.
+     */
+    private static final float GAIN_MIN = 0.0f;
+    /** Maximum value for a linear gain or auxiliary effect level.
+     *  This value must be greater than or equal to 1.0f.
+     */
+    private static final float GAIN_MAX = 1.0f;
 
     /** Minimum value for sample rate */
     private static final int SAMPLE_RATE_HZ_MIN = 4000;
@@ -548,21 +552,25 @@
     // Getters
     //--------------------
     /**
-     * Returns the minimum valid volume value. Volume values set under this one will
-     * be clamped at this value.
-     * @return the minimum volume expressed as a linear attenuation.
+     * Returns the minimum gain value, which is the constant 0.0.
+     * Gain values less than 0.0 will be clamped to 0.0.
+     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
+     * @return the minimum value, which is the constant 0.0.
      */
     static public float getMinVolume() {
-        return VOLUME_MIN;
+        return GAIN_MIN;
     }
 
     /**
-     * Returns the maximum valid volume value. Volume values set above this one will
-     * be clamped at this value.
-     * @return the maximum volume expressed as a linear attenuation.
+     * Returns the maximum gain value, which is greater than or equal to 1.0.
+     * Gain values greater than the maximum will be clamped to the maximum.
+     * <p>The word "volume" in the API name is historical; this is actually a gain.
+     * expressed as a linear multiplier on sample values, where a maximum value of 1.0
+     * corresponds to a gain of 0 dB (sample values left unmodified).
+     * @return the maximum value, which is greater than or equal to 1.0.
      */
     static public float getMaxVolume() {
-        return VOLUME_MAX;
+        return GAIN_MAX;
     }
 
     /**
@@ -845,17 +853,35 @@
     }
 
 
+    private static float clampGainOrLevel(float gainOrLevel) {
+        if (Float.isNaN(gainOrLevel)) {
+            throw new IllegalArgumentException();
+        }
+        if (gainOrLevel < GAIN_MIN) {
+            gainOrLevel = GAIN_MIN;
+        } else if (gainOrLevel > GAIN_MAX) {
+            gainOrLevel = GAIN_MAX;
+        }
+        return gainOrLevel;
+    }
+
 
      /**
-     * Sets the specified left/right output volume values on the AudioTrack. Values are clamped
-     * to the ({@link #getMinVolume()}, {@link #getMaxVolume()}) interval if outside this range.
-     * @param leftVolume output attenuation for the left channel. A value of 0.0f is silence,
-     *      a value of 1.0f is no attenuation.
-     * @param rightVolume output attenuation for the right channel
+     * Sets the specified left and right output gain values on the AudioTrack.
+     * <p>Gain values are clamped to the closed interval [0.0, max] where
+     * max is the value of {@link #getMaxVolume}.
+     * A value of 0.0 results in zero gain (silence), and
+     * a value of 1.0 means unity gain (signal unchanged).
+     * The default value is 1.0 meaning unity gain.
+     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
+     * @param leftGain output gain for the left channel.
+     * @param rightGain output gain for the right channel
      * @return error code or success, see {@link #SUCCESS},
      *    {@link #ERROR_INVALID_OPERATION}
+     * @deprecated Applications should use {@link #setVolume} instead, as it
+     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
      */
-    public int setStereoVolume(float leftVolume, float rightVolume) {
+    public int setStereoVolume(float leftGain, float rightGain) {
         if (isRestricted()) {
             return SUCCESS;
         }
@@ -863,36 +889,31 @@
             return ERROR_INVALID_OPERATION;
         }
 
-        // clamp the volumes
-        if (leftVolume < getMinVolume()) {
-            leftVolume = getMinVolume();
-        }
-        if (leftVolume > getMaxVolume()) {
-            leftVolume = getMaxVolume();
-        }
-        if (rightVolume < getMinVolume()) {
-            rightVolume = getMinVolume();
-        }
-        if (rightVolume > getMaxVolume()) {
-            rightVolume = getMaxVolume();
-        }
+        leftGain = clampGainOrLevel(leftGain);
+        rightGain = clampGainOrLevel(rightGain);
 
-        native_setVolume(leftVolume, rightVolume);
+        native_setVolume(leftGain, rightGain);
 
         return SUCCESS;
     }
 
 
     /**
-     * Sets the specified output volume values on all channels of this track.  The value is clamped
-     * to the ({@link #getMinVolume()}, {@link #getMaxVolume()}) interval if outside this range.
-     * @param volume output attenuation for all channels. A value of 0.0f is silence,
-     *      a value of 1.0f is no attenuation.
+     * Sets the specified output gain value on all channels of this track.
+     * <p>Gain values are clamped to the closed interval [0.0, max] where
+     * max is the value of {@link #getMaxVolume}.
+     * A value of 0.0 results in zero gain (silence), and
+     * a value of 1.0 means unity gain (signal unchanged).
+     * The default value is 1.0 meaning unity gain.
+     * <p>This API is preferred over {@link #setStereoVolume}, as it
+     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
+     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
+     * @param gain output gain for all channels.
      * @return error code or success, see {@link #SUCCESS},
      *    {@link #ERROR_INVALID_OPERATION}
      */
-    public int setVolume(float volume) {
-        return setStereoVolume(volume, volume);
+    public int setVolume(float gain) {
+        return setStereoVolume(gain, gain);
     }
 
 
@@ -1309,19 +1330,21 @@
 
     /**
      * Sets the send level of the audio track to the attached auxiliary effect
-     * {@link #attachAuxEffect(int)}.  The level value range is 0.0f to 1.0f.
-     * Values are clamped to the (0.0f, 1.0f) interval if outside this range.
+     * {@link #attachAuxEffect(int)}.  Effect levels
+     * are clamped to the closed interval [0.0, max] where
+     * max is the value of {@link #getMaxVolume}.
+     * A value of 0.0 results in no effect, and a value of 1.0 is full send.
      * <p>By default the send level is 0.0f, so even if an effect is attached to the player
      * this method must be called for the effect to be applied.
-     * <p>Note that the passed level value is a raw scalar. UI controls should be scaled
-     * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
+     * <p>Note that the passed level value is a linear scalar. UI controls should be scaled
+     * logarithmically: the gain applied by audio framework ranges from -72dB to at least 0dB,
      * so an appropriate conversion from linear UI input x to level is:
      * x == 0 -&gt; level = 0
      * 0 &lt; x &lt;= R -&gt; level = 10^(72*(x-R)/20/R)
      *
-     * @param level send level scalar
+     * @param level linear send level
      * @return error code or success, see {@link #SUCCESS},
-     *    {@link #ERROR_INVALID_OPERATION}
+     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR}
      */
     public int setAuxEffectSendLevel(float level) {
         if (isRestricted()) {
@@ -1330,15 +1353,9 @@
         if (mState == STATE_UNINITIALIZED) {
             return ERROR_INVALID_OPERATION;
         }
-        // clamp the level
-        if (level < getMinVolume()) {
-            level = getMinVolume();
-        }
-        if (level > getMaxVolume()) {
-            level = getMaxVolume();
-        }
-        native_setAuxEffectSendLevel(level);
-        return SUCCESS;
+        level = clampGainOrLevel(level);
+        int err = native_setAuxEffectSendLevel(level);
+        return err == 0 ? SUCCESS : ERROR;
     }
 
     //---------------------------------------------------------
@@ -1508,7 +1525,7 @@
             int sampleRateInHz, int channelConfig, int audioFormat);
 
     private native final int native_attachAuxEffect(int effectId);
-    private native final void native_setAuxEffectSendLevel(float level);
+    private native final int native_setAuxEffectSendLevel(float level);
 
     //---------------------------------------------------------
     // Utility methods
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 7170ffb..440653a 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -20,6 +20,8 @@
 import java.util.UUID;
 import java.util.HashMap;
 import java.util.List;
+import android.os.Binder;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -95,12 +97,28 @@
 
     private final static String TAG = "MediaDrm";
 
+    private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
+
     private EventHandler mEventHandler;
     private OnEventListener mOnEventListener;
 
     private long mNativeContext;
 
     /**
+     * Specify no certificate type
+     *
+     * @hide - not part of the public API at this time
+     */
+    public static final int CERTIFICATE_TYPE_NONE = 0;
+
+    /**
+     * Specify X.509 certificate type
+     *
+     * @hide - not part of the public API at this time
+     */
+    public static final int CERTIFICATE_TYPE_X509 = 1;
+
+    /**
      * Query if the given scheme identified by its UUID is supported on
      * this device.
      * @param uuid The UUID of the crypto scheme.
@@ -135,7 +153,7 @@
     }
 
     private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid,
-                                                                      String mimeType);
+            String mimeType);
 
     /**
      * Instantiate a MediaDrm object
@@ -159,7 +177,7 @@
          * It's easier to create it here than in C++.
          */
         native_setup(new WeakReference<MediaDrm>(this),
-                     getByteArrayFromUUID(uuid));
+                getByteArrayFromUUID(uuid));
     }
 
     /**
@@ -268,7 +286,7 @@
      * the cookie passed to native_setup().)
      */
     private static void postEventFromNative(Object mediadrm_ref,
-                                            int eventType, int extra, Object obj)
+            int eventType, int extra, Object obj)
     {
         MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
         if (md == null) {
@@ -316,6 +334,9 @@
      * Contains the opaque data an app uses to request keys from a license server
      */
     public final static class KeyRequest {
+        private byte[] mData;
+        private String mDefaultUrl;
+
         KeyRequest() {}
 
         /**
@@ -329,9 +350,6 @@
          * server URL from other sources.
          */
         public String getDefaultUrl() { return mDefaultUrl; }
-
-        private byte[] mData;
-        private String mDefaultUrl;
     };
 
     /**
@@ -368,9 +386,8 @@
      * problem with the certifcate
      */
     public native KeyRequest getKeyRequest(byte[] scope, byte[] init,
-                                           String mimeType, int keyType,
-                                           HashMap<String, String> optionalParameters)
-        throws NotProvisionedException;
+            String mimeType, int keyType, HashMap<String, String> optionalParameters)
+            throws NotProvisionedException;
 
 
     /**
@@ -394,7 +411,7 @@
      * @throws ResourceBusyException if required resources are in use
      */
     public native byte[] provideKeyResponse(byte[] scope, byte[] response)
-        throws NotProvisionedException, DeniedByServerException;
+            throws NotProvisionedException, DeniedByServerException;
 
 
     /**
@@ -456,7 +473,12 @@
      * is returned in ProvisionRequest.data. The recommended URL to deliver the provision
      * request to is returned in ProvisionRequest.defaultUrl.
      */
-    public native ProvisionRequest getProvisionRequest();
+    public ProvisionRequest getProvisionRequest() {
+        return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
+    }
+
+    private native ProvisionRequest getProvisionRequestNative(int certType,
+            String certAuthority);
 
     /**
      * After a provision response is received by the app, it is provided to the DRM
@@ -468,8 +490,13 @@
      * @throws DeniedByServerException if the response indicates that the
      * server rejected the request
      */
-    public native void provideProvisionResponse(byte[] response)
-        throws DeniedByServerException;
+    public void provideProvisionResponse(byte[] response)
+            throws DeniedByServerException {
+        provideProvisionResponseNative(response);
+    }
+
+    private native Certificate provideProvisionResponseNative(byte[] response)
+            throws DeniedByServerException;
 
     /**
      * A means of enforcing limits on the number of concurrent streams per subscriber
@@ -556,23 +583,22 @@
 
 
     private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId,
-                                                              String algorithm);
+            String algorithm);
 
     private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId,
-                                                           String algorithm);
+            String algorithm);
 
     private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] input, byte[] iv);
+            byte[] keyId, byte[] input, byte[] iv);
 
     private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] input, byte[] iv);
+            byte[] keyId, byte[] input, byte[] iv);
 
     private static final native byte[] signNative(MediaDrm drm, byte[] sessionId,
-                                                  byte[] keyId, byte[] message);
+            byte[] keyId, byte[] message);
 
     private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId,
-                                                     byte[] keyId, byte[] message,
-                                                     byte[] signature);
+            byte[] keyId, byte[] message, byte[] signature);
 
     /**
      * In addition to supporting decryption of DASH Common Encrypted Media, the
@@ -602,7 +628,7 @@
         private byte[] mSessionId;
 
         CryptoSession(MediaDrm drm, byte[] sessionId,
-                      String cipherAlgorithm, String macAlgorithm)
+                String cipherAlgorithm, String macAlgorithm)
         {
             mSessionId = sessionId;
             mDrm = drm;
@@ -677,12 +703,124 @@
      * "algorithms".
      */
     public CryptoSession getCryptoSession(byte[] sessionId,
-                                          String cipherAlgorithm,
-                                          String macAlgorithm)
+            String cipherAlgorithm, String macAlgorithm)
     {
         return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
     }
 
+    /**
+     * Contains the opaque data an app uses to request a certificate from a provisioning
+     * server
+     *
+     * @hide - not part of the public API at this time
+     */
+    public final static class CertificateRequest {
+        private byte[] mData;
+        private String mDefaultUrl;
+
+        CertificateRequest(byte[] data, String defaultUrl) {
+            mData = data;
+            mDefaultUrl = defaultUrl;
+        }
+
+        /**
+         * Get the opaque message data
+         */
+        public byte[] getData() { return mData; }
+
+        /**
+         * Get the default URL to use when sending the certificate request
+         * message to a server, if known. The app may prefer to use a different
+         * certificate server URL obtained from other sources.
+         */
+        public String getDefaultUrl() { return mDefaultUrl; }
+    }
+
+    /**
+     * Generate a certificate request, specifying the certificate type
+     * and authority. The response received should be passed to
+     * provideCertificateResponse.
+     *
+     * @param certType Specifies the certificate type.
+     *
+     * @param certAuthority is passed to the certificate server to specify
+     * the chain of authority.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public CertificateRequest getCertificateRequest(int certType,
+            String certAuthority)
+    {
+        ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
+        return new CertificateRequest(provisionRequest.getData(),
+                provisionRequest.getDefaultUrl());
+    }
+
+    /**
+     * Contains the wrapped private key and public certificate data associated
+     * with a certificate.
+     *
+     * @hide - not part of the public API at this time
+     */
+    public final static class Certificate {
+        Certificate() {}
+
+        /**
+         * Get the wrapped private key data
+         */
+        public byte[] getWrappedPrivateKey() { return mWrappedKey; }
+
+        /**
+         * Get the PEM-encoded certificate chain
+         */
+        public byte[] getContent() { return mCertificateData; }
+
+        private byte[] mWrappedKey;
+        private byte[] mCertificateData;
+    }
+
+
+    /**
+     * Process a response from the certificate server.  The response
+     * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+     * <p>
+     * The public X509 certificate chain and wrapped private key are returned
+     * in the returned Certificate objec.  The certificate chain is in PEM format.
+     * The wrapped private key should be stored in application private
+     * storage, and used when invoking the signRSA method.
+     *
+     * @param response the opaque certificate response byte array to provide to the
+     * DRM engine plugin.
+     *
+     * @throws DeniedByServerException if the response indicates that the
+     * server rejected the request
+     *
+     * @hide - not part of the public API at this time
+     */
+    public Certificate provideCertificateResponse(byte[] response)
+            throws DeniedByServerException {
+        return provideProvisionResponseNative(response);
+    }
+
+    private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
+            String algorithm, byte[] wrappedKey, byte[] message);
+
+    /**
+     * Sign data using an RSA key
+     *
+     * @param sessionId a sessionId obtained from openSession on the MediaDrm object
+     * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
+     * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
+     * from provideCertificateResponse
+     * @param message the data for which a signature is to be computed
+     *
+     * @hide - not part of the public API at this time
+     */
+    public byte[] signRSA(byte[] sessionId, String algorithm,
+            byte[] wrappedKey, byte[] message) {
+        return signRSANative(this, sessionId, algorithm, wrappedKey, message);
+    }
+
     @Override
     protected void finalize() {
         native_finalize();
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 15ae238..fce3fd0 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -202,12 +202,17 @@
     public void setServer(MtpServer server) {
         mServer = server;
 
+        // always unregister before registering
+        try {
+            mContext.unregisterReceiver(mBatteryReceiver);
+        } catch (IllegalArgumentException e) {
+            // wasn't previously registered, ignore
+        }
+
         // register for battery notifications when we are connected
         if (server != null) {
             mContext.registerReceiver(mBatteryReceiver,
                     new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        } else {
-            mContext.unregisterReceiver(mBatteryReceiver);
         }
     }
 
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index fcd425e..716418c 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -386,11 +386,12 @@
             dataSize = buffer->stride * buffer->height;
             break;
         case HAL_PIXEL_FORMAT_Y16:
+            bytesPerPixel = 2;
             // Single plane, 16bpp, strides are specified in pixels, not in bytes
             ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
 
             pData = buffer->data;
-            dataSize = buffer->stride * buffer->height * 2;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_BLOB:
             // Used for JPEG data, height must be 1, width == size, single plane.
@@ -402,9 +403,10 @@
             break;
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
             // Single plane 16bpp bayer data.
+            bytesPerPixel = 2;
             ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
             pData = buffer->data;
-            dataSize = buffer->width * 2 * buffer->height;
+            dataSize = buffer->stride * buffer->height * bytesPerPixel;
             break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index b2fb2df..d04b1f8 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -27,6 +27,8 @@
 #include "jni.h"
 #include "JNIHelp.h"
 
+#include <cutils/compiler.h>
+
 #include <gui/Surface.h>
 
 #include <media/ICrypto.h>
@@ -738,6 +740,10 @@
     } else if (numBytesOfClearDataObj != NULL
             && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
         err = -ERANGE;
+    // subSamples array may silently overflow if number of samples are too large.  Use
+    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
+    } else if ( CC_UNLIKELY(numSubSamples >= INT32_MAX / sizeof(*subSamples)) ) {
+        err = -EINVAL;
     } else {
         jboolean isCopy;
 
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 052d97d..7c45682 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -100,6 +100,16 @@
     jint kKeyTypeRelease;
 } gKeyTypes;
 
+struct CertificateTypes {
+    jint kCertificateTypeNone;
+    jint kCertificateTypeX509;
+} gCertificateTypes;
+
+struct CertificateFields {
+    jfieldID wrappedPrivateKey;
+    jfieldID certificateData;
+};
+
 struct fields_t {
     jfieldID context;
     jmethodID post_event;
@@ -110,6 +120,11 @@
     SetFields set;
     IteratorFields iterator;
     EntryFields entry;
+    CertificateFields certificate;
+    jclass certificateClassId;
+    jclass hashmapClassId;
+    jclass arraylistClassId;
+    jclass stringClassId;
 };
 
 static fields_t gFields;
@@ -406,8 +421,7 @@
 */
 
 static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/lang/String");
+    jclass clazz = gFields.stringClassId;
     KeyedVector<String8, String8> keyedVector;
 
     jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
@@ -450,8 +464,7 @@
 }
 
 static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/util/HashMap");
+    jclass clazz = gFields.hashmapClassId;
     jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
     for (size_t i = 0; i < map.size(); ++i) {
         jstring jkey = env->NewStringUTF(map.keyAt(i).string());
@@ -465,8 +478,7 @@
 
 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
                                                    List<Vector<uint8_t> > list) {
-    jclass clazz;
-    FIND_CLASS(clazz, "java/util/ArrayList");
+    jclass clazz = gFields.arraylistClassId;
     jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
     List<Vector<uint8_t> >::iterator iter = list.begin();
     while (iter != list.end()) {
@@ -542,6 +554,11 @@
     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
     gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
 
+    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
+    gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
+    gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
+
     FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
     GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
     GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
@@ -550,6 +567,11 @@
     GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
     GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
 
+    FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
+    GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
+    GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
+    gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
     FIND_CLASS(clazz, "java/util/ArrayList");
     GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
     GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
@@ -571,6 +593,15 @@
     FIND_CLASS(clazz, "java/util/Map$Entry");
     GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
     GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
+
+    FIND_CLASS(clazz, "java/util/HashMap");
+    gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "java/lang/String");
+    gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "java/util/ArrayList");
+    gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
 }
 
 static void android_media_MediaDrm_native_setup(
@@ -826,8 +857,8 @@
     return KeyedVectorToHashMap(env, infoMap);
 }
 
-static jobject android_media_MediaDrm_getProvisionRequest(
-    JNIEnv *env, jobject thiz) {
+static jobject android_media_MediaDrm_getProvisionRequestNative(
+    JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
     if (drm == NULL) {
@@ -839,7 +870,17 @@
     Vector<uint8_t> request;
     String8 defaultUrl;
 
-    status_t err = drm->getProvisionRequest(request, defaultUrl);
+    String8 certType;
+    if (jcertType == gCertificateTypes.kCertificateTypeX509) {
+        certType = "X.509";
+    } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
+        certType = "none";
+    } else {
+        certType = "invalid";
+    }
+
+    String8 certAuthority = JStringToString8(env, jcertAuthority);
+    status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
 
     if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
         return NULL;
@@ -863,27 +904,43 @@
     return provisionObj;
 }
 
-static void android_media_MediaDrm_provideProvisionResponse(
+static jobject android_media_MediaDrm_provideProvisionResponseNative(
     JNIEnv *env, jobject thiz, jbyteArray jresponse) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
     if (drm == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
                           "MediaDrm obj is null");
-        return;
+        return NULL;
     }
 
     if (jresponse == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException",
                           "provision response is null");
-        return;
+        return NULL;
     }
 
     Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
+    Vector<uint8_t> certificate, wrappedKey;
 
-    status_t err = drm->provideProvisionResponse(response);
+    status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
+
+    // Fill out return obj
+    jclass clazz = gFields.certificateClassId;
+
+    jobject certificateObj = NULL;
+
+    if (clazz && certificate.size() && wrappedKey.size()) {
+        certificateObj = env->AllocObject(clazz);
+        jbyteArray jcertificate = VectorToJByteArray(env, certificate);
+        env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
+
+        jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
+        env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
+    }
 
     throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+    return certificateObj;
 }
 
 static jobject android_media_MediaDrm_getSecureStops(
@@ -1209,6 +1266,38 @@
 }
 
 
+static jbyteArray android_media_MediaDrm_signRSANative(
+    JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
+    jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
+
+    sp<IDrm> drm = GetDrm(env, jdrm);
+
+    if (!CheckSession(env, drm, jsessionId)) {
+        return NULL;
+    }
+
+    if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "required argument is null");
+        return NULL;
+    }
+
+    Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
+    String8 algorithm = JStringToString8(env, jalgorithm);
+    Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
+    Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
+    Vector<uint8_t> signature;
+
+    status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+        return NULL;
+    }
+
+    return VectorToJByteArray(env, signature);
+}
+
+
 static JNINativeMethod gMethods[] = {
     { "release", "()V", (void *)android_media_MediaDrm_release },
     { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
@@ -1244,11 +1333,11 @@
     { "queryKeyStatus", "([B)Ljava/util/HashMap;",
       (void *)android_media_MediaDrm_queryKeyStatus },
 
-    { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
-      (void *)android_media_MediaDrm_getProvisionRequest },
+    { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
+      (void *)android_media_MediaDrm_getProvisionRequestNative },
 
-    { "provideProvisionResponse", "([B)V",
-      (void *)android_media_MediaDrm_provideProvisionResponse },
+    { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
+      (void *)android_media_MediaDrm_provideProvisionResponseNative },
 
     { "getSecureStops", "()Ljava/util/List;",
       (void *)android_media_MediaDrm_getSecureStops },
@@ -1287,6 +1376,9 @@
 
     { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
       (void *)android_media_MediaDrm_verifyNative },
+
+    { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
+      (void *)android_media_MediaDrm_signRSANative },
 };
 
 int register_android_media_Drm(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index a78f16d..3dbf77b 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -87,7 +87,7 @@
         jbyteArray byteArrayObj = env->NewByteArray(size);
         env->DeleteLocalRef(env->GetObjectClass(mDataSource));
         env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
-        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, (jint)size);
         env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
         env->DeleteLocalRef(byteArrayObj);
         if (env->ExceptionCheck()) {
@@ -632,7 +632,7 @@
     env->CallVoidMethod(
             cryptoInfoObj,
             gFields.cryptoInfoSetID,
-            numSubSamples,
+            (jint)numSubSamples,
             numBytesOfPlainDataObj,
             numBytesOfEncryptedDataObj,
             keyObj,
diff --git a/media/lib/Android.mk b/media/lib/remotedisplay/Android.mk
similarity index 93%
rename from media/lib/Android.mk
rename to media/lib/remotedisplay/Android.mk
index 50799a6..ea1ac2b 100644
--- a/media/lib/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -15,7 +15,7 @@
 #
 LOCAL_PATH := $(call my-dir)
 
-# the library
+# the remotedisplay library
 # ============================================================
 include $(CLEAR_VARS)
 
@@ -23,7 +23,7 @@
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files) \
+            $(call all-java-files-under, java) \
             $(call all-aidl-files-under, java)
 
 include $(BUILD_JAVA_LIBRARY)
diff --git a/media/lib/README.txt b/media/lib/remotedisplay/README.txt
similarity index 99%
rename from media/lib/README.txt
rename to media/lib/remotedisplay/README.txt
index cade3df..5738dbe 100644
--- a/media/lib/README.txt
+++ b/media/lib/remotedisplay/README.txt
@@ -25,4 +25,3 @@
 library is a compromise to make new capabilities available to the system
 without exposing the full surface area of the support library media
 route provider protocol.
-
diff --git a/media/lib/com.android.media.remotedisplay.xml b/media/lib/remotedisplay/com.android.media.remotedisplay.xml
similarity index 100%
rename from media/lib/com.android.media.remotedisplay.xml
rename to media/lib/remotedisplay/com.android.media.remotedisplay.xml
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
diff --git a/media/lib/Android.mk b/media/lib/signer/Android.mk
similarity index 76%
copy from media/lib/Android.mk
copy to media/lib/signer/Android.mk
index 50799a6..4c3772f 100644
--- a/media/lib/Android.mk
+++ b/media/lib/signer/Android.mk
@@ -15,24 +15,23 @@
 #
 LOCAL_PATH := $(call my-dir)
 
-# the library
+# the mediadrm signer library
 # ============================================================
 include $(CLEAR_VARS)
 
-LOCAL_MODULE:= com.android.media.remotedisplay
+LOCAL_MODULE:= com.android.mediadrm.signer
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := \
-            $(call all-subdir-java-files) \
-            $(call all-aidl-files-under, java)
+            $(call all-java-files-under, java)
 
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
-# ====  com.android.media.remotedisplay.xml lib def  ========================
+# ====  com.android.mediadrm.signer.xml lib def  ========================
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := com.android.media.remotedisplay.xml
+LOCAL_MODULE := com.android.mediadrm.signer.xml
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_MODULE_CLASS := ETC
diff --git a/media/lib/signer/README.txt b/media/lib/signer/README.txt
new file mode 100644
index 0000000..362ab8e
--- /dev/null
+++ b/media/lib/signer/README.txt
@@ -0,0 +1,28 @@
+This library (com.android.mediadrm.signer.jar) is a shared java library
+containing classes required by unbundled apps running on devices that use
+the certficate provisioning and private key signing capabilities provided
+by the MediaDrm API.
+
+--- Rules of this library ---
+o This library is effectively a PUBLIC API for unbundled CAST receivers
+  that may be distributed outside the system image. So it MUST BE API STABLE.
+  You can add but not remove. The rules are the same as for the
+  public platform SDK API.
+o This library can see and instantiate internal platform classes, but it must not
+  expose them in any public method (or by extending them via inheritance). This would
+  break clients of the library because they cannot see the internal platform classes.
+
+This library is distributed in the system image, and loaded as
+a shared library. So you can change the implementation, but not
+the interface. In this way it is like framework.jar.
+
+--- Why does this library exist? ---
+
+Unbundled apps cannot use internal platform classes.
+
+This library will eventually be replaced when the provisioned certificate-
+based signing infrastructure that is currently defined in the support library
+is reintegrated with the framework in a new API.  That API isn't ready yet so
+this library is a compromise to make new capabilities available to the system
+without exposing the full surface area of the support library.
+
diff --git a/core/res/res/drawable/ab_transparent_quantum.xml b/media/lib/signer/com.android.mediadrm.signer.xml
similarity index 72%
copy from core/res/res/drawable/ab_transparent_quantum.xml
copy to media/lib/signer/com.android.mediadrm.signer.xml
index 495bfb6..b5b1f09 100644
--- a/core/res/res/drawable/ab_transparent_quantum.xml
+++ b/media/lib/signer/com.android.mediadrm.signer.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ab_transparent_qntm_alpha"
-    android:tint="?attr/colorControlNormal" />
+<permissions>
+    <library name="com.android.media.drm.signer"
+            file="/system/framework/com.android.media.drm.signer.jar" />
+</permissions>
diff --git a/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
new file mode 100644
index 0000000..0a2897f
--- /dev/null
+++ b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediadrm.signer;
+
+import android.media.MediaDrm;
+import android.media.DeniedByServerException;
+
+/**
+ * Provides certificate request generation, response handling and
+ * signing APIs
+ */
+public final class MediaDrmSigner {
+    private MediaDrmSigner() {}
+
+    /**
+     * Specify X.509 certificate type
+     */
+    public static final int CERTIFICATE_TYPE_X509 = MediaDrm.CERTIFICATE_TYPE_X509;
+
+    /**
+     * Contains the opaque data an app uses to request a certificate from a provisioning
+     * server
+     */
+    public final static class CertificateRequest {
+        private final MediaDrm.CertificateRequest mCertRequest;
+
+        CertificateRequest(MediaDrm.CertificateRequest certRequest) {
+            mCertRequest = certRequest;
+        }
+
+        /**
+         * Get the opaque message data
+         */
+        public byte[] getData() {
+            return mCertRequest.getData();
+        }
+
+        /**
+         * Get the default URL to use when sending the certificate request
+         * message to a server, if known. The app may prefer to use a different
+         * certificate server URL obtained from other sources.
+         */
+        public String getDefaultUrl() {
+            return mCertRequest.getDefaultUrl();
+        }
+    }
+
+    /**
+     * Contains the wrapped private key and public certificate data associated
+     * with a certificate.
+     */
+    public final static class Certificate {
+        private final MediaDrm.Certificate mCertificate;
+
+        Certificate(MediaDrm.Certificate certificate) {
+            mCertificate = certificate;
+        }
+
+        /**
+         * Get the wrapped private key data
+         */
+        public byte[] getWrappedPrivateKey() {
+            return mCertificate.getWrappedPrivateKey();
+        }
+
+        /**
+         * Get the PEM-encoded public certificate chain
+         */
+        public byte[] getContent() {
+            return mCertificate.getContent();
+        }
+    }
+
+    /**
+     * Generate a certificate request, specifying the certificate type
+     * and authority. The response received should be passed to
+     * provideCertificateResponse.
+     *
+     * @param drm the MediaDrm object
+     * @param certType Specifies the certificate type.
+     * @param certAuthority is passed to the certificate server to specify
+     * the chain of authority.
+     */
+    public static CertificateRequest getCertificateRequest(MediaDrm drm, int certType,
+            String certAuthority) {
+        return new CertificateRequest(drm.getCertificateRequest(certType, certAuthority));
+    }
+
+    /**
+     * Process a response from the provisioning server.  The response
+     * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+     *
+     * The public X509 certificate chain and wrapped private key are returned
+     * in the returned Certificate objec.  The certificate chain is in BIO serialized
+     * PEM format.  The wrapped private key should be stored in application private
+     * storage, and used when invoking the signRSA method.
+     *
+     * @param drm the MediaDrm object
+     * @param response the opaque certificate response byte array to provide to the
+     * DRM engine plugin.
+     * @throws android.media.DeniedByServerException if the response indicates that the
+     * server rejected the request
+     */
+    public static Certificate provideCertificateResponse(MediaDrm drm, byte[] response)
+            throws DeniedByServerException {
+        return new Certificate(drm.provideCertificateResponse(response));
+    }
+
+    /**
+     * Sign data using an RSA key
+     *
+     * @param drm the MediaDrm object
+     * @param sessionId a sessionId obtained from openSession on the MediaDrm object
+     * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
+     * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
+     * from provideCertificateResponse
+     * @param message the data for which a signature is to be computed
+     */
+    public static byte[] signRSA(MediaDrm drm, byte[] sessionId,
+            String algorithm, byte[] wrappedKey, byte[] message) {
+        return drm.signRSA(sessionId, algorithm, wrappedKey, message);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 43ebef4..5f3ba74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -140,7 +140,9 @@
 
     private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
         int requestId = mCameraUser.submitRequest(request, streaming);
-        assertTrue("Request IDs should be non-negative", requestId >= 0);
+        assertTrue(
+                "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
+                requestId >= 0);
         return requestId;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index 3f17aa9..26498ca 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -309,7 +309,7 @@
                 });
 
         // rational (n) -- in particular rational x 9
-        checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class,
+        checkKeyGetAndSetArray("android.sensor.calibrationTransform", Rational[].class,
                 new Rational[] {
                         new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
                         new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index 95ae33b..b0bc5d4 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -19,7 +19,6 @@
 LOCAL_SRC_FILES := \
         omx_jpeg_decoder.cpp \
         jpeg_decoder_bench.cpp \
-        SkOmxPixelRef.cpp \
         StreamSource.cpp
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp b/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
deleted file mode 100644
index a25e854..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 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 <media/stagefright/foundation/ADebug.h>
-#include <SkBitmap.h>
-
-#include "SkOmxPixelRef.h"
-
-using namespace android;
-
-SkOmxPixelRef::SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
-        sp<MediaSource> decoder)  {
-    mBuffer = buffer;
-    mDecoder = decoder;
-    mSize = buffer->size();
-    mCTable = ctable;
-    SkSafeRef(mCTable);
-}
-
-SkOmxPixelRef::~SkOmxPixelRef() {
-    mBuffer->release();
-    CHECK_EQ(mDecoder->stop(), (status_t)OK);
-    SkSafeUnref(mCTable);
-}
-
-void* SkOmxPixelRef::onLockPixels(SkColorTable** ct) {
-    *ct = mCTable;
-    return mBuffer->data();
-}
-
-void SkOmxPixelRef::onUnlockPixels() {
-    // nothing to do
-}
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.h b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
deleted file mode 100644
index 374604c..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 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 SKOMXPIXELREF_DEFINED
-#define SKOMXPIXELREF_DEFINED
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <SkPixelRef.h>
-
-namespace android {
-
-class SkOmxPixelRef : public SkPixelRef {
-public:
-    SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
-            sp<MediaSource> decoder);
-    virtual ~SkOmxPixelRef();
-
-     //! Return the allocation size for the pixels
-    size_t getSize() const { return mSize; }
-
-    SK_DECLARE_UNFLATTENABLE_OBJECT()
-protected:
-    // overrides from SkPixelRef
-    virtual void* onLockPixels(SkColorTable**);
-    virtual void onUnlockPixels();
-
-private:
-    MediaBuffer* mBuffer;
-    sp<MediaSource> mDecoder;
-    size_t          mSize;
-    SkColorTable*   mCTable;
-
-    typedef SkPixelRef INHERITED;
-};
-
-} // namespace android
-#endif // SKOMXPIXELREF_DEFINED
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 53f04bc..3dd988e 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -34,7 +34,6 @@
 #include <SkMallocPixelRef.h>
 
 #include "omx_jpeg_decoder.h"
-#include "SkOmxPixelRef.h"
 #include "StreamSource.h"
 
 using namespace android;
@@ -158,10 +157,6 @@
     printf("Duration in decoder->read(): %.1f (msecs). \n",
                 duration / 1E3 );
 
-    /* Mark the code for now, since we attend to copy buffer to SkBitmap.
-    // Install pixelRef to Bitmap.
-    installPixelRef(buffer, decoder, bm);*/
-
     // Copy pixels from buffer to bm.
     // May need to check buffer->rawBytes() == bm->rawBytes().
     CHECK_EQ(buffer->size(), bm->getSize());
@@ -172,17 +167,6 @@
     return true;
 }
 
-void OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> decoder,
-        SkBitmap* bm) {
-
-    // set bm's pixelref based on the data in buffer.
-    SkAutoLockPixels alp(*bm);
-    SkPixelRef* pr = new SkOmxPixelRef(NULL, buffer, decoder);
-    bm->setPixelRef(pr)->unref();
-    bm->lockPixels();
-    return;
-}
-
 void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
         int width, int height) {
     bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
index a313877..e431e72 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
@@ -49,8 +49,6 @@
     sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source);
     bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source,
             SkBitmap* bm);
-    void installPixelRef(MediaBuffer* buffer, sp<MediaSource> decoder,
-            SkBitmap* bm);
     void configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, int width,
             int height);
     SkBitmap::Config getColorSpaceConfig(SkBitmap::Config pref);
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml
index 4fb26ae..8141fa7 100644
--- a/packages/BackupRestoreConfirmation/AndroidManifest.xml
+++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml
@@ -1,20 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 -->
-
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.backupconfirm" >
 
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 179bcd1..6b77a7c 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -42,7 +42,7 @@
         <activity
             android:name=".SettingsActivity"
             android:label="@string/menu_settings"
-            android:theme="@android:style/Theme.Holo.Light.DialogWhenLarge"
+            android:theme="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge"
             android:exported="false" />
 
         <provider
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
index 19d2ebe..8d31444 100644
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/styles.xml
@@ -15,11 +15,11 @@
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <style name="Theme" parent="@android:style/Theme.Holo.Light">
+    <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
         <item name="android:windowBackground">@*android:drawable/dialog_full_holo_light</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowAnimationStyle">@*android:style/Animation.Holo.Dialog</item>
+        <item name="android:windowAnimationStyle">@*android:style/Animation.DeviceDefault.Dialog</item>
     </style>
 </resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 0c8f712..a416eb4 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -29,11 +29,11 @@
 
     <!-- Normally just a redirection, but this is used to make ourselves a
          dialog on large tablets -->
-    <style name="Theme" parent="@android:style/Theme.Holo.Light">
+    <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
     </style>
     
-    <style name="DarkerOverflow" parent="@android:style/Widget.Holo.Light.ActionButton.Overflow">
+    <style name="DarkerOverflow" parent="@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow">
         <item name="android:src">@drawable/ic_menu_overflow</item>
     </style>
 
diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
new file mode 100644
index 0000000..2a95cfe
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
@@ -0,0 +1,319 @@
+# 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.
+
+#
+# Arabic (US-101 keys) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base, capslock:                     '\u0630'
+    shift:                              '\u0651'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '\u0661'
+    shift:                              '!'
+    capslock:                           '1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u0662'
+    shift:                              '@'
+    capslock:                           '2'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0663'
+    shift:                              '#'
+    capslock:                           '3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u0664'
+    shift:                              '$'
+    capslock:                           '4'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u0665'
+    shift:                              '%'
+    capslock:                           '5'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u0666'
+    shift:                              '^'
+    capslock:                           '6'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u0667'
+    shift:                              '&'
+    capslock:                           '7'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u0668'
+    shift:                              '*'
+    capslock:                           '8'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '\u0669'
+    shift:                              '('
+    capslock:                           '9'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '\u0660'
+    shift:                              ')'
+    capslock:                           '0'
+}
+
+key MINUS {
+    label:                              '-'
+    base, capslock:                     '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base, capslock:                     '='
+    shift:                              '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base, capslock:                     '\u0636'
+    shift:                              '\u064e'
+}
+
+key W {
+    label:                              'W'
+    base, capslock:                     '\u0635'
+    shift:                              '\u064b'
+}
+
+key E {
+    label:                              'E'
+    base, capslock:                     '\u062b'
+    shift:                              '\u064f'
+}
+
+key R {
+    label:                              'R'
+    base, capslock:                     '\u0642'
+    shift:                              '\u064c'
+}
+
+key T {
+    label:                              'T'
+    base, capslock:                     '\u0641'
+    shift:                              '\ufef9'
+}
+
+key Y {
+    label:                              'Y'
+    base, capslock:                     '\u063a'
+    shift:                              '\u0625'
+}
+
+key U {
+    label:                              'U'
+    base, capslock:                     '\u0639'
+    shift:                              '\u2018'
+}
+
+key I {
+    label:                              'I'
+    base, capslock:                     '\u0647'
+    shift:                              '\u00f7'
+}
+
+key O {
+    label:                              'O'
+    base, capslock:                     '\u062e'
+    shift:                              '\u00d7'
+}
+
+key P {
+    label:                              'P'
+    base, capslock:                     '\u062d'
+    shift:                              '\u061b'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '\u062c'
+    shift:                              '<'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     '\u062f'
+    shift:                              '>'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base, capslock:                     '\u0634'
+    shift:                              '\u0650'
+}
+
+key S {
+    label:                              'S'
+    base, capslock:                     '\u0633'
+    shift:                              '\u064d'
+}
+
+key D {
+    label:                              'D'
+    base, capslock:                     '\u064a'
+    shift:                              ']'
+}
+
+key F {
+    label:                              'F'
+    base, capslock:                     '\u0628'
+    shift:                              '['
+}
+
+key G {
+    label:                              'G'
+    base, capslock:                     '\u0644'
+    shift:                              '\ufef7'
+}
+
+key H {
+    label:                              'H'
+    base, capslock:                     '\u0627'
+    shift:                              '\u0623'
+}
+
+key J {
+    label:                              'J'
+    base, capslock:                     '\u062a'
+    shift:                              '\u0640'
+}
+
+key K {
+    label:                              'K'
+    base, capslock:                     '\u0646'
+    shift:                              '\u060c'
+}
+
+key L {
+    label:                              'L'
+    base, capslock:                     '\u0645'
+    shift:                              '/'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base, capslock:                     '\u0643'
+    shift:                              ':'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base, capslock:                     '\u0637'
+    shift:                              '"'
+}
+
+### ROW 4
+
+key Z {
+    label:                              'Z'
+    base, capslock:                     '\u0626'
+    shift:                              '~'
+}
+
+key X {
+    label:                              'X'
+    base, capslock:                     '\u0621'
+    shift:                              '\u0652'
+}
+
+key C {
+    label:                              'C'
+    base, capslock:                     '\u0624'
+    shift:                              '}'
+}
+
+key V {
+    label:                              'V'
+    base, capslock:                     '\u0631'
+    shift:                              '{'
+}
+
+key B {
+    label:                              'B'
+    base, capslock:                     '\ufefb'
+    shift:                              '\ufef5'
+}
+
+key N {
+    label:                              'N'
+    base, capslock:                     '\u0649'
+    shift:                              '\u0622'
+}
+
+key M {
+    label:                              'M'
+    base, capslock:                     '\u0629'
+    shift:                              '\u2019'
+}
+
+key COMMA {
+    label:                              ','
+    base, capslock:                     '\u0648'
+    shift:                              ','
+}
+
+key PERIOD {
+    label:                              '.'
+    base, capslock:                     '\u0632'
+    shift:                              '.'
+}
+
+key SLASH {
+    label:                              '/'
+    base, capslock:                     '\u0638'
+    shift:                              '\u061f'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_greek.kcm b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
new file mode 100644
index 0000000..a7684e1
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
@@ -0,0 +1,338 @@
+# 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.
+
+#
+# Greek (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base, capslock:                     '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base, capslock:                     '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base, capslock:                     '2'
+    shift:                              '@'
+    ralt:                               '\u00b2'
+}
+
+key 3 {
+    label:                              '3'
+    base, capslock:                     '3'
+    shift:                              '#'
+    ralt:                               '\u00b3'
+}
+
+key 4 {
+    label:                              '4'
+    base, capslock:                     '4'
+    shift:                              '$'
+    ralt:                               '\u00a3'
+}
+
+key 5 {
+    label:                              '5'
+    base, capslock:                     '5'
+    shift:                              '%'
+    ralt:                               '\u00a7'
+}
+
+key 6 {
+    label:                              '6'
+    base, capslock:                     '6'
+    shift:                              '^'
+    ralt:                               '\u00b6'
+}
+
+key 7 {
+    label:                              '7'
+    base, capslock:                     '7'
+    shift:                              '&'
+}
+
+key 8 {
+    label:                              '8'
+    base, capslock:                     '8'
+    shift:                              '*'
+    ralt:                               '\u00a4'
+}
+
+key 9 {
+    label:                              '9'
+    base, capslock:                     '9'
+    shift:                              '('
+    ralt:                               '\u00a6'
+}
+
+key 0 {
+    label:                              '0'
+    base, capslock:                     '0'
+    shift:                              ')'
+    ralt:                               '\u00b0'
+}
+
+key MINUS {
+    label:                              '-'
+    base, capslock:                     '-'
+    shift:                              '_'
+    ralt:                               '\u00b1'
+}
+
+key EQUALS {
+    label:                              '='
+    base, capslock:                     '='
+    shift:                              '+'
+    ralt:                               '\u00bd'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base, capslock:                     ';'
+    shift:                              ':'
+}
+
+key W {
+    label:                              'W'
+    base, capslock:                     '\u03c2'
+    shift:                              '\u0385'
+}
+
+key E {
+    label:                              'E'
+    base:                               '\u03b5'
+    shift, capslock:                    '\u0395'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               '\u03c1'
+    shift, capslock:                    '\u03a1'
+    ralt:                               '\u00ae'
+}
+
+key T {
+    label:                              'T'
+    base:                               '\u03c4'
+    shift, capslock:                    '\u03a4'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               '\u03c5'
+    shift, capslock:                    '\u03a5'
+    ralt:                               '\u00a5'
+}
+
+key U {
+    label:                              'U'
+    base:                               '\u03b8'
+    shift, capslock:                    '\u0398'
+}
+
+key I {
+    label:                              'I'
+    base:                               '\u03b9'
+    shift, capslock:                    '\u0399'
+}
+
+key O {
+    label:                              'O'
+    base:                               '\u03bf'
+    shift, capslock:                    '\u039f'
+}
+
+key P {
+    label:                              'P'
+    base:                               '\u03c0'
+    shift, capslock:                    '\u03a0'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '['
+    shift:                              '{'
+    ralt:                               '\u00ab'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     ']'
+    shift:                              '}'
+    ralt:                               '\u00bb'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               '\u03b1'
+    shift, capslock:                    '\u0391'
+}
+
+key S {
+    label:                              'S'
+    base:                               '\u03c3'
+    shift, capslock:                    '\u03a3'
+}
+
+key D {
+    label:                              'D'
+    base:                               '\u03b4'
+    shift, capslock:                    '\u0394'
+}
+
+key F {
+    label:                              'F'
+    base:                               '\u03c6'
+    shift, capslock:                    '\u03a6'
+}
+
+key G {
+    label:                              'G'
+    base:                               '\u03b3'
+    shift, capslock:                    '\u0393'
+}
+
+key H {
+    label:                              'H'
+    base:                               '\u03b7'
+    shift, capslock:                    '\u0397'
+}
+
+key J {
+    label:                              'J'
+    base:                               '\u03be'
+    shift, capslock:                    '\u039e'
+}
+
+key K {
+    label:                              'K'
+    base:                               '\u03ba'
+    shift, capslock:                    '\u039a'
+}
+
+key L {
+    label:                              'L'
+    base:                               '\u03bb'
+    shift, capslock:                    '\u039b'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base, capslock:                     '\u0301'
+#should be \u0384 (greek tonos)
+    shift:                              '\u0308'
+    ralt:                               '\u0385'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base, capslock:                     '\''
+    shift:                              '"'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+    ralt:                               '\u00ac'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base, capslock:                     '<'
+    shift:                              '>'
+    ralt:                               '\\'
+    shift+ralt:                         '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               '\u03b6'
+    shift, capslock:                    '\u0396'
+}
+
+key X {
+    label:                              'X'
+    base:                               '\u03c7'
+    shift, capslock:                    '\u03a7'
+}
+
+key C {
+    label:                              'C'
+    base:                               '\u03c8'
+    shift, capslock:                    '\u03a8'
+    ralt:                               '\u00a9'
+}
+
+key V {
+    label:                              'V'
+    base:                               '\u03c9'
+    shift, capslock:                    '\u03a9'
+}
+
+key B {
+    label:                              'B'
+    base:                               '\u03b2'
+    shift, capslock:                    '\u0392'
+}
+
+key N {
+    label:                              'N'
+    base:                               '\u03bd'
+    shift, capslock:                    '\u039d'
+}
+
+key M {
+    label:                              'M'
+    base:                               '\u03bc'
+    shift, capslock:                    '\u039c'
+}
+
+key COMMA {
+    label:                              ','
+    base, capslock:                     ','
+    shift:                              '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base, capslock:                     '.'
+    shift:                              '>'
+}
+
+key SLASH {
+    label:                              '/'
+    base, capslock:                     '/'
+    shift:                              '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
new file mode 100644
index 0000000..cd3a4b9
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
@@ -0,0 +1,341 @@
+# 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.
+
+#
+# Hebrew (based EU) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               ';'
+    shift:                              '~'
+    shift+capslock:                     '\u05b0'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    shift+capslock:                     '\u05b1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '@'
+    shift+capslock:                     '\u05b2'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    shift+capslock:                     '\u05b3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+    ralt:                               '\u20aa'
+    shift+capslock:                     '\u05b4'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    shift+capslock:                     '\u05b5'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '^'
+    shift+capslock:                     '\u05b6'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '&'
+    shift+capslock:                     '\u05b7'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '*'
+    shift+capslock:                     '\u05b8'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+    shift+capslock:                     '\u05c2'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+    shift+capslock:                     '\u05c1'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '\u05bf'
+    shift+capslock:                     '\u05b9'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '='
+    shift:                              '+'
+    shift+capslock:                     '\u05bc'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               '/'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               '\u0027'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               '\u05e7'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               '\u05e8'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               '\u05d0'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               '\u05d8'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               '\u05d5'
+    shift, capslock:                    'U'
+    ralt:                               '\u05f0'
+}
+
+key I {
+    label:                              'I'
+    base:                               '\u05df'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               '\u05dd'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               '\u05e4'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '['
+    shift:                              '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     ']'
+    shift:                              '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               '\u05e9'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               '\u05d3'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               '\u05d2'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               '\u05db'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               '\u05e2'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               '\u05d9'
+    shift, capslock:                    'H'
+    ralt:                               '\u05f2'
+}
+
+key J {
+    label:                              'J'
+    base:                               '\u05d7'
+    shift, capslock:                    'J'
+    ralt:                               '\u05f1'
+}
+
+key K {
+    label:                              'K'
+    base:                               '\u05dc'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               '\u05da'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               '\u05e3'
+    shift:                              ':'
+    capslock:                           ';'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base:                               ','
+    shift:                              '"'
+    capslock:                           '\''
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               '\u05d6'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               '\u05e1'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               '\u05d1'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               '\u05d4'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               '\u05e0'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               '\u05de'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               '\u05e6'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               '\u05ea'
+    shift:                              '<'
+    capslock:                           ','
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '\u05e5'
+    shift:                              '>'
+    capslock:                           '.'
+}
+
+key SLASH {
+    label:                              '/'
+    base:                               '.'
+    shift:                              '?'
+    capslock:                           '/'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
new file mode 100644
index 0000000..72ca333
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
@@ -0,0 +1,338 @@
+# 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.
+
+#
+# Lithuanian (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '\u0105'
+    shift, capslock:                    '\u0104'
+    ralt:                               '1'
+    shift+ralt:                         '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u010d'
+    shift, capslock:                    '\u010c'
+    ralt:                               '2'
+    shift+ralt:                         '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0119'
+    shift, capslock:                    '\u0118'
+    ralt:                               '3'
+    shift+ralt:                         '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u0117'
+    shift, capslock:                    '\u0116'
+    ralt:                               '4'
+    shift+ralt:                         '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u012f'
+    shift, capslock:                    '\u012e'
+    ralt:                               '5'
+    shift+ralt:                         '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u0161'
+    shift, capslock:                    '\u0160'
+    ralt:                               '6'
+    shift+ralt:                         '\u0302'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u0173'
+    shift, capslock:                    '\u0172'
+    ralt:                               '7'
+    shift+ralt:                         '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u016b'
+    shift, capslock:                    '\u016a'
+    ralt:                               '8'
+    shift+ralt:                         '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+    ralt:                               '9'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+    ralt:                               '0'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '\u017e'
+    shift, capslock:                    '\u017d'
+    ralt:                               '='
+    shift+ralt:                         '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base:                               '['
+    shift:                              '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base:                               ']'
+    shift:                              '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               ';'
+    shift:                              ':'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '"'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              '>'
+}
+
+key SLASH {
+    label:                              '/'
+    base:                               '/'
+    shift:                              '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
new file mode 100644
index 0000000..16eb53f
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
@@ -0,0 +1,325 @@
+# 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.
+
+#
+# Spanish (Latin) (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '|'
+    base:                               '|'
+    shift:                              '\u00ba'
+    ralt:                               '\u00ac'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+}
+
+key MINUS {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key EQUALS {
+    label:                              '\u00bf'
+    base:                               '\u00bf'
+    shift:                              '\u00a1'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '@'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0308'
+    ralt:                               '['
+}
+
+key RIGHT_BRACKET {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d1'
+    base:                               '\u00f1'
+    shift, capslock:                    '\u00d1'
+}
+
+key APOSTROPHE {
+    label:                              '{'
+    base:                               '{'
+    shift:                              '['
+    ralt:                               '\u0302'
+}
+
+key BACKSLASH {
+    label:                              '}'
+    base:                               '}'
+    shift:                              ']'
+    ralt:                               '\u0300'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key SLASH {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index 13fcbb4..ddaf706 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloweens"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turks"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Oekraïens"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabies"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieks"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreeus"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litaus"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latyn)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index d475772..09b65e0 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ስሎቫኒያ"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ቱርክኛ"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ዩክሬን"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"አረብኛ"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ግሪክኛ"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ዕብራስጥ"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ሊቱዌኒያኛ"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ስፓኒሽ (ላቲን)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 903d978..4c5cccc 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"السلوفينية"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"التركية"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"الأوكرانية"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"العربية"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"اليونانية"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"العبرية"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"الليتوانية"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"الإسبانية (اللاتينية)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 0c413a4..cc3eb36 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенски"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турски"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украински"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабска клавиатурна подредба"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Гръцка клавиатурна подредба"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ивритска клавиатурна подредба"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовска клавиатурна подредба"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Исп. клав. подредба (Лат. Америка)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 2021b8f..2c8521c 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Eslovè"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraïnès"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Àrab"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreu"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituà"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanyol (llatí)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 33b420e..9b65eed 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovinské"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabština"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"řečtina"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejština"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litevština"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španělština (Latinská Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index fc07db2..8b423ab 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovensk"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tyrkisk"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainsk"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisk"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Græsk"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebræisk"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinamerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index b5c3b50..b5a5870 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slowenisch"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türkisch"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainisch"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisch"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griechisch"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebräisch"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisch"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanisch (Lateinisch)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index f5d57a0..976f370 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Σλοβενικά"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Τουρκικά"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ουκρανικά"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Αραβικά"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Ελληνικά"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Εβραϊκά"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Λιθουανικά"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ισπανικά (Λατινικής Αμερικής)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 2d794a6..50a98b26 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 2d794a6..50a98b26 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 2d61b80..b842a3b 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griego"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreo"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (latino)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 82ea4d6..5dc85a0 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griego"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreo"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (Latinoamérica)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-et-rEE/strings.xml b/packages/InputDevices/res/values-et-rEE/strings.xml
index 5b4fa3b..4ffdb37 100644
--- a/packages/InputDevices/res/values-et-rEE/strings.xml
+++ b/packages/InputDevices/res/values-et-rEE/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveenia"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türgi"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Araabia"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Kreeka"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Heebrea"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Leedu"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Hispaania (Ladina-Ameerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index 06c7f3a..fd6f54b 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"اسلوونیایی"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ترکی"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"اوکراینی"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"عربی"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"یونانی"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"عبری"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"لیتوانیایی"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"اسپانیایی (لاتین)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 428eb30..b7ec183 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"sloveeni"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turkki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukraina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabia"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"kreikka"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"heprea"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"liettua"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"espanja (Latinalainen Amerikka)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index c947634..18600ed 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovène"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainien"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hébreu"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 4ad4ffa..e3ca49c 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovène"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainien"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hébreu"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 8e1864e..a1a4ef2 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"स्लोवेनियाई"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्की"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"यूक्रेनियाई"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ग्रीक"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"हिब्रू"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियाई"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"स्पेनिश (लैटिन)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index 6217bf0..512ffd7 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovenska"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turska"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinska"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arapski"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"grčki"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejski"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litavski"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španjolski (Latinska Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 0cdbfb2..645e597 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"szlovén"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"török"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrán"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arab"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"görög"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"héber"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litván"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"spanyol (latin-amerikai)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-hy-rAM/strings.xml b/packages/InputDevices/res/values-hy-rAM/strings.xml
index bc5bbfc..282dc82 100644
--- a/packages/InputDevices/res/values-hy-rAM/strings.xml
+++ b/packages/InputDevices/res/values-hy-rAM/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Սլովեներեն"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Թուրքերեն"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ուկրաիներեն"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Արաբերեն"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Հունարեն"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Եբրայերեն"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Լիտվերեն"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Իսպաներեն (Լատինական)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 11e2dd0a..a7fc330 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenia"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arab"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Yunani"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ibrani"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuania"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanyol (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index 334318e..e8fe310 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraino"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabo"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greco"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ebraico"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spagnolo (America Latina)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index a989391..d2673d9 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"סלובנית"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"טורקית"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"אוקראינית"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ערבית"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"יוונית"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"עברית"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ליטאית"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ספרדית (לטינית)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 950b727..86cd30e 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"スロベニア語"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"トルコ語"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ウクライナ語"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"アラビア語"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ギリシャ語"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ヘブライ語"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"リトアニア語"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"スペイン語(中南米)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ka-rGE/strings.xml b/packages/InputDevices/res/values-ka-rGE/strings.xml
index 6e507aa..14ebee8 100644
--- a/packages/InputDevices/res/values-ka-rGE/strings.xml
+++ b/packages/InputDevices/res/values-ka-rGE/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"სლოვენური"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"თურქული"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"უკრაინული"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"არაბული"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ბერძნული"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ებრაული"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ლიტვური"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ესპანური (ლათინური)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-km-rKH/strings.xml b/packages/InputDevices/res/values-km-rKH/strings.xml
index 9a8c99b..569f273 100644
--- a/packages/InputDevices/res/values-km-rKH/strings.xml
+++ b/packages/InputDevices/res/values-km-rKH/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ស្លូវ៉ានី"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ទួរគី"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"អ៊ុយក្រែន"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"អារ៉ាប់"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ក្រិក"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"អ៊ីស្រាអែល"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"លីទុយអានី"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"អេស្ប៉ាញ (ឡាតាំង​)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 8071586..dbbe6ea 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"슬로베니아어"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"터키어"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"우크라이나어"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"아랍어"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"그리스어"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"히브리어"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"리투아니아어"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"스페인어(라틴)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lo-rLA/strings.xml b/packages/InputDevices/res/values-lo-rLA/strings.xml
index 2c97e11..eaf5026 100644
--- a/packages/InputDevices/res/values-lo-rLA/strings.xml
+++ b/packages/InputDevices/res/values-lo-rLA/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ສະໂລເວນຽນ"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ເຕີກິສ"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ຢູເຄຣນຽນ"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ອາຣັບ"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"ກ​ຣີກ"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ຮີບຣິວ"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"​ລິ​ທົວ​ນຽນ"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"​ສະ​ແປນ​ນິດ (ລາ​ຕິນ)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index c0ed159..2fcacde 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovėnų k."</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkų k."</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainiečių k."</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabų"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Graikų"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrajų"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuvių"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ispanų (Lotynų Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index 07a8654..921c881 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovēņu"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turku"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiņu"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arābu"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieķu"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ivrits"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuviešu"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spāņu (latīņu)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-mn-rMN/strings.xml b/packages/InputDevices/res/values-mn-rMN/strings.xml
index ec6cccb..c99339e 100644
--- a/packages/InputDevices/res/values-mn-rMN/strings.xml
+++ b/packages/InputDevices/res/values-mn-rMN/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Словени"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Турк"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Украйн"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Араб"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Грек"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Еврей"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литви"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испани (Латин)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ms-rMY/strings.xml b/packages/InputDevices/res/values-ms-rMY/strings.xml
index 486f048..32041d0 100644
--- a/packages/InputDevices/res/values-ms-rMY/strings.xml
+++ b/packages/InputDevices/res/values-ms-rMY/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Bahasa Slovenia"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Bahasa Turki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Bahasa Ukraine"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Bahasa Arab"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Bahasa Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Bahasa Ibrani"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Bahasa Lithuania"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Bahasa Sepanyol (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index b646061..e880981 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovensk"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tyrkisk"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainsk"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisk"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Gresk"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraisk"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinsk)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index 56d84c9..92a9fcf 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveens"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turks"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Oekraïens"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisch"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieks"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreeuws"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litouws"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latijns-Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 4522215..f84252a 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Słoweński"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turecki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiński"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabski"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"grecki"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrajski"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litewski"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"hiszpański (Ameryka Łacińska)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 9a639cd..670badd 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grego"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraico"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index 05a0cd0..71274aa 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grego"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraico"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 895d8f6..151c11d 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenă"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turcă"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraineană"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabă"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greacă"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ebraică"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniană"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaniolă (America Latină)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index a4cbfd7..585a215 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенский"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецкий"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украинский"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабский"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Греческий"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Иврит"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовский"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испанский (Латинская Америка)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index 01ab042..d14c204 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovinské"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabčina"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Gréčtina"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrejčina"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litovčina"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Španielčina (Latinská Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 30ff3c4..b8fc823e 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovenska"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"turška"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinska"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabščina"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"grščina"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejščina"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litovščina"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španščina (Latinska Amerika)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index d23ac00..45e0b4b 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словеначка"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турска"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украјинска"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"арапски"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"грчки"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"хебрејски"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"литвански"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"шпански (Латинска Америка)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index 25a5ae8..ce20bff 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenskt"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkiskt"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainskt"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabiska"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grekiska"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreiska"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauiska"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanska (latinamerikansk)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 65ab96a1..38bc83a 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Kislovenia"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Kituruki"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Kiukrania"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Kiarabu"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Kigiriki"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Kiyahudi"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Kilithuania"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Kihispania (Kilatini)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 0cc7d47..8951281 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"สโลวีเนีย"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ตุรกี"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ยูเครน"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ภาษาอารบิค"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"กรีก"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ฮิบรู"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ลิทัวเนีย"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"สเปน (ละติน)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index 08f34d2..c551e20 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index f7c1262..d828e78 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovence"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türkçe"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraynaca"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arapça"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Yunanca"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"İbranice"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litvanca"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"İspanyolca (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index ee6ffc7..b4b9923 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенська"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецька"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"українська"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабська"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Грецька"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Іврит"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовська"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Іспанська (латиниця)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index 7a65e45..18aa989 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Tiếng Sloven"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tiếng Thổ Nhĩ Kỳ"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Tiếng Ukraina"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Tiếng Ả rập"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Tiếng Hy Lạp"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Tiếng Do Thái"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Tiếng Lithuania"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Tiếng Tây Ban Nha (La tinh)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index 85b1c84..8d76f92 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛文尼亚语"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其语"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"乌克兰语"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯语"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"希腊语"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯来语"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛语"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙语(拉丁美洲)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 839c546..031f294 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛文尼亞文"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其文"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"烏克蘭文"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯文"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"希臘文"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯來文"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index ba9f132..76cb6a2 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛維尼亞文"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其文"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"烏克蘭文"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯文"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"希臘文"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯來文"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index fbf1074..3e4ad67 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -34,4 +34,9 @@
     <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Isi-Slovenian"</string>
     <string name="keyboard_layout_turkish" msgid="7736163250907964898">"Isi-Turkish"</string>
     <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Isi-Ukrainian"</string>
+    <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Isi-Arabic"</string>
+    <string name="keyboard_layout_greek" msgid="7289253560162386040">"Isi-Greek"</string>
+    <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Isi-Hebrew"</string>
+    <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Isi-Lithuanian"</string>
+    <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Isi-Spanish (Latin)"</string>
 </resources>
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 54c18f1..6239336 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -98,4 +98,19 @@
 
     <!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_ukrainian">Ukrainian</string>
+
+    <!-- Arabic keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_arabic">Arabic</string>
+
+    <!-- Greek keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_greek">Greek</string>
+
+    <!-- Hebrew keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_hebrew">Hebrew</string>
+
+    <!-- Lithuanian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_lithuanian">Lithuanian</string>
+
+    <!-- Spanish (Latin) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_spanish_latin">Spanish (Latin)</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 1f48a36..dc1db0b 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -123,4 +123,24 @@
     <keyboard-layout android:name="keyboard_layout_ukrainian"
             android:label="@string/keyboard_layout_ukrainian"
             android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
+
+    <keyboard-layout android:name="keyboard_layout_arabic"
+            android:label="@string/keyboard_layout_arabic"
+            android:keyboardLayout="@raw/keyboard_layout_arabic" />
+
+    <keyboard-layout android:name="keyboard_layout_greek"
+            android:label="@string/keyboard_layout_greek"
+            android:keyboardLayout="@raw/keyboard_layout_greek" />
+
+    <keyboard-layout android:name="keyboard_layout_hebrew"
+            android:label="@string/keyboard_layout_hebrew"
+            android:keyboardLayout="@raw/keyboard_layout_hebrew" />
+
+    <keyboard-layout android:name="keyboard_layout_lithuanian"
+            android:label="@string/keyboard_layout_lithuanian"
+            android:keyboardLayout="@raw/keyboard_layout_lithuanian" />
+
+    <keyboard-layout android:name="keyboard_layout_spanish_latin"
+            android:label="@string/keyboard_layout_spanish_latin"
+            android:keyboardLayout="@raw/keyboard_layout_spanish_latin" />
 </keyboard-layouts>
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 66d1e75..75b7dbd 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -39,11 +39,13 @@
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.TRUST_LISTENER" />
 
     <application android:label="@string/app_name"
         android:process="com.android.systemui"
         android:persistent="true"
-        android:supportsRtl="true">
+        android:supportsRtl="true"
+        android:requiredForProfile="all">
 
         <service android:name=".KeyguardService"
             android:exported="true" />
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 19eb4c5..c775467 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -75,7 +75,7 @@
     <string name="keyguard_accessibility_transport_thumbs_down_description" msgid="8101433677192177861">"Bài hát được đánh dấu không thích"</string>
     <string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Trái tim"</string>
     <string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"Mở khóa để tiếp tục"</string>
-    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình khởi chạy bị hủy"</string>
+    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình chạy bị hủy"</string>
     <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"Thả <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> để xóa."</string>
     <string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> sẽ không bị xóa."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index d4f98af..80fcf75 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -68,7 +68,7 @@
         <item name="android:textSize">@dimen/widget_big_font_size</item>
     </style>
 
-    <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.Holo.SeekBar">
+    <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.DeviceDefault.Light.SeekBar">
         <item name="android:indeterminateOnly">false</item>
         <item name="android:progressDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
         <item name="android:indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 368a97a..0d5e477 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -104,9 +104,10 @@
 
         // Workaround to avoid camera release/acquisition race when resuming face unlock
         // after showing lockscreen camera (bug 11063890).
-        KeyguardUpdateMonitor.getInstance(getContext()).setAlternateUnlockEnabled(false);
+        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
+        updateMonitor.setAlternateUnlockEnabled(false);
 
-        if (lockPatternUtils.isSecure()) {
+        if (mustLaunchSecurely()) {
             // Launch the secure version of the camera
             if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
                 // TODO: Show disambiguation dialog instead.
@@ -123,6 +124,13 @@
         }
     }
 
+    private boolean mustLaunchSecurely() {
+        LockPatternUtils lockPatternUtils = getLockPatternUtils();
+        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
+        int currentUser = lockPatternUtils.getCurrentUser();
+        return lockPatternUtils.isSecure() && !updateMonitor.getUserHasTrust(currentUser);
+    }
+
     public void launchWidgetPicker(int appWidgetId) {
         Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
 
@@ -177,9 +185,9 @@
                 Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_SINGLE_TOP
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        boolean isSecure = lockPatternUtils.isSecure();
-        if (!isSecure || showsWhileLocked) {
-            if (!isSecure) {
+        boolean mustLaunchSecurely = mustLaunchSecurely();
+        if (!mustLaunchSecurely || showsWhileLocked) {
+            if (!mustLaunchSecurely) {
                 dismissKeyguardOnNextActivity();
             }
             try {
@@ -253,7 +261,7 @@
     }
 
     private Intent getCameraIntent() {
-        return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+        return mustLaunchSecurely() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
     }
 
     private boolean wouldLaunchResolverActivity(Intent intent) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 9f5768a..da6482a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -23,6 +23,7 @@
 import com.android.internal.widget.LockPatternUtils;
 
 public class KeyguardSecurityModel {
+
     /**
      * The different types of security available for {@link Mode#UnlockScreen}.
      * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
@@ -82,6 +83,8 @@
         } else if (simState == IccCardConstants.State.PUK_REQUIRED
                 && mLockPatternUtils.isPukUnlockScreenEnable()) {
             mode = SecurityMode.SimPuk;
+        } else if (updateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
+            mode = SecurityMode.None;
         } else {
             final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
             switch (security) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3b712e9..88c78ab 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -20,6 +20,7 @@
 import android.app.IUserSwitchObserver;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -51,6 +52,8 @@
 
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.SparseBooleanArray;
+
 import com.google.android.collect.Lists;
 
 import java.lang.ref.WeakReference;
@@ -66,7 +69,7 @@
  * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
  * and {@link #clearFailedUnlockAttempts()}.  Maybe we should rename this 'KeyguardContext'...
  */
-public class KeyguardUpdateMonitor {
+public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
 
     private static final String TAG = "KeyguardUpdateMonitor";
     private static final boolean DEBUG = false;
@@ -205,6 +208,17 @@
 
     private AudioManager mAudioManager;
 
+    private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
+
+    @Override
+    public void onTrustChanged(boolean enabled, int userId) {
+        mUserHasTrust.put(userId, enabled);
+    }
+
+    public boolean getUserHasTrust(int userId) {
+        return mUserHasTrust.get(userId);
+    }
+
     static class DisplayClientState {
         public int clientGeneration;
         public boolean clearing;
@@ -581,6 +595,9 @@
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
+
+        TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+        trustManager.registerTrustListener(this);
     }
 
     private boolean isDeviceProvisionedInSettingsDb() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 481d132..556711b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -178,4 +178,5 @@
      * Called when the NFC Service has found a tag that is registered for NFC unlock.
      */
     public void onNfcUnlock() { }
+
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index 31e806c..354d13f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -550,7 +550,9 @@
 
                 @Override
                 public int getSessionType() {
-                    return mLockPatternUtils.isSecure() ? Session.TYPE_KEYGUARD_SECURE
+                    return mLockPatternUtils.isSecure() && !mUpdateMonitor.getUserHasTrust(
+                            mLockPatternUtils.getCurrentUser())
+                            ? Session.TYPE_KEYGUARD_SECURE
                             : Session.TYPE_KEYGUARD_INSECURE;
                 }
             }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
@@ -979,6 +981,13 @@
             return;
         }
 
+        if (mLockPatternUtils.checkVoldPassword()) {
+            if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
+            // Without this, settings is not enabled until the lock screen first appears
+            hideLocked();
+            return;
+        }
+
         if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
         showLocked(options);
     }
diff --git a/packages/Keyguard/test/AndroidManifest.xml b/packages/Keyguard/test/AndroidManifest.xml
index b801e4b..1638127 100644
--- a/packages/Keyguard/test/AndroidManifest.xml
+++ b/packages/Keyguard/test/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <application android:label="@string/app_name" android:icon="@drawable/app_icon">
         <activity android:name=".KeyguardTestActivity"
                 android:label="@string/app_name"
-                android:theme="@android:style/Theme.Holo">
+                android:theme="@android:style/Theme.DeviceDefault.Light">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/DynamicDrawableTest/Android.mk b/packages/Keyguard/test/SampleTrustAgent/Android.mk
similarity index 68%
copy from tests/DynamicDrawableTest/Android.mk
copy to packages/Keyguard/test/SampleTrustAgent/Android.mk
index 5c51301..7551fdf 100644
--- a/tests/DynamicDrawableTest/Android.mk
+++ b/packages/Keyguard/test/SampleTrustAgent/Android.mk
@@ -1,4 +1,3 @@
-#
 # Copyright (C) 2014 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,10 +16,18 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := DynamicDrawableTest
+LOCAL_PACKAGE_NAME := SampleTrustAgent
+
+# Remove these to verify permission checks are working correctly
+#LOCAL_CERTIFICATE := platform
+#LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_MODULE_TAGS := tests
 
+# LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
 include $(BUILD_PACKAGE)
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
new file mode 100644
index 0000000..1511911
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.trustagent.test">
+    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
+    <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+    <application android:label="@string/app_name">
+      <service
+          android:name=".SampleTrustAgent"
+          android:label="@string/app_name"
+          android:exported="true">
+        <intent-filter>
+          <action android:name="android.service.trust.TrustAgentService" />
+          <category android:name="android.intent.category.DEFAULT" />
+        </intent-filter>
+        <meta-data android:name="android.service.trust.trustagent"
+                   android:resource="@xml/sample_trust_agent"/>
+      </service>
+
+      <activity
+          android:name=".SampleTrustAgentSettings"
+          android:label="@string/app_name"
+          android:exported="true"
+          android:launchMode="singleInstance" >
+      </activity>
+    </application>
+</manifest>
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
new file mode 100644
index 0000000..01b107b
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -0,0 +1,35 @@
+<?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:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+    <Button android:id="@+id/enable_trust"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Grant trust for 30 seconds" />
+    <Button android:id="@+id/revoke_trust"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Revoke trust" />
+    <CheckBox android:id="@+id/report_unlock_attempts"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Report unlock attempts" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml b/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml
new file mode 100644
index 0000000..0c6b502
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <string name="app_name">Sample Trust Agent</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
new file mode 100644
index 0000000..b48e011
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
@@ -0,0 +1,18 @@
+<?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
+  -->
+<trust_agent xmlns:android="http://schemas.android.com/apk/res/android"
+        android:settingsActivity=".SampleTrustAgentSettings" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
new file mode 100644
index 0000000..25406d6
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -0,0 +1,107 @@
+/*
+ * 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.trustagent.test;
+
+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.preference.PreferenceManager;
+import android.service.trust.TrustAgentService;
+import android.support.v4.content.LocalBroadcastManager;
+import android.widget.Toast;
+
+public class SampleTrustAgent extends TrustAgentService {
+
+    LocalBroadcastManager mLocalBroadcastManager;
+
+    private static final String ACTION_ENABLE_TRUST = "action.sample_trust_agent.enable_trust";
+    private static final String ACTION_REVOKE_TRUST = "action.sample_trust_agent.revoke_trust";
+
+    private static final String EXTRA_MESSAGE = "extra.message";
+    private static final String EXTRA_DURATION = "extra.duration";
+    private static final String EXTRA_EXTRA = "extra.extra";
+
+    private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
+            = "preference.report_unlock_attempts";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_ENABLE_TRUST);
+        filter.addAction(ACTION_REVOKE_TRUST);
+        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
+        mLocalBroadcastManager.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    protected void onUnlockAttempt(boolean successful) {
+        if (getReportUnlockAttempts(this)) {
+            Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
+                    Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mLocalBroadcastManager.unregisterReceiver(mReceiver);
+    }
+
+    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (ACTION_ENABLE_TRUST.equals(action)) {
+                enableTrust(intent.getStringExtra(EXTRA_MESSAGE),
+                        intent.getLongExtra(EXTRA_DURATION, 0),
+                        false /* initiatedByUser */);
+            } else if (ACTION_REVOKE_TRUST.equals(action)) {
+                revokeTrust();
+            }
+        }
+    };
+
+    public static void sendEnableTrust(Context context,
+            String message, long durationMs, Bundle extra) {
+        Intent intent = new Intent(ACTION_ENABLE_TRUST);
+        intent.putExtra(EXTRA_MESSAGE, message);
+        intent.putExtra(EXTRA_DURATION, durationMs);
+        intent.putExtra(EXTRA_EXTRA, extra);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+    }
+
+    public static void sendRevokeTrust(Context context) {
+        Intent intent = new Intent(ACTION_REVOKE_TRUST);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+    }
+
+    public static void setReportUnlockAttempts(Context context, boolean enabled) {
+        SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(context);
+        sharedPreferences.edit().putBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, enabled).apply();
+    }
+
+    public static boolean getReportUnlockAttempts(Context context) {
+        SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(context);
+        return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
+    }
+}
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
new file mode 100644
index 0000000..0a6f675
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -0,0 +1,69 @@
+/*
+ * 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.trustagent.test;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+public class SampleTrustAgentSettings extends Activity implements View.OnClickListener,
+        CompoundButton.OnCheckedChangeListener {
+
+    private static final int TRUST_DURATION_MS = 30 * 1000;
+
+    private CheckBox mReportUnlockAttempts;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.sample_trust_agent_settings);
+
+        findViewById(R.id.enable_trust).setOnClickListener(this);
+        findViewById(R.id.revoke_trust).setOnClickListener(this);
+
+        mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
+        mReportUnlockAttempts.setOnCheckedChangeListener(this);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
+    }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.enable_trust) {
+            SampleTrustAgent.sendEnableTrust(this, "SampleTrustAgent", TRUST_DURATION_MS,
+                    null /* extra */);
+        } else if (id == R.id.revoke_trust) {
+            SampleTrustAgent.sendRevokeTrust(this);
+        }
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+        if (buttonView.getId() == R.id.report_unlock_attempts) {
+            SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
+        }
+    }
+}
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 6fc77df..4488b6a 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -61,7 +61,7 @@
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
                 android:indeterminate="true"
-                style="@android:style/Widget.Holo.ProgressBar.Horizontal">
+                style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal">
             </ProgressBar>
 
         </LinearLayout>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 86f4a37..94ab895 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,7 @@
 
 <resources>
 
-    <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
+    <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowSoftInputMode">stateAlwaysHidden|adjustResize</item>
         <item name="android:windowIsTranslucent">true</item>
@@ -25,11 +25,11 @@
         <item name="android:windowIsFloating">true</item>
     </style>
 
-    <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light">
+    <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item>
     </style>
 
-    <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.Holo.ActionBar">
+    <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.DeviceDefault.Light.ActionBar">
         <item name="android:displayOptions">showTitle</item>
     </style>
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 29e8d1d..19286c8 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.shell"
         coreApp="true"
@@ -83,7 +101,7 @@
 
         <activity
             android:name=".BugreportWarningActivity"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true"
             android:exported="false" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b09cc1d..3424eed 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
         package="com.android.systemui"
@@ -157,7 +175,7 @@
         <activity android:name=".usb.UsbConfirmActivity"
             android:exported="true"
             android:permission="android.permission.MANAGE_USB"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
@@ -166,7 +184,7 @@
         <activity android:name=".usb.UsbPermissionActivity"
             android:exported="true"
             android:permission="android.permission.MANAGE_USB"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
@@ -175,7 +193,7 @@
         <activity android:name=".usb.UsbResolverActivity"
             android:exported="true"
             android:permission="android.permission.MANAGE_USB"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
@@ -184,7 +202,7 @@
         <activity android:name=".usb.UsbAccessoryUriActivity"
             android:exported="true"
             android:permission="android.permission.MANAGE_USB"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
@@ -192,7 +210,7 @@
         <!-- started from UsbDebuggingManager -->
         <activity android:name=".usb.UsbDebuggingActivity"
             android:permission="android.permission.MANAGE_USB"
-            android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true">
         </activity>
@@ -202,7 +220,7 @@
             android:name=".net.NetworkOverLimitActivity"
             android:exported="true"
             android:permission="android.permission.MANAGE_NETWORK_POLICY"
-            android:theme="@android:style/Theme.Holo.Panel"
+            android:theme="@android:style/Theme.DeviceDefault.Light.Panel"
             android:finishOnCloseSystemDialogs="true"
             android:launchMode="singleTop"
             android:taskAffinity="com.android.systemui.net"
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index f6e875c..96da21f 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -26,23 +26,31 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="top|center_horizontal"
-        android:background="#88000000">
+        android:background="#e6444444">
         <ImageView
-            android:id="@+id/activity_icon"
-            android:layout_width="@dimen/recents_task_view_icon_size"
-            android:layout_height="@dimen/recents_task_view_icon_size"
-            android:layout_gravity="top|left"
+            android:id="@+id/application_icon"
+            android:layout_width="@dimen/recents_task_view_application_icon_size"
+            android:layout_height="@dimen/recents_task_view_application_icon_size"
+            android:layout_gravity="center_vertical|left"
             android:padding="8dp" />
         <TextView
             android:id="@+id/activity_description"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical|left"
-            android:layout_marginLeft="@dimen/recents_task_view_icon_size"
+            android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
+            android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
             android:textSize="24sp"
             android:textColor="#ffffffff"
             android:text="@string/recents_empty_message"
             android:fontFamily="sans-serif-thin" />
+        <ImageView
+            android:id="@+id/activity_icon"
+            android:layout_width="@dimen/recents_task_view_activity_icon_size"
+            android:layout_height="@dimen/recents_task_view_activity_icon_size"
+            android:layout_gravity="center_vertical|right"
+            android:padding="12dp"
+            android:visibility="invisible" />
     </com.android.systemui.recents.views.TaskBarView>
 </com.android.systemui.recents.views.TaskView>
 
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1da66bb..a7ec064 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -24,19 +24,10 @@
     android:id="@+id/notification_panel"
     android:layout_width="0dp"
     android:layout_height="wrap_content"
-    android:background="@drawable/notification_panel_bg"
     android:paddingTop="@dimen/notification_panel_padding_top"
     android:layout_marginStart="@dimen/notification_panel_margin_left"
     >
 
-    <View
-        android:id="@+id/handle"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/close_handle_height"
-        android:background="@drawable/status_bar_close"
-        android:visibility="invisible"
-        />
-
     <include
         layout="@layout/carrier_label"
         android:layout_height="@dimen/carrier_label_height"
@@ -69,6 +60,7 @@
             />
 
         <FrameLayout
+            android:id="@+id/notification_container_parent"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             >
@@ -77,21 +69,6 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 />
-    
-            <ScrollView
-                android:id="@+id/scroll"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:fadingEdge="none"
-                android:overScrollMode="ifContentScrolls"
-                >
-                <com.android.systemui.statusbar.policy.NotificationRowLayout
-                    android:id="@+id/latestItems"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    systemui:rowHeight="@dimen/notification_row_min_height"
-                    />
-            </ScrollView>
 
             <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
                     android:id="@+id/notification_stack_scroller"
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index 834cc2c..e6d7c93 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -29,7 +29,7 @@
         android:layout_alignParentBottom="true"
         android:button="@null"
         />
-    <SeekBar
+    <com.android.systemui.settings.ToggleSeekBar
         android:id="@+id/slider"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d7457f0..2e116d0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -20,7 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="7164937344850004466">"የስርዓት UI"</string>
-    <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
+    <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጽዳ"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ከዝርዝር አስወግድ"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"የትግበራ መረጃ"</string>
     <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ምንም የቅርብ ጊዜ ትግበራዎች የሉም"</string>
@@ -136,7 +136,7 @@
     <string name="accessibility_battery_level" msgid="7451474187113371965">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
-    <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጥራ"</string>
+    <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጽዳ"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS በማግኘት ላይ።"</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ነቅቷል።"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7671ef1..289d6c6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -188,8 +188,8 @@
     <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Bloccato in verticale"</string>
     <string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Bloccato in orizzontale"</string>
     <string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodo di immissione"</string>
-    <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizzazione"</string>
-    <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Posizione non attiva"</string>
+    <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizz."</string>
+    <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Geolocalizz. non attiva"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimediale"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
     <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo chiamate di emergenza"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1dd9300..77944c8 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -56,10 +56,10 @@
     <!-- Amount of time to hold off before showing the search panel when the user presses home -->
     <integer name="config_show_search_delay">200</integer>
 
-    <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+    <!-- Vibration duration for GlowPadView used in SearchPanelView -->
     <integer translatable="false" name="config_vibration_duration">0</integer>
 
-    <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+    <!-- Vibration duration for GlowPadView used in SearchPanelView -->
     <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
 
     <!-- The length of the vibration when the notification pops open. -->
@@ -107,5 +107,10 @@
 
     <!-- milliseconds before the heads up notification accepts touches. -->
     <integer name="heads_up_sensitivity_delay">700</integer>
+
+    <!-- The min animation duration for animating views that are currently visible. -->
+    <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>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a9b69854..2c8f9a1 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -230,8 +230,15 @@
     <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
     <dimen name="glowpadview_inner_radius">15dip</dimen>
 
-    <!-- The size of the icon in the recents task view. -->
-    <dimen name="recents_task_view_icon_size">60dp</dimen>
+    <!-- The size of the application icon in the recents task view. -->
+    <dimen name="recents_task_view_application_icon_size">60dp</dimen>
+
+    <!-- The size of the activity icon in the recents task view. -->
+    <dimen name="recents_task_view_activity_icon_size">60dp</dimen>
+
+    <!-- Used to calculate the translation animation duration, the expected amount of movement 
+         in dps over one second of time. -->
+    <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
 
     <!-- Space below the notification stack -->
     <dimen name="notification_stack_margin_bottom">0dp</dimen>
@@ -248,6 +255,6 @@
     <!-- Z distance between notifications if they are in the stack -->
     <dimen name="z_distance_between_notifications">2dp</dimen>
 
-    <!-- Width of the zen mode interstitial dialog.  Defaults to MATCH_PARENT. -->
-    <dimen name="zen_mode_dialog_width">-1px</dimen>
+    <!-- Width of the zen mode interstitial dialog. -->
+    <dimen name="zen_mode_dialog_width">320dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 14af020..76cadd7 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,12 +16,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+    <style name="RecentsStyle" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
     </style>
 
     <!-- Alternate Recents theme -->
-    <style name="RecentsTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+    <style name="RecentsTheme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
         <item name="android:windowTranslucentStatus">true</item>
         <item name="android:windowTranslucentNavigation">true</item>
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 48a6522..1832d37 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -34,6 +34,8 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
         View getChildAtRawPosition(float x, float y);
@@ -108,7 +110,7 @@
 
     private int mGravity;
 
-    private View mScrollView;
+    private ScrollAdapter mScrollAdapter;
 
     private OnScaleGestureListener mScaleGestureListener
             = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@@ -301,8 +303,8 @@
         mGravity = gravity;
     }
 
-    public void setScrollView(View scrollView) {
-        mScrollView = scrollView;
+    public void setScrollAdapter(ScrollAdapter adapter) {
+        mScrollAdapter = adapter;
     }
 
     private float calculateGlow(float target, float actual) {
@@ -384,7 +386,7 @@
                 }
                 return true;
             }
-            if (mScrollView != null && mScrollView.getScrollY() > 0) {
+            if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
                 return false;
             }
             // Now look for other gestures
@@ -407,7 +409,8 @@
             }
 
             case MotionEvent.ACTION_DOWN:
-                mWatchingForPull = isInside(mScrollView, x, y);
+                mWatchingForPull = mScrollAdapter != null &&
+                        isInside(mScrollAdapter.getHostView(), x, y);
                 mLastMotionY = y;
                 break;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 9d2d6ee..eb09335 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -156,7 +156,7 @@
 
     // Create an TaskDescription, returning null if the title or icon is null
     TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent,
-            ComponentName origActivity, CharSequence description) {
+            ComponentName origActivity, CharSequence description, int userId) {
         Intent intent = new Intent(baseIntent);
         if (origActivity != null) {
             intent.setComponent(origActivity);
@@ -175,7 +175,7 @@
 
                 TaskDescription item = new TaskDescription(taskId,
                         persistentTaskId, resolveInfo, baseIntent, info.packageName,
-                        description);
+                        description, userId);
                 item.setLabel(title);
 
                 return item;
@@ -368,7 +368,7 @@
         final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
 
         final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
                 UserHandle.CURRENT.getIdentifier());
         TaskDescription item = null;
         if (recentTasks.size() > 0) {
@@ -391,7 +391,8 @@
 
             item = createTaskDescription(recentInfo.id,
                     recentInfo.persistentId, recentInfo.baseIntent,
-                    recentInfo.origActivity, recentInfo.description);
+                    recentInfo.origActivity, recentInfo.description,
+                    recentInfo.userId);
             if (item != null) {
                 loadThumbnailAndIcon(item);
             }
@@ -441,7 +442,7 @@
 
                 final List<ActivityManager.RecentTaskInfo> recentTasks =
                         am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE
-                        | ActivityManager.RECENT_INCLUDE_RELATED);
+                        | ActivityManager.RECENT_INCLUDE_PROFILES);
                 int numTasks = recentTasks.size();
                 ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN)
                         .addCategory(Intent.CATEGORY_HOME).resolveActivityInfo(pm, 0);
@@ -474,7 +475,8 @@
 
                     TaskDescription item = createTaskDescription(recentInfo.id,
                             recentInfo.persistentId, recentInfo.baseIntent,
-                            recentInfo.origActivity, recentInfo.description);
+                            recentInfo.origActivity, recentInfo.description,
+                            recentInfo.userId);
 
                     if (item != null) {
                         while (true) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
index f75ea92..7ab40b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -165,7 +165,7 @@
                     am.getRecentTasks(2,
                             ActivityManager.RECENT_WITH_EXCLUDED |
                             ActivityManager.RECENT_IGNORE_UNAVAILABLE |
-                            ActivityManager.RECENT_INCLUDE_RELATED);
+                            ActivityManager.RECENT_INCLUDE_PROFILES);
             if (recentTasks.size() > 1 &&
                     mRecentsPanel.simulateClick(recentTasks.get(1).persistentId)) {
                 // recents panel will take care of calling show(false) through simulateClick
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ef56044..98bdee0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -689,7 +689,7 @@
             if (DEBUG) Log.v(TAG, "Starting activity " + intent);
             try {
                 context.startActivityAsUser(intent, opts,
-                        new UserHandle(UserHandle.USER_CURRENT));
+                        new UserHandle(ad.userId));
             } catch (SecurityException e) {
                 Log.e(TAG, "Recents does not have the permission to launch " + intent, e);
             } catch (ActivityNotFoundException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
index 2e0ee36..5ad965f 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recent;
 
+import android.os.UserHandle;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
@@ -27,6 +28,7 @@
     final Intent intent; // launch intent for application
     final String packageName; // used to override animations (see onClick())
     final CharSequence description;
+    final int userId;
 
     private Drawable mThumbnail; // generated by Activity.onCreateThumbnail()
     private Drawable mIcon; // application package icon
@@ -35,7 +37,7 @@
 
     public TaskDescription(int _taskId, int _persistentTaskId,
             ResolveInfo _resolveInfo, Intent _intent,
-            String _packageName, CharSequence _description) {
+            String _packageName, CharSequence _description, int _userId) {
         resolveInfo = _resolveInfo;
         intent = _intent;
         taskId = _taskId;
@@ -43,6 +45,7 @@
 
         description = _description;
         packageName = _packageName;
+        userId = _userId;
     }
 
     public TaskDescription() {
@@ -53,6 +56,7 @@
 
         description = null;
         packageName = null;
+        userId = UserHandle.USER_NULL;
     }
 
     public void setLoaded(boolean loaded) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 1a616a0..8543b97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,35 +23,26 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
 import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SystemUI;
 
 import java.util.List;
 
@@ -113,6 +104,7 @@
     final static String sRecentsService = "com.android.systemui.recents.RecentsService";
 
     Context mContext;
+    SystemServicesProxy mSystemServicesProxy;
 
     // Recents service binding
     Messenger mService = null;
@@ -127,6 +119,7 @@
 
     public AlternateRecentsComponent(Context context) {
         mContext = context;
+        mSystemServicesProxy = new SystemServicesProxy(context);
         mMessenger = new Messenger(new RecentsMessageHandler());
     }
 
@@ -219,17 +212,16 @@
 
     /** Loads the first task thumbnail */
     Bitmap loadFirstTaskThumbnail() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
                 UserHandle.CURRENT.getIdentifier());
         for (ActivityManager.RecentTaskInfo t : tasks) {
             // Skip tasks in the home stack
-            if (am.isInHomeStack(t.persistentId)) {
+            if (ssp.isInHomeStack(t.persistentId)) {
                 return null;
             }
 
-            Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
+            Bitmap thumbnail = ssp.getTaskThumbnail(t.persistentId);
             return thumbnail;
         }
         return null;
@@ -237,13 +229,12 @@
 
     /** Returns whether there is a first task */
     boolean hasFirstTask() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
-                ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
                 UserHandle.CURRENT.getIdentifier());
         for (ActivityManager.RecentTaskInfo t : tasks) {
             // Skip tasks in the home stack
-            if (am.isInHomeStack(t.persistentId)) {
+            if (ssp.isInHomeStack(t.persistentId)) {
                 continue;
             }
 
@@ -294,8 +285,8 @@
 
         // If Recents is the front most activity, then we should just communicate with it directly
         // to launch the first task or dismiss itself
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
         if (!tasks.isEmpty()) {
             ComponentName topActivity = tasks.get(0).topActivity;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
new file mode 100644
index 0000000..b085211
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
@@ -0,0 +1,67 @@
+package com.android.systemui.recents;
+
+import android.animation.TimeInterpolator;
+
+/**
+ * A pre-baked bezier-curved interpolator for quantum-paper transitions.
+ */
+public class BakedBezierInterpolator implements TimeInterpolator {
+    public static final BakedBezierInterpolator INSTANCE = new BakedBezierInterpolator();
+
+    /**
+     * Use the INSTANCE variable instead of instantiating.
+     */
+    private BakedBezierInterpolator() {
+        super();
+    }
+
+    /**
+     * Lookup table values.
+     * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+     * P0 (0,0)
+     * P1 (0.4, 0)
+     * P2 (0.2, 1.0)
+     * P3 (1.0, 1.0)
+     *
+     * Values sampled with x at regular intervals between 0 and 1.
+     *
+     * These values were generated using:
+     *   ./scripts/bezier_interpolator_values_gen.py 0.4 0.2
+     */
+    private static final float[] VALUES = new float[] {
+        0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
+        0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
+        0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
+        0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
+        0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
+        0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
+        0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
+        0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
+        0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
+        0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+    };
+
+    private static final float STEP_SIZE = 1.0f / (VALUES.length - 1);
+
+    @Override
+    public float getInterpolation(float input) {
+        if (input >= 1.0f) {
+            return 1.0f;
+        }
+
+        if (input <= 0f) {
+            return 0f;
+        }
+
+        int position = Math.min(
+                (int)(input * (VALUES.length - 1)),
+                VALUES.length - 2);
+
+        float quantized = position * STEP_SIZE;
+        float difference = input - quantized;
+        float weight = difference / STEP_SIZE;
+
+        return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index b5950e9..86f188e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,11 +26,17 @@
         public static final boolean Verbose = false;
 
         public static class App {
-            public static final boolean EnableTaskFiltering = false;
+            public static final boolean EnableTaskFiltering = true;
             public static final boolean EnableTaskStackClipping = false;
             public static final boolean EnableToggleNewRecentsActivity = false;
             // This disables the bitmap and icon caches to
             public static final boolean DisableBackgroundCache = false;
+            // For debugging, this enables us to create mock recents tasks
+            public static final boolean EnableSystemServicesProxy = false;
+            // For debugging, this defines the number of mock recents packages to create
+            public static final int SystemServicesProxyMockPackageCount = 3;
+            // For debugging, this defines the number of mock recents tasks to create
+            public static final int SystemServicesProxyMockTaskCount = 75;
 
             // Timing certain paths
             public static final String TimeRecentsStartupKey = "startup";
@@ -73,17 +79,11 @@
         public static class RecentsTaskLoader {
             // XXX: This should be calculated on the first load
             public static final int PreloadFirstTasksCount = 5;
-            // For debugging, this allows us to multiply the number of cards for each task
-            public static final int TaskEntryMultiplier = 1;
         }
 
         public static class TaskStackView {
-            public static class Animation {
-                public static final int TaskRemovedReshuffleDuration = 200;
-                public static final int SnapScrollBackDuration = 650;
-            }
-
             public static final int TaskStackOverscrollRange = 150;
+            public static final int FilterStartDelay = 25;
 
             // The padding will be applied to the smallest dimension, and then applied to all sides
             public static final float StackPaddingPct = 0.15f;
@@ -98,16 +98,10 @@
         }
 
         public static class TaskView {
-            public static class Animation {
-                public static final int TaskDataUpdatedFadeDuration = 250;
-                public static final int TaskIconOnEnterDuration = 175;
-                public static final int TaskIconOnLeavingDuration = 75;
-            }
-
             public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
             public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
 
-            public static final boolean UseRoundedCorners = true;
+            public static final boolean UseRoundedCorners = false;
             public static final float RoundedCornerRadiusDps = 3;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b65b864..dd75921 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -54,8 +54,11 @@
                     finish();
                 }
             } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
-                // Dismiss recents and launch the first task if possible
-                dismissRecentsIfVisible();
+                // Try and unfilter and filtered stacks
+                if (!mRecentsView.unfilterFilteredStacks()) {
+                    // If there are no filtered stacks, dismiss recents and launch the first task
+                    dismissRecentsIfVisible();
+                }
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 3d47cb6..4a0de0b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,11 +17,11 @@
 package com.android.systemui.recents;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
+import com.android.systemui.R;
 
 
 /** A static Recents configuration for the current context
@@ -34,6 +34,11 @@
     public Rect systemInsets = new Rect();
     public Rect displayRect = new Rect();
 
+    public float animationPxMovementPerSecond;
+
+    public int filteringCurrentViewsMinAnimDuration;
+    public int filteringNewViewsMinAnimDuration;
+
     /** Private constructor */
     private RecentsConfiguration() {}
 
@@ -58,6 +63,12 @@
         mDisplayMetrics = dm;
 
         displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
+        animationPxMovementPerSecond =
+                res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
+        filteringCurrentViewsMinAnimDuration =
+                res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
+        filteringNewViewsMinAnimDuration =
+                res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
     }
 
     public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 515cec1..22363bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -66,7 +66,7 @@
                 // in a bottom inset
                 tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
                 tsv.boundScroll();
-                TaskViewTransform transform = tsv.getStackTransform(0);
+                TaskViewTransform transform = tsv.getStackTransform(0, tsv.getStackScroll());
                 Rect taskRect = new Rect(transform.rect);
 
                 data.putParcelable("taskRect", taskRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index b497b69..d661f287 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -20,7 +20,6 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -109,18 +108,20 @@
     Handler mLoadThreadHandler;
     Handler mMainThreadHandler;
 
+    SystemServicesProxy mSystemServicesProxy;
     TaskResourceLoadQueue mLoadQueue;
-    DrawableLruCache mIconCache;
+    DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
 
     boolean mCancelled;
     boolean mWaitingOnLoadQueue;
 
     /** Constructor, creates a new loading thread that loads task resources in the background */
-    public TaskResourceLoader(TaskResourceLoadQueue loadQueue, DrawableLruCache iconCache,
+    public TaskResourceLoader(TaskResourceLoadQueue loadQueue,
+                              DrawableLruCache applicationIconCache,
                               BitmapLruCache thumbnailCache) {
         mLoadQueue = loadQueue;
-        mIconCache = iconCache;
+        mApplicationIconCache = applicationIconCache;
         mThumbnailCache = thumbnailCache;
         mMainThreadHandler = new Handler();
         mLoadThread = new HandlerThread("Recents-TaskResourceLoader");
@@ -135,6 +136,7 @@
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|start]");
         mContext = context;
         mCancelled = false;
+        mSystemServicesProxy = new SystemServicesProxy(context);
         // Notify the load thread to start loading
         synchronized(mLoadThread) {
             mLoadThread.notifyAll();
@@ -146,6 +148,7 @@
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|stop]");
         // Mark as cancelled for the thread to pick up
         mCancelled = true;
+        mSystemServicesProxy = null;
         // If we are waiting for the load queue for more tasks, then we can just reset the
         // Context now, since nothing is using it
         if (mWaitingOnLoadQueue) {
@@ -175,66 +178,60 @@
                     }
                 }
             } else {
+                SystemServicesProxy ssp = mSystemServicesProxy;
+
                 // Load the next item from the queue
                 Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
                 final Task t = nextTaskData.first;
                 final boolean forceLoadTask = nextTaskData.second;
                 if (t != null) {
-                    try {
-                        Drawable loadIcon = mIconCache.get(t.key);
-                        Bitmap loadThumbnail = mThumbnailCache.get(t.key);
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [TaskResourceLoader|load]",
-                                t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
-                                        " forceLoad: " + forceLoadTask);
-                        // Load the icon
-                        if (loadIcon == null || forceLoadTask) {
-                            PackageManager pm = mContext.getPackageManager();
-                            ActivityInfo info = pm.getActivityInfo(t.key.intent.getComponent(),
-                                    PackageManager.GET_META_DATA);
-                            Drawable icon = info.loadIcon(pm);
-                            if (!mCancelled) {
-                                if (icon != null) {
-                                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                            "    [TaskResourceLoader|loadIcon]",
-                                            icon);
-                                    loadIcon = icon;
-                                    mIconCache.put(t.key, icon);
-                                }
-                            }
-                        }
-                        // Load the thumbnail
-                        if (loadThumbnail == null || forceLoadTask) {
-                            ActivityManager am = (ActivityManager)
-                                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
-                            Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id);
-                            if (!mCancelled) {
-                                if (thumbnail != null) {
-                                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                            "    [TaskResourceLoader|loadThumbnail]",
-                                            thumbnail);
-                                    loadThumbnail = thumbnail;
-                                    mThumbnailCache.put(t.key, thumbnail);
-                                } else {
-                                    Console.logError(mContext,
-                                            "Failed to load task top thumbnail for: " +
-                                                    t.key.intent.getComponent().getPackageName());
-                                }
-                            }
-                        }
+                    Drawable loadIcon = mApplicationIconCache.get(t.key);
+                    Bitmap loadThumbnail = mThumbnailCache.get(t.key);
+                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                            "  [TaskResourceLoader|load]",
+                            t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
+                                    " forceLoad: " + forceLoadTask);
+                    // Load the application icon
+                    if (loadIcon == null || forceLoadTask) {
+                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
+                        Drawable icon = ssp.getActivityIcon(info);
                         if (!mCancelled) {
-                            // Notify that the task data has changed
-                            final Drawable newIcon = loadIcon;
-                            final Bitmap newThumbnail = loadThumbnail;
-                            mMainThreadHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
-                                }
-                            });
+                            if (icon != null) {
+                                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                        "    [TaskResourceLoader|loadIcon]",
+                                        icon);
+                                loadIcon = icon;
+                                mApplicationIconCache.put(t.key, icon);
+                            }
                         }
-                    } catch (PackageManager.NameNotFoundException ne) {
-                        ne.printStackTrace();
+                    }
+                    // Load the thumbnail
+                    if (loadThumbnail == null || forceLoadTask) {
+                        Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
+                        if (!mCancelled) {
+                            if (thumbnail != null) {
+                                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                        "    [TaskResourceLoader|loadThumbnail]",
+                                        thumbnail);
+                                loadThumbnail = thumbnail;
+                                mThumbnailCache.put(t.key, thumbnail);
+                            } else {
+                                Console.logError(mContext,
+                                        "Failed to load task top thumbnail for: " +
+                                                t.key.baseIntent.getComponent().getPackageName());
+                            }
+                        }
+                    }
+                    if (!mCancelled) {
+                        // Notify that the task data has changed
+                        final Drawable newIcon = loadIcon;
+                        final Bitmap newThumbnail = loadThumbnail;
+                        mMainThreadHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
+                            }
+                        });
                     }
                 }
 
@@ -296,7 +293,8 @@
 public class RecentsTaskLoader {
     static RecentsTaskLoader sInstance;
 
-    DrawableLruCache mIconCache;
+    SystemServicesProxy mSystemServicesProxy;
+    DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
@@ -304,7 +302,7 @@
     int mMaxThumbnailCacheSize;
     int mMaxIconCacheSize;
 
-    BitmapDrawable mDefaultIcon;
+    BitmapDrawable mDefaultApplicationIcon;
     Bitmap mDefaultThumbnail;
 
     /** Private Constructor */
@@ -324,11 +322,12 @@
                 "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
                 " iconCache: " + iconCacheSize);
 
-        // Initialize the cache and loaders
+        // Initialize the proxy, cache and loaders
+        mSystemServicesProxy = new SystemServicesProxy(context);
         mLoadQueue = new TaskResourceLoadQueue();
-        mIconCache = new DrawableLruCache(iconCacheSize);
+        mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
-        mLoader = new TaskResourceLoader(mLoadQueue, mIconCache, mThumbnailCache);
+        mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache);
 
         // Create the default assets
         Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
@@ -339,10 +338,10 @@
         c.setBitmap(mDefaultThumbnail);
         c.drawColor(0x00000000);
         c.setBitmap(null);
-        mDefaultIcon = new BitmapDrawable(context.getResources(), icon);
+        mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
         Console.log(Constants.DebugFlags.App.TaskDataLoader,
                 "[RecentsTaskLoader|defaultBitmaps]",
-                "icon: " + mDefaultIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+                "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
     }
 
     /** Initializes the recents task loader */
@@ -358,6 +357,11 @@
         return sInstance;
     }
 
+    /** Returns the system services proxy */
+    public SystemServicesProxy getSystemServicesProxy() {
+        return mSystemServicesProxy;
+    }
+
     /** Reload the set of recent tasks */
     SpaceNode reload(Context context, int preloadCount) {
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
@@ -367,142 +371,119 @@
         SpaceNode root = new SpaceNode(context);
         root.setStack(stack);
 
-        try {
-            long t1 = System.currentTimeMillis();
+        long t1 = System.currentTimeMillis();
 
-            PackageManager pm = context.getPackageManager();
-            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        // Get the recent tasks
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks =
+                ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
+        Collections.reverse(tasks);
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+                "[RecentsTaskLoader|getRecentTasks]",
+                "" + (System.currentTimeMillis() - t1) + "ms");
+        Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                "[RecentsTaskLoader|tasks]", "" + tasks.size());
 
-            // Get the recent tasks
-            List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(25,
-                    ActivityManager.RECENT_IGNORE_UNAVAILABLE |
-                    ActivityManager.RECENT_INCLUDE_RELATED, UserHandle.CURRENT.getIdentifier());
-            Collections.reverse(tasks);
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls,
-                    "[RecentsTaskLoader|getRecentTasks]",
-                    "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                    "[RecentsTaskLoader|tasks]", "" + tasks.size());
+        // Remove home/recents tasks
+        Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+        while (iter.hasNext()) {
+            ActivityManager.RecentTaskInfo t = iter.next();
 
-            // Remove home/recents tasks
-            Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
-            while (iter.hasNext()) {
-                ActivityManager.RecentTaskInfo t = iter.next();
-
-                // Skip tasks in the home stack
-                if (am.isInHomeStack(t.persistentId)) {
-                    iter.remove();
-                    continue;
-                }
-                // Skip tasks from this Recents package
-                if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
-                    iter.remove();
-                    continue;
-                }
+            // Skip tasks in the home stack
+            if (ssp.isInHomeStack(t.persistentId)) {
+                iter.remove();
+                continue;
             }
-
-            // Add each task to the task stack
-            t1 = System.currentTimeMillis();
-            int taskCount = tasks.size();
-            for (int i = 0; i < taskCount; i++) {
-                ActivityManager.RecentTaskInfo t = tasks.get(i);
-                ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
-                        PackageManager.GET_META_DATA);
-                String title = info.loadLabel(pm).toString();
-                boolean isForemostTask = (i == (taskCount - 1));
-
-                // Preload the specified number of apps
-                if (i >= (taskCount - preloadCount)) {
-                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                            "[RecentsTaskLoader|preloadTask]",
-                            "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
-
-                    String label = (t.activityLabel == null ? title : t.activityLabel.toString());
-                    BitmapDrawable bd = null;
-                    if (t.activityIcon != null) {
-                        bd = new BitmapDrawable(res, t.activityIcon);
-                    }
-                    Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
-
-                    // Load the icon (if possible and not the foremost task, from the cache)
-                    if (task.icon != null) {
-                        mIconCache.put(task.key, task.icon);
-                    } else {
-                        if (!isForemostTask) {
-                            task.icon = mIconCache.get(task.key);
-                            if (task.icon != null) {
-                                // Even though we get things from the cache, we should update them
-                                // if they've changed in the bg
-                                tasksToForceLoad.add(task);
-                            }
-                        }
-                        if (task.icon == null) {
-                            task.icon = info.loadIcon(pm);
-                            if (task.icon != null) {
-                                mIconCache.put(task.key, task.icon);
-                            } else {
-                                task.icon = mDefaultIcon;
-                            }
-                        }
-                    }
-
-                    // Load the thumbnail (if possible and not the foremost task, from the cache)
-                    if (!isForemostTask) {
-                        task.thumbnail = mThumbnailCache.get(task.key);
-                        if (task.thumbnail != null) {
-                            // Even though we get things from the cache, we should update them if
-                            // they've changed in the bg
-                            tasksToForceLoad.add(task);
-                        }
-                    }
-                    if (task.thumbnail == null) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "[RecentsTaskLoader|loadingTaskThumbnail]");
-                        task.thumbnail = am.getTaskTopThumbnail(t.id);
-                        if (task.thumbnail != null) {
-                            mThumbnailCache.put(task.key, task.thumbnail);
-                        } else {
-                            task.thumbnail = mDefaultThumbnail;
-                        }
-                    }
-
-                    // Create as many tasks a we want to multiply by
-                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
-                        stack.addTask(task);
-                    }
-                } else {
-                    // Create as many tasks a we want to multiply by
-                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
-                        stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
-                                null, null));
-                    }
-                }
+            // Skip tasks from this Recents package
+            if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
+                iter.remove();
+                continue;
             }
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls,
-                    "[RecentsTaskLoader|getAllTaskTopThumbnail]",
-                    "" + (System.currentTimeMillis() - t1) + "ms");
-
-            /*
-            // Get all the stacks
-            t1 = System.currentTimeMillis();
-            List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
-            Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
-            for (ActivityManager.StackInfo s : stackInfos) {
-                Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [RecentsTaskLoader|stack]", s.toString());
-                if (stacks.containsKey(s.stackId)) {
-                    stacks.get(s.stackId).setRect(s.bounds);
-                }
-            }
-            */
-        } catch (Exception e) {
-            e.printStackTrace();
         }
 
+        // Add each task to the task stack
+        t1 = System.currentTimeMillis();
+        int taskCount = tasks.size();
+        for (int i = 0; i < taskCount; i++) {
+            ActivityManager.RecentTaskInfo t = tasks.get(i);
+            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
+            String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
+                    t.activityLabel.toString());
+            Bitmap activityIcon = t.activityIcon;
+            boolean isForemostTask = (i == (taskCount - 1));
+
+            // Create a new task
+            Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
+                    activityIcon, t.userId);
+
+            // Preload the specified number of apps
+            if (i >= (taskCount - preloadCount)) {
+                Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                        "[RecentsTaskLoader|preloadTask]",
+                        "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+
+                // Load the icon (if possible and not the foremost task, from the cache)
+                if (!isForemostTask) {
+                    task.applicationIcon = mApplicationIconCache.get(task.key);
+                    if (task.applicationIcon != null) {
+                        // Even though we get things from the cache, we should update them
+                        // if they've changed in the bg
+                        tasksToForceLoad.add(task);
+                    }
+                }
+                if (task.applicationIcon == null) {
+                    task.applicationIcon = ssp.getActivityIcon(info);
+                    if (task.applicationIcon != null) {
+                        mApplicationIconCache.put(task.key, task.applicationIcon);
+                    } else {
+                        task.applicationIcon = mDefaultApplicationIcon;
+                    }
+                }
+
+                // Load the thumbnail (if possible and not the foremost task, from the cache)
+                if (!isForemostTask) {
+                    task.thumbnail = mThumbnailCache.get(task.key);
+                    if (task.thumbnail != null) {
+                        // Even though we get things from the cache, we should update them if
+                        // they've changed in the bg
+                        tasksToForceLoad.add(task);
+                    }
+                }
+                if (task.thumbnail == null) {
+                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                            "[RecentsTaskLoader|loadingTaskThumbnail]");
+                    task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+                    if (task.thumbnail != null) {
+                        mThumbnailCache.put(task.key, task.thumbnail);
+                    } else {
+                        task.thumbnail = mDefaultThumbnail;
+                    }
+                }
+            }
+
+            // Add the task to the stack
+            Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+            stack.addTask(task);
+        }
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+                "[RecentsTaskLoader|getAllTaskTopThumbnail]",
+                "" + (System.currentTimeMillis() - t1) + "ms");
+
+        /*
+        // Get all the stacks
+        t1 = System.currentTimeMillis();
+        List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
+        Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
+        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+        for (ActivityManager.StackInfo s : stackInfos) {
+            Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [RecentsTaskLoader|stack]", s.toString());
+            if (stacks.containsKey(s.stackId)) {
+                stacks.get(s.stackId).setRect(s.bounds);
+            }
+        }
+        */
+
         // Start the task loader
         mLoader.start(context);
 
@@ -516,16 +497,16 @@
 
     /** Acquires the task resource data from the pool. */
     public void loadTaskData(Task t) {
-        Drawable icon = mIconCache.get(t.key);
+        Drawable applicationIcon = mApplicationIconCache.get(t.key);
         Bitmap thumbnail = mThumbnailCache.get(t.key);
 
         Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
-                t + " icon: " + icon + " thumbnail: " + thumbnail +
+                t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
                         " thumbnailCacheSize: " + mThumbnailCache.size());
 
         boolean requiresLoad = false;
-        if (icon == null) {
-            icon = mDefaultIcon;
+        if (applicationIcon == null) {
+            applicationIcon = mDefaultApplicationIcon;
             requiresLoad = true;
         }
         if (thumbnail == null) {
@@ -535,7 +516,7 @@
         if (requiresLoad) {
             mLoadQueue.addTask(t, false);
         }
-        t.notifyTaskDataLoaded(thumbnail, icon, false);
+        t.notifyTaskDataLoaded(thumbnail, applicationIcon, false);
     }
 
     /** Releases the task resource data back into the pool. */
@@ -545,7 +526,7 @@
                 " thumbnailCacheSize: " + mThumbnailCache.size());
 
         mLoadQueue.removeTask(t);
-        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon);
+        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
     }
 
     /** Completely removes the resource data from the pool. */
@@ -555,8 +536,8 @@
 
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
-        mIconCache.remove(t.key);
-        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon);
+        mApplicationIconCache.remove(t.key);
+        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
     }
 
     /** Stops the task loader and clears all pending tasks */
@@ -579,19 +560,19 @@
             case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                 // We are leaving recents, so trim the data a bit
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
-                mIconCache.trimToSize(mMaxIconCacheSize / 2);
+                mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                 // We are going to be low on memory
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
-                mIconCache.trimToSize(mMaxIconCacheSize / 4);
+                mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                 // We are low on memory, so release everything
                 mThumbnailCache.evictAll();
-                mIconCache.evictAll();
+                mApplicationIconCache.evictAll();
                 break;
             default:
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
new file mode 100644
index 0000000..efcd948
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Acts as a shim around the real system services that we need to access data from, and provides
+ * a point of injection when testing UI.
+ */
+public class SystemServicesProxy {
+    ActivityManager mAm;
+    PackageManager mPm;
+    String mPackage;
+
+    Bitmap mDummyIcon;
+
+    /** Private constructor */
+    public SystemServicesProxy(Context context) {
+        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        mPm = context.getPackageManager();
+        mPackage = context.getPackageName();
+
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            // Create a dummy icon
+            mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(mDummyIcon);
+            c.drawColor(0xFF999999);
+            c.setBitmap(null);
+        }
+    }
+
+    /** Returns a list of the recents tasks */
+    public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+        if (mAm == null) return null;
+
+        // If we are mocking, then create some recent tasks
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            ArrayList<ActivityManager.RecentTaskInfo> tasks =
+                    new ArrayList<ActivityManager.RecentTaskInfo>();
+            int count = Math.min(numTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
+            for (int i = 0; i < count; i++) {
+                // Create a dummy component name
+                int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
+                ComponentName cn = new ComponentName("com.android.test" + packageIndex,
+                        "com.android.test" + i + ".Activity");
+                // Create the recent task info
+                ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+                rti.id = rti.persistentId = i;
+                rti.baseIntent = new Intent();
+                rti.baseIntent.setComponent(cn);
+                rti.description = rti.activityLabel = "" + i + " - " +
+                        Long.toString(Math.abs(new Random().nextLong()), 36);
+                if (i % 2 == 0) {
+                    rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
+                }
+                tasks.add(rti);
+            }
+            return tasks;
+        }
+
+        return mAm.getRecentTasksForUser(numTasks,
+                ActivityManager.RECENT_IGNORE_UNAVAILABLE |
+                ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+    }
+
+    /** Returns a list of the running tasks */
+    public List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
+        if (mAm == null) return null;
+        return mAm.getRunningTasks(numTasks);
+    }
+
+    /** Returns whether the specified task is in the home stack */
+    public boolean isInHomeStack(int taskId) {
+        if (mAm == null) return false;
+
+        // If we are mocking, then just return false
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return false;
+        }
+
+        return mAm.isInHomeStack(taskId);
+    }
+
+    /** Returns the top task thumbnail for the given task id */
+    public Bitmap getTaskThumbnail(int taskId) {
+        if (mAm == null) return null;
+
+        // If we are mocking, then just return a dummy thumbnail
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(thumbnail);
+            c.drawColor(0xff333333);
+            c.setBitmap(null);
+            return thumbnail;
+        }
+
+        return mAm.getTaskTopThumbnail(taskId);
+    }
+
+    /** Moves a task to the front with the specified activity options */
+    public void moveTaskToFront(int taskId, ActivityOptions opts) {
+        if (mAm == null) return;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+        if (opts != null) {
+            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
+                    opts.toBundle());
+        } else {
+            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
+        }
+    }
+
+    /** Removes the task and kills the process */
+    public void removeTask(int taskId) {
+        if (mAm == null) return;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+        mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+    }
+
+    /** Returns the activity info for a given component name */
+    public ActivityInfo getActivityInfo(ComponentName cn) {
+        if (mPm == null) return null;
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
+
+        try {
+            return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /** Returns the activity label */
+    public String getActivityLabel(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock label
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return "Recent Task";
+        }
+
+        return info.loadLabel(mPm).toString();
+    }
+
+    /** Returns the activity icon */
+    public Drawable getActivityIcon(ActivityInfo info) {
+        if (mPm == null) return null;
+
+        // If we are mocking, then return a mock label
+        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+            return new ColorDrawable(0xFF666666);
+        }
+
+        return info.loadIcon(mPm);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 33e4246..4a1b3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,8 +20,18 @@
 
 /* Common code */
 public class Utilities {
-    public static final Rect tmpRect = new Rect();
-    public static final Rect tmpRect2 = new Rect();
+    /**
+     * Calculates a consistent animation duration (ms) for all animations depending on the movement
+     * of the object being animated.
+     */
+    public static int calculateTranslationAnimationDuration(int distancePx) {
+        return calculateTranslationAnimationDuration(distancePx, 100);
+    }
+    public static int calculateTranslationAnimationDuration(int distancePx, int minDuration) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        return Math.max(minDuration, (int) (1000f /* ms/s */ *
+                (Math.abs(distancePx) / config.animationPxMovementPerSecond)));
+    }
 
     /** Scales a rect about its centroid */
     public static void scaleRectAboutCenter(Rect r, float scale) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index cda4ab2..a0ff3b7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -19,7 +19,6 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import com.android.systemui.recents.Constants;
 
 
 /**
@@ -37,11 +36,11 @@
     /* The Task Key represents the unique primary key for the task */
     public static class TaskKey {
         public final int id;
-        public final Intent intent;
+        public final Intent baseIntent;
 
         public TaskKey(int id, Intent intent) {
             this.id = id;
-            this.intent = intent;
+            this.baseIntent = intent;
         }
 
         @Override
@@ -56,29 +55,27 @@
 
         @Override
         public String toString() {
-            return "Task.Key: " + id + ", " + intent.getComponent().getPackageName();
+            return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
         }
     }
 
     public TaskKey key;
-    public String title;
-    public Drawable icon;
+    public Drawable applicationIcon;
+    public String activityLabel;
+    public Bitmap activityIcon;
     public Bitmap thumbnail;
     public boolean isActive;
+    public int userId;
 
     TaskCallbacks mCb;
 
-    public Task(int id, boolean isActive, Intent intent, String activityTitle, Drawable icon) {
-        this(id, isActive, intent, activityTitle, icon, null);
-    }
-
-    public Task(int id, boolean isActive, Intent intent, String activityTitle, Drawable icon,
-                Bitmap thumbnail) {
+    public Task(int id, boolean isActive, Intent intent, String activityTitle,
+                Bitmap activityIcon, int userId) {
         this.key = new TaskKey(id, intent);
-        this.title = activityTitle;
-        this.icon = icon;
-        this.thumbnail = thumbnail;
+        this.activityLabel = activityTitle;
+        this.activityIcon = activityIcon;
         this.isActive = isActive;
+        this.userId = userId;
     }
 
     /** Set the callbacks */
@@ -87,8 +84,9 @@
     }
 
     /** Notifies the callback listeners that this task has been loaded */
-    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable icon, boolean reloadingTaskData) {
-        this.icon = icon;
+    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon,
+                                     boolean reloadingTaskData) {
+        this.applicationIcon = applicationIcon;
         this.thumbnail = thumbnail;
         if (mCb != null) {
             mCb.onTaskDataLoaded(reloadingTaskData);
@@ -96,8 +94,8 @@
     }
 
     /** Notifies the callback listeners that this task has been unloaded */
-    public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) {
-        icon = defaultIcon;
+    public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultApplicationIcon) {
+        applicationIcon = defaultApplicationIcon;
         thumbnail = defaultThumbnail;
         if (mCb != null) {
             mCb.onTaskDataUnloaded();
@@ -106,20 +104,13 @@
 
     @Override
     public boolean equals(Object o) {
-        // If we have multiple task entries for the same task, then we do the simple object
-        // equality check
-        if (Constants.Values.RecentsTaskLoader.TaskEntryMultiplier > 1) {
-            return super.equals(o);
-        }
-
-        // Otherwise, check that the id and intent match (the other fields can be asynchronously
-        // loaded and is unsuitable to testing the identity of this Task)
+        // Check that the id matches
         Task t = (Task) o;
         return key.equals(t.key);
     }
 
     @Override
     public String toString() {
-        return "Task: " + key.intent.getComponent().getPackageName() + " [" + super.toString() + "]";
+        return "Task: " + key.baseIntent.getComponent().getPackageName() + " [" + super.toString() + "]";
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index f2f89ae3..a0e5b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -39,9 +39,11 @@
     TaskFilter mFilter;
 
     /** Sets the task filter, saving the current touch state */
-    void setFilter(TaskFilter filter) {
+    boolean setFilter(TaskFilter filter) {
+        ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks);
         mFilter = filter;
         updateFilteredTasks();
+        return !prevFilteredTasks.equals(mFilteredTasks);
     }
 
     /** Removes the task filter and returns the previous touch state */
@@ -126,9 +128,9 @@
         /* Notifies when a task has been removed from the stack */
         public void onStackTaskRemoved(TaskStack stack, Task t);
         /** Notifies when the stack was filtered */
-        public void onStackFiltered(TaskStack stack);
+        public void onStackFiltered(TaskStack newStack, ArrayList<Task> curStack, Task t);
         /** Notifies when the stack was un-filtered */
-        public void onStackUnfiltered(TaskStack stack);
+        public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curStack);
     }
 
     Context mContext;
@@ -201,29 +203,30 @@
     }
 
     /** Filters the stack into tasks similar to the one specified */
-    public void filterTasks(Task t) {
+    public void filterTasks(final Task t) {
+        ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
         // Set the task list filter
-        // XXX: This is a dummy filter that currently just accepts every other task.
-        mTaskList.setFilter(new TaskFilter() {
+        boolean filtered = mTaskList.setFilter(new TaskFilter() {
             @Override
-            public boolean acceptTask(Task t, int i) {
-                if (i % 2 == 0) {
-                    return true;
-                }
-                return false;
+            public boolean acceptTask(Task at, int i) {
+                return t.key.baseIntent.getComponent().getPackageName().equals(
+                        at.key.baseIntent.getComponent().getPackageName());
             }
         });
-        if (mCb != null) {
-            mCb.onStackFiltered(this);
+        if (filtered && mCb != null) {
+            mCb.onStackFiltered(this, oldStack, t);
         }
     }
 
     /** Unfilters the current stack */
     public void unfilterTasks() {
+        ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
         // Unset the filter, then update the virtual scroll
         mTaskList.removeFilter();
         if (mCb != null) {
-            mCb.onStackUnfiltered(this);
+            mCb.onStackUnfiltered(this, oldStack);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index cc85439..1ebe231 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recents.views;
 
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -30,6 +29,7 @@
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsTaskLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
@@ -211,17 +211,18 @@
                 View sourceView = tv;
                 int offsetX = 0;
                 int offsetY = 0;
+                int stackScroll = stackView.getStackScroll();
                 if (tv == null) {
                     // If there is no actual task view, then use the stack view as the source view
                     // and then offset to the expected transform rect, but bound this to just
                     // outside the display rect (to ensure we don't animate from too far away)
                     RecentsConfiguration config = RecentsConfiguration.getInstance();
                     sourceView = stackView;
-                    transform = stackView.getStackTransform(stack.indexOfTask(task));
+                    transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
                     offsetX = transform.rect.left;
                     offsetY = Math.min(transform.rect.top, config.displayRect.height());
                 } else {
-                    transform = stackView.getStackTransform(stack.indexOfTask(task));
+                    transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
                 }
 
                 // Compute the thumbnail to scale up from
@@ -245,26 +246,20 @@
 
                 if (task.isActive) {
                     // Bring an active task to the foreground
-                    ActivityManager am = (ActivityManager)
-                            stackView.getContext().getSystemService(Context.ACTIVITY_SERVICE);
-                    if (opts != null) {
-                        am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME,
-                                opts.toBundle());
-                    } else {
-                        am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME);
-                    }
+                    RecentsTaskLoader.getInstance().getSystemServicesProxy()
+                            .moveTaskToFront(task.key.id, opts);
                 } else {
                     // Launch the activity with the desired animation
-                    Intent i = new Intent(task.key.intent);
+                    Intent i = new Intent(task.key.baseIntent);
                     i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                             | Intent.FLAG_ACTIVITY_TASK_ON_HOME
                             | Intent.FLAG_ACTIVITY_NEW_TASK);
                     try {
                         if (opts != null) {
                             getContext().startActivityAsUser(i, opts.toBundle(),
-                                    UserHandle.CURRENT);
+                                    new UserHandle(task.userId));
                         } else {
-                            getContext().startActivityAsUser(i, UserHandle.CURRENT);
+                            getContext().startActivityAsUser(i, new UserHandle(task.userId));
                         }
                     } catch (ActivityNotFoundException anfe) {
                         Console.logError(getContext(), "Could not start 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 235c6cc..c9a6d67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -17,21 +17,12 @@
 package com.android.systemui.recents.views;
 
 import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Typeface;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.model.Task;
 
 
@@ -39,6 +30,7 @@
 class TaskBarView extends FrameLayout {
     Task mTask;
 
+    ImageView mApplicationIcon;
     ImageView mActivityIcon;
     TextView mActivityDescription;
 
@@ -61,6 +53,7 @@
     @Override
     protected void onFinishInflate() {
         // Initialize the icon and description views
+        mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
         mActivityIcon = (ImageView) findViewById(R.id.activity_icon);
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
     }
@@ -68,9 +61,13 @@
     /** Binds the bar view to the task */
     void rebindToTask(Task t, boolean animate) {
         mTask = t;
-        if (t.icon != null) {
-            mActivityIcon.setImageDrawable(t.icon);
-            mActivityDescription.setText(t.title);
+        if (t.applicationIcon != null) {
+            mApplicationIcon.setImageDrawable(t.applicationIcon);
+            mActivityDescription.setText(t.activityLabel);
+            if (t.activityIcon != null) {
+                mActivityIcon.setImageBitmap(t.activityIcon);
+                mActivityIcon.setVisibility(View.VISIBLE);
+            }
             if (animate) {
                 // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
             }
@@ -80,7 +77,9 @@
     /** Unbinds the bar view from the task */
     void unbindFromTask() {
         mTask = null;
-        mActivityIcon.setImageDrawable(null);
+        mApplicationIcon.setImageDrawable(null);
+        mActivityIcon.setImageBitmap(null);
+        mActivityIcon.setVisibility(View.INVISIBLE);
         mActivityDescription.setText("");
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index e7f517f..fa06764 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -18,10 +18,10 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -34,6 +34,8 @@
 import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.OverScroller;
+import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -41,7 +43,6 @@
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
 
 import java.util.ArrayList;
 
@@ -71,14 +72,21 @@
     int mStackScroll;
     int mMinScroll;
     int mMaxScroll;
+    int mStashedScroll;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
 
+    // Filtering
+    AnimatorSet mFilterChildrenAnimator;
+
     // Optimizations
     int mHwLayersRefCount;
     int mStackViewsAnimationDuration;
     boolean mStackViewsDirty = true;
     boolean mAwaitingFirstLayout = true;
+    int[] mTmpVisibleRange = new int[2];
+    Rect mTmpRect = new Rect();
+    Rect mTmpRect2 = new Rect();
     LayoutInflater mInflater;
 
     public TaskStackView(Context context, TaskStack stack) {
@@ -102,7 +110,7 @@
     }
     void requestSynchronizeStackViewsWithModel(int duration) {
         Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
-                "[TaskStackView|requestSynchronize]", "", Console.AnsiYellow);
+                "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
         if (!mStackViewsDirty) {
             invalidate();
         }
@@ -128,14 +136,17 @@
     }
 
     /** Update/get the transform */
-    public TaskViewTransform getStackTransform(int indexInStack) {
+    public TaskViewTransform getStackTransform(int indexInStack, int stackScroll) {
         TaskViewTransform transform = new TaskViewTransform();
 
-        // Map the items to an continuous position relative to the current scroll
+        // Return early if we have an invalid index
+        if (indexInStack < 0) return transform;
+
+        // Map the items to an continuous position relative to the specified scroll
         int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
         float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
         float peekHeight = Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
-        float t = ((indexInStack * overlapHeight) - getStackScroll()) / overlapHeight;
+        float t = ((indexInStack * overlapHeight) - stackScroll) / overlapHeight;
         float boundedT = Math.max(t, -(numPeekCards + 1));
 
         // Set the scale relative to its position
@@ -167,25 +178,62 @@
         return transform;
     }
 
+    /**
+     * Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
+     */
+    private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
+                                                            int stackScroll,
+                                                            int[] visibleRangeOut,
+                                                            boolean boundTranslationsToRect) {
+        // XXX: Optimization: Use binary search to find the visible range
+
+        ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
+        int taskCount = tasks.size();
+        int firstVisibleIndex = -1;
+        int lastVisibleIndex = -1;
+        for (int i = 0; i < taskCount; i++) {
+            TaskViewTransform transform = getStackTransform(i, stackScroll);
+            taskTransforms.add(transform);
+            if (transform.visible) {
+                if (firstVisibleIndex < 0) {
+                    firstVisibleIndex = i;
+                }
+                lastVisibleIndex = i;
+            }
+
+            if (boundTranslationsToRect) {
+                transform.translationY = Math.min(transform.translationY, mRect.bottom);
+            }
+        }
+        if (visibleRangeOut != null) {
+            visibleRangeOut[0] = firstVisibleIndex;
+            visibleRangeOut[1] = lastVisibleIndex;
+        }
+        return taskTransforms;
+    }
+
     /** Synchronizes the views with the model */
     void synchronizeStackViewsWithModel() {
         Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
                 "[TaskStackView|synchronizeViewsWithModel]",
                 "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
         if (mStackViewsDirty) {
-
-            // XXX: Optimization: Use binary search to find the visible range
-            // XXX: Optimize to not call getStackTransform() so many times
             // XXX: Consider using TaskViewTransform pool to prevent allocations
             // XXX: Iterate children views, update transforms and remove all that are not visible
             //      For all remaining tasks, update transforms and if visible add the view
 
-            // Update the visible state of all the tasks
+            // Get all the task transforms
+            int[] visibleRange = mTmpVisibleRange;
+            int stackScroll = getStackScroll();
             ArrayList<Task> tasks = mStack.getTasks();
+            ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
+                    visibleRange, false);
+
+            // Update the visible state of all the tasks
             int taskCount = tasks.size();
             for (int i = 0; i < taskCount; i++) {
                 Task task = tasks.get(i);
-                TaskViewTransform transform = getStackTransform(i);
+                TaskViewTransform transform = taskTransforms.get(i);
                 TaskView tv = getChildViewForTask(task);
 
                 if (transform.visible) {
@@ -194,11 +242,10 @@
                         // When we are picking up a new view from the view pool, prepare it for any
                         // following animation by putting it in a reasonable place
                         if (mStackViewsAnimationDuration > 0 && i != 0) {
-                            // XXX: We have to animate when filtering, etc. Maybe we should have a
-                            //      runnable that ensures that tasks are animated in a special way
-                            //      when they are entering the scene?
-                            int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
-                            tv.updateViewPropertiesFromTask(null, getStackTransform(fromIndex), 0);
+                            int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
+                                    (visibleRange[1] + 1);
+                            tv.updateViewPropertiesToTaskTransform(null,
+                                    getStackTransform(fromIndex, stackScroll), 0);
                         }
                     }
                 } else {
@@ -208,17 +255,18 @@
                 }
             }
 
-            // Update all the current view children
+            // Update all the remaining view children
             // NOTE: We have to iterate in reverse where because we are removing views directly
             int childCount = getChildCount();
             for (int i = childCount - 1; i >= 0; i--) {
                 TaskView tv = (TaskView) getChildAt(i);
                 Task task = tv.getTask();
-                TaskViewTransform transform = getStackTransform(mStack.indexOfTask(task));
-                if (!transform.visible) {
+                int taskIndex = mStack.indexOfTask(task);
+                if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
                     mViewPool.returnViewToPool(tv);
                 } else {
-                    tv.updateViewPropertiesFromTask(null, transform, mStackViewsAnimationDuration);
+                    tv.updateViewPropertiesToTaskTransform(null, taskTransforms.get(taskIndex),
+                            mStackViewsAnimationDuration);
                 }
             }
 
@@ -235,6 +283,10 @@
         mStackScroll = value;
         requestSynchronizeStackViewsWithModel();
     }
+    /** Sets the current stack scroll without synchronizing the stack view with the model */
+    public void setStackScrollRaw(int value) {
+        mStackScroll = value;
+    }
 
     /** Gets the current stack scroll */
     public int getStackScroll() {
@@ -242,7 +294,7 @@
     }
 
     /** Animates the stack scroll into bounds */
-    ObjectAnimator animateBoundScroll(int duration) {
+    ObjectAnimator animateBoundScroll() {
         int curScroll = getStackScroll();
         int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
         if (newScroll != curScroll) {
@@ -251,36 +303,41 @@
 
             // Abort any current animations
             abortScroller();
-            if (mScrollAnimator != null) {
-                mScrollAnimator.cancel();
-                mScrollAnimator.removeAllListeners();
-            }
+            abortBoundScrollAnimation();
 
             // Start a new scroll animation
-            mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
-            mScrollAnimator.setDuration(duration);
-            mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    setStackScroll((Integer) animation.getAnimatedValue());
-                }
-            });
-            mScrollAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    // Disable hw layers on the stack
-                    decHwLayersRefCount("animateBoundScroll");
-                }
-            });
+            animateScroll(curScroll, newScroll);
             mScrollAnimator.start();
         }
         return mScrollAnimator;
     }
 
+    /** Animates the stack scroll */
+    void animateScroll(int curScroll, int newScroll) {
+        mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
+        mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
+                curScroll, 250));
+        mScrollAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+        mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                setStackScroll((Integer) animation.getAnimatedValue());
+            }
+        });
+        mScrollAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Disable hw layers on the stack
+                decHwLayersRefCount("animateBoundScroll");
+            }
+        });
+    }
+
     /** Aborts any current stack scrolls */
     void abortBoundScrollAnimation() {
         if (mScrollAnimator != null) {
             mScrollAnimator.cancel();
+            mScrollAnimator.removeAllListeners();
         }
     }
 
@@ -304,6 +361,20 @@
         return false;
     }
 
+    /**
+     * Bounds the current scroll if necessary, but does not synchronize the stack view with the
+     * model.
+     */
+    public boolean boundScrollRaw() {
+        int curScroll = getStackScroll();
+        int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
+        if (newScroll != curScroll) {
+            setStackScrollRaw(newScroll);
+            return true;
+        }
+        return false;
+    }
+
     /** Returns whether the current scroll is out of bounds */
     boolean isScrollOutOfBounds() {
         return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
@@ -404,12 +475,12 @@
             TaskView tv = (TaskView) child;
             TaskView nextTv = null;
             int curIndex = indexOfChild(tv);
-            if (curIndex < (getChildCount() - 1)) {
+            if ((curIndex > -1) && (curIndex < (getChildCount() - 1))) {
                 // Clip against the next view (if we aren't animating its alpha)
                 nextTv = (TaskView) getChildAt(curIndex + 1);
                 if (nextTv.getAlpha() == 1f) {
-                    Rect curRect = tv.getClippingRect(Utilities.tmpRect, false);
-                    Rect nextRect = nextTv.getClippingRect(Utilities.tmpRect2, true);
+                    Rect curRect = tv.getClippingRect(mTmpRect, false);
+                    Rect nextRect = nextTv.getClippingRect(mTmpRect2, true);
                     RecentsConfiguration config = RecentsConfiguration.getInstance();
                     // The hit rects are relative to the task view, which needs to be offset by the
                     // system bar height
@@ -528,9 +599,7 @@
                     mTaskRect.right, mStackRectSansPeek.top + mTaskRect.height());
         }
 
-        if (!mAwaitingFirstLayout) {
-            requestSynchronizeStackViewsWithModel();
-        } else {
+        if (mAwaitingFirstLayout) {
             mAwaitingFirstLayout = false;
         }
     }
@@ -566,17 +635,277 @@
         }
 
         updateMinMaxScroll(true);
-        requestSynchronizeStackViewsWithModel(Constants.Values.TaskStackView.Animation.TaskRemovedReshuffleDuration);
+        int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
+        requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
     }
 
     @Override
-    public void onStackFiltered(TaskStack stack) {
-        requestSynchronizeStackViewsWithModel();
+    public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curStack,
+                                Task filteredTask) {
+        // NOTE: This code assumes that the current (unfiltered) stack is a superset of the new
+        // (filtered) stack
+        // XXX: Use HW Layers
+
+        // Stash the scroll and filtered task for us to restore to when we unfilter
+        mStashedScroll = getStackScroll();
+
+        // Compute the transforms of the items in the current stack
+        final ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curStack, mStashedScroll, null, true);
+
+        // Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
+        updateMinMaxScroll(false);
+        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+        setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack after setting the new scroll
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
+
+        // Animate all of the existing views on screen either out of view (if they are not visible
+        // in the new stack) or to their final positions in the new stack
+        final ArrayList<TaskView> childrenToReturnToPool = new ArrayList<TaskView>();
+        final ArrayList<Task> tasks = mStack.getTasks();
+        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+        int childCount = getChildCount();
+        int movement = 0;
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            Task task = tv.getTask();
+            TaskViewTransform toTransform;
+            int taskIndex = tasks.indexOf(task);
+
+            boolean willBeInvisible = (taskIndex < 0) || !taskTransforms.get(taskIndex).visible;
+            if (willBeInvisible) {
+                // Compose a new transform that fades and slides the task out of view
+                TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
+                toTransform = new TaskViewTransform(fromTransform);
+                tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+                tv.prepareTaskTransformForFilterTaskHidden(toTransform);
+
+                childrenToReturnToPool.add(tv);
+            } else {
+                toTransform = taskTransforms.get(taskIndex);
+
+                // Use the movement of the visible views to calculate the duration of the animation
+                movement = Math.max(movement,
+                        Math.abs(toTransform.translationY - (int) tv.getTranslationY()));
+            }
+            childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+        }
+
+        // Cancel the previous animation
+        if (mFilterChildrenAnimator != null) {
+            mFilterChildrenAnimator.cancel();
+            mFilterChildrenAnimator.removeAllListeners();
+        }
+
+        // Create a new animation for the existing children
+        final RecentsConfiguration config = RecentsConfiguration.getInstance();
+        mFilterChildrenAnimator = new AnimatorSet();
+        mFilterChildrenAnimator.setDuration(
+                Utilities.calculateTranslationAnimationDuration(movement,
+                        config.filteringCurrentViewsMinAnimDuration));
+        mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+        mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+            boolean isCancelled;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                isCancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (isCancelled) return;
+
+                // Return all the removed children to the view pool
+                for (TaskView tv : childrenToReturnToPool) {
+                    mViewPool.returnViewToPool(tv);
+                }
+
+                // For views that are not already visible, animate them in
+                ArrayList<Animator> newViewsAnims = new ArrayList<Animator>();
+                int taskCount = tasks.size();
+                int movement = 0;
+                int offset = 0;
+                for (int i = 0; i < taskCount; i++) {
+                    Task task = tasks.get(i);
+                    TaskViewTransform toTransform = taskTransforms.get(i);
+                    if (toTransform.visible) {
+                        TaskViewTransform fromTransform =
+                                curTaskTransforms.get(curStack.indexOf(task));
+                        TaskView tv = getChildViewForTask(task);
+                        if (tv == null) {
+                            tv = mViewPool.pickUpViewFromPool(task, task);
+                            // Compose a new transform that fades and slides the new task in
+                            fromTransform = new TaskViewTransform(toTransform);
+                            tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+                            tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+
+                            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+                            anim.setStartDelay(offset *
+                                    Constants.Values.TaskStackView.FilterStartDelay);
+                            newViewsAnims.add(anim);
+
+                            // Use the movement of the newly visible views to calculate the duration
+                            // of the animation
+                            movement = Math.max(movement, Math.abs(toTransform.translationY -
+                                    fromTransform.translationY));
+                            offset++;
+                        }
+                    }
+
+                    // Animate the new views in
+                    mFilterChildrenAnimator = new AnimatorSet();
+                    mFilterChildrenAnimator.setDuration(
+                            Utilities.calculateTranslationAnimationDuration(movement,
+                                    config.filteringNewViewsMinAnimDuration));
+                    mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+                    mFilterChildrenAnimator.playTogether(newViewsAnims);
+                    mFilterChildrenAnimator.start();
+                }
+                invalidate();
+            }
+        });
+        mFilterChildrenAnimator.playTogether(childViewAnims);
+        mFilterChildrenAnimator.start();
     }
 
     @Override
-    public void onStackUnfiltered(TaskStack stack) {
-        requestSynchronizeStackViewsWithModel();
+    public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curStack) {
+        // Compute the transforms of the items in the current stack
+        final int curScroll = getStackScroll();
+        final ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curStack, curScroll, null, true);
+
+        // Restore the stashed scroll
+        updateMinMaxScroll(false);
+        setStackScrollRaw(mStashedScroll);
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack after restoring the stashed scroll
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
+
+        // Animate all of the existing views out of view (if they are not in the visible range in
+        // the new stack) or to their final positions in the new stack
+        final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
+        final ArrayList<Task> tasks = mStack.getTasks();
+        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+        int childCount = getChildCount();
+        int movement = 0;
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            Task task = tv.getTask();
+            int taskIndex = tasks.indexOf(task);
+            TaskViewTransform toTransform;
+
+            // If the view is no longer visible, then we should just animate it out
+            boolean willBeInvisible = taskIndex < 0 || !taskTransforms.get(taskIndex).visible;
+            if (willBeInvisible) {
+                toTransform = new TaskViewTransform(taskTransforms.get(taskIndex));
+                tv.prepareTaskTransformForFilterTaskVisible(toTransform);
+                childrenToRemove.add(tv);
+            } else {
+                toTransform = taskTransforms.get(taskIndex);
+                // Use the movement of the visible views to calculate the duration of the animation
+                movement = Math.max(movement, Math.abs(toTransform.translationY -
+                        (int) tv.getTranslationY()));
+            }
+
+            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+            childViewAnims.add(anim);
+        }
+
+        // Cancel the previous animation
+        if (mFilterChildrenAnimator != null) {
+            mFilterChildrenAnimator.cancel();
+            mFilterChildrenAnimator.removeAllListeners();
+        }
+
+        // Create a new animation for the existing children
+        final RecentsConfiguration config = RecentsConfiguration.getInstance();
+        mFilterChildrenAnimator = new AnimatorSet();
+        mFilterChildrenAnimator.setDuration(
+                Utilities.calculateTranslationAnimationDuration(movement,
+                        config.filteringCurrentViewsMinAnimDuration));
+        mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+        mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+            boolean isCancelled;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                isCancelled = true;
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (isCancelled) return;
+
+                // Return all the removed children to the view pool
+                for (TaskView tv : childrenToRemove) {
+                    mViewPool.returnViewToPool(tv);
+                }
+
+                // Increment the hw layers ref count
+                addHwLayersRefCount("unfilteredNewViews");
+
+                // For views that are not already visible, animate them in
+                ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
+                int taskCount = tasks.size();
+                int movement = 0;
+                int offset = 0;
+                for (int i = 0; i < taskCount; i++) {
+                    Task task = tasks.get(i);
+                    TaskViewTransform toTransform = taskTransforms.get(i);
+                    if (toTransform.visible) {
+                        TaskView tv = getChildViewForTask(task);
+                        if (tv == null) {
+                            // For views that are not already visible, animate them in
+                            tv = mViewPool.pickUpViewFromPool(task, task);
+
+                            // Compose a new transform to fade and slide the new task in
+                            TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
+                            tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+                            tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+
+                            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+                            anim.setStartDelay(offset *
+                                    Constants.Values.TaskStackView.FilterStartDelay);
+                            newViewAnims.add(anim);
+                            // Use the movement of the newly visible views to calculate the duration
+                            // of the animation
+                            movement = Math.max(movement,
+                                    Math.abs(toTransform.translationY - fromTransform.translationY));
+                            offset++;
+                        }
+                    }
+                }
+
+                // Run the animation
+                mFilterChildrenAnimator = new AnimatorSet();
+                mFilterChildrenAnimator.setDuration(
+                        Utilities.calculateTranslationAnimationDuration(movement,
+                                config.filteringNewViewsMinAnimDuration));
+                mFilterChildrenAnimator.playTogether(newViewAnims);
+                mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        // Decrement the hw layers ref count
+                        decHwLayersRefCount("unfilteredNewViews");
+                    }
+                });
+                mFilterChildrenAnimator.start();
+                invalidate();
+            }
+        });
+        mFilterChildrenAnimator.playTogether(childViewAnims);
+        mFilterChildrenAnimator.start();
+
+        // Clear the saved vars
+        mStashedScroll = 0;
     }
 
     /**** ViewPoolConsumer Implementation ****/
@@ -825,7 +1154,7 @@
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP: {
                 // Animate the scroll back if we've cancelled
-                mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+                mSv.animateBoundScroll();
                 // Disable HW layers
                 if (mIsScrolling) {
                     mSv.decHwLayersRefCount("stackScroll");
@@ -845,7 +1174,7 @@
 
     /** Handles touch events once we have intercepted them */
     public boolean onTouchEvent(MotionEvent ev) {
-        Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
+        Console.log(Constants.DebugFlags.UI.TouchEvents,
                 "[TaskStackViewTouchHandler|touchEvent]",
                 Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
 
@@ -955,7 +1284,7 @@
                 } else if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
                     // XXX: Make this animation a function of the velocity OR distance
-                    mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+                    mSv.animateBoundScroll();
                 }
 
                 if (mIsScrolling) {
@@ -989,7 +1318,7 @@
                 if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
                     // XXX: Make this animation a function of the velocity OR distance
-                    mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+                    mSv.animateBoundScroll();
                 }
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
@@ -1038,16 +1367,19 @@
         loader.deleteTaskData(task);
 
         // Remove the task from activity manager
-        final ActivityManager am = (ActivityManager)
-                activity.getSystemService(Context.ACTIVITY_SERVICE);
-        if (am != null) {
-            am.removeTask(tv.getTask().key.id,
-                    ActivityManager.REMOVE_TASK_KILL_PROCESS);
-        }
+        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
 
-        // If there are no remaining tasks, then just close the activity
+        // If there are no remaining tasks, then either unfilter the current stack, or just close
+        // the activity if there are no filtered stacks
         if (mSv.mStack.getTaskCount() == 0) {
-            activity.finish();
+            boolean shouldFinishActivity = true;
+            if (mSv.mStack.hasFilteredTasks()) {
+                mSv.mStack.unfilterTasks();
+                shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
+            }
+            if (shouldFinishActivity) {
+                activity.finish();
+            }
         }
 
         // Disable HW layers
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index c86b0e1..e99fecb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,21 +16,28 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 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;
 
+import java.util.Random;
+
 
 /* A task view */
 public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
@@ -72,6 +79,7 @@
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
+        mBarView.mApplicationIcon.setOnClickListener(this);
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
         }
@@ -90,12 +98,16 @@
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
+    protected void dispatchDraw(Canvas canvas) {
+        int restoreCount = 0;
         if (Constants.Values.TaskView.UseRoundedCorners) {
+            restoreCount = canvas.save();
             canvas.clipPath(mRoundedRectClipPath);
         }
-
-        super.onDraw(canvas);
+        super.dispatchDraw(canvas);
+        if (Constants.Values.TaskView.UseRoundedCorners) {
+            canvas.restoreToCount(restoreCount);
+        }
     }
 
     /** Set callback */
@@ -109,27 +121,43 @@
     }
 
     /** Synchronizes this view's properties with the task's transform */
-    void updateViewPropertiesFromTask(TaskViewTransform animateFromTransform,
-                                      TaskViewTransform transform, int duration) {
+    void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
+                                             TaskViewTransform toTransform, int duration) {
         if (duration > 0) {
             if (animateFromTransform != null) {
                 setTranslationY(animateFromTransform.translationY);
                 setScaleX(animateFromTransform.scale);
                 setScaleY(animateFromTransform.scale);
+                setAlpha(animateFromTransform.alpha);
             }
-            animate().translationY(transform.translationY)
-                    .scaleX(transform.scale)
-                    .scaleY(transform.scale)
+            animate().translationY(toTransform.translationY)
+                    .scaleX(toTransform.scale)
+                    .scaleY(toTransform.scale)
+                    .alpha(toTransform.alpha)
                     .setDuration(duration)
-                    .setInterpolator(new AccelerateDecelerateInterpolator())
+                    .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                    .withLayer()
                     .start();
         } else {
-            setTranslationY(transform.translationY);
-            setScaleX(transform.scale);
-            setScaleY(transform.scale);
+            setTranslationY(toTransform.translationY);
+            setScaleX(toTransform.scale);
+            setScaleY(toTransform.scale);
+            setAlpha(toTransform.alpha);
         }
     }
 
+    /** Returns an animator to animate this task to the specified transform */
+    Animator getAnimatorToTaskTransform(TaskViewTransform toTransform) {
+        AnimatorSet anims = new AnimatorSet();
+        anims.playTogether(
+                ObjectAnimator.ofFloat(this, "translationY", toTransform.translationY),
+                ObjectAnimator.ofFloat(this, "scaleX", toTransform.scale),
+                ObjectAnimator.ofFloat(this, "scaleY", toTransform.scale),
+                ObjectAnimator.ofFloat(this, "alpha", toTransform.alpha)
+        );
+        return anims;
+    }
+
     /** Resets this view's properties */
     void resetViewProperties() {
         setTranslationX(0f);
@@ -139,6 +167,17 @@
         setAlpha(1f);
     }
 
+    void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
+        // Fade the view out and slide it away
+        toTransform.alpha = 0f;
+        toTransform.translationY += 200;
+    }
+
+    void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
+        // Fade the view in
+        fromTransform.alpha = 0f;
+    }
+
     /** Animates this task view as it enters recents */
     public void animateOnEnterRecents() {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -155,7 +194,8 @@
                 .translationX(0)
                 .translationY(0)
                 .setStartDelay(235)
-                .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
+                .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
                 .withLayer()
                 .start();
     }
@@ -171,8 +211,8 @@
             .translationX(translate / 2)
             .translationY(-translate)
             .setStartDelay(0)
-            .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
-            .setInterpolator(new DecelerateInterpolator())
+            .setInterpolator(BakedBezierInterpolator.INSTANCE)
+            .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
             .withLayer()
             .withEndAction(r)
             .start();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 66c52a0..0748bbb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -23,13 +23,27 @@
 public class TaskViewTransform {
     public int translationY = 0;
     public float scale = 1f;
-    public boolean visible = true;
+    public float alpha = 1f;
+    public boolean visible = false;
     public Rect rect = new Rect();
     float t;
 
+    public TaskViewTransform() {
+        // Do nothing
+    }
+
+    public TaskViewTransform(TaskViewTransform o) {
+        translationY = o.translationY;
+        scale = o.scale;
+        alpha = o.alpha;
+        visible = o.visible;
+        rect.set(o.rect);
+        t = o.t;
+    }
+
     @Override
     public String toString() {
-        return "TaskViewTransform y: " + translationY + " scale: " + scale +
+        return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
                 " visible: " + visible + " rect: " + rect;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
new file mode 100644
index 0000000..a0a5561
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
@@ -0,0 +1,45 @@
+/*
+ * 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.settings;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.SeekBar;
+
+public class ToggleSeekBar extends SeekBar {
+    public ToggleSeekBar(Context context) {
+        super(context);
+    }
+
+    public ToggleSeekBar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ToggleSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (!isEnabled()) {
+            setEnabled(true);
+        }
+
+        return super.onTouchEvent(event);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index d584043..7d38058 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -19,20 +19,18 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.RelativeLayout;
 import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
 import com.android.systemui.R;
 
-public class ToggleSlider extends RelativeLayout
-        implements CompoundButton.OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener {
-    private static final String TAG = "StatusBar.ToggleSlider";
-
+public class ToggleSlider extends RelativeLayout {
     public interface Listener {
         public void onInit(ToggleSlider v);
         public void onChanged(ToggleSlider v, boolean tracking, boolean checked, int value);
@@ -55,20 +53,21 @@
 
     public ToggleSlider(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+
         View.inflate(context, R.layout.status_bar_toggle_slider, this);
 
         final Resources res = context.getResources();
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ToggleSlider,
-                defStyle, 0);
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.ToggleSlider, defStyle, 0);
 
-        mToggle = (CompoundButton)findViewById(R.id.toggle);
-        mToggle.setOnCheckedChangeListener(this);
-        mToggle.setBackgroundDrawable(res.getDrawable(R.drawable.status_bar_toggle_button));
+        mToggle = (CompoundButton) findViewById(R.id.toggle);
+        mToggle.setOnCheckedChangeListener(mCheckListener);
+        mToggle.setBackground(res.getDrawable(R.drawable.status_bar_toggle_button));
 
-        mSlider = (SeekBar)findViewById(R.id.slider);
-        mSlider.setOnSeekBarChangeListener(this);
+        mSlider = (SeekBar) findViewById(R.id.slider);
+        mSlider.setOnSeekBarChangeListener(mSeekListener);
 
-        mLabel = (TextView)findViewById(R.id.label);
+        mLabel = (TextView) findViewById(R.id.label);
         mLabel.setText(a.getString(R.styleable.ToggleSlider_text));
 
         a.recycle();
@@ -82,50 +81,6 @@
         }
     }
 
-    public void onCheckedChanged(CompoundButton toggle, boolean checked) {
-        Drawable thumb;
-        Drawable slider;
-        final Resources res = getContext().getResources();
-        if (checked) {
-            thumb = res.getDrawable(
-                    com.android.internal.R.drawable.scrubber_control_disabled_holo);
-            slider = res.getDrawable(
-                    R.drawable.status_bar_settings_slider_disabled);
-        } else {
-            thumb = res.getDrawable(
-                    com.android.internal.R.drawable.scrubber_control_selector_holo);
-            slider = res.getDrawable(
-                    com.android.internal.R.drawable.scrubber_progress_horizontal_holo_dark);
-        }
-        mSlider.setThumb(thumb);
-        mSlider.setProgressDrawable(slider);
-
-        if (mListener != null) {
-            mListener.onChanged(this, mTracking, checked, mSlider.getProgress());
-        }
-    }
-
-    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-        if (mListener != null) {
-            mListener.onChanged(this, mTracking, mToggle.isChecked(), progress);
-        }
-    }
-
-    public void onStartTrackingTouch(SeekBar seekBar) {
-        mTracking = true;
-        if (mListener != null) {
-            mListener.onChanged(this, mTracking, mToggle.isChecked(), mSlider.getProgress());
-        }
-        mToggle.setChecked(false);
-    }
-
-    public void onStopTrackingTouch(SeekBar seekBar) {
-        mTracking = false;
-        if (mListener != null) {
-            mListener.onChanged(this, mTracking, mToggle.isChecked(), mSlider.getProgress());
-        }
-    }
-
     public void setOnChangedListener(Listener l) {
         mListener = l;
     }
@@ -145,5 +100,49 @@
     public void setValue(int value) {
         mSlider.setProgress(value);
     }
+
+    private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton toggle, boolean checked) {
+            mSlider.setEnabled(!checked);
+
+            if (mListener != null) {
+                mListener.onChanged(
+                        ToggleSlider.this, mTracking, checked, mSlider.getProgress());
+            }
+        }
+    };
+
+    private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            if (mListener != null) {
+                mListener.onChanged(
+                        ToggleSlider.this, mTracking, mToggle.isChecked(), progress);
+            }
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            mTracking = true;
+
+            if (mListener != null) {
+                mListener.onChanged(
+                        ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+            }
+
+            mToggle.setChecked(false);
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            mTracking = false;
+
+            if (mListener != null) {
+                mListener.onChanged(
+                        ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+            }
+        }
+    };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index bad5641..844b964 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -41,7 +41,6 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -78,6 +77,7 @@
 import com.android.systemui.SearchPanelView;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -98,8 +98,6 @@
     protected static final int MSG_HIDE_HEADS_UP = 1027;
     protected static final int MSG_ESCALATE_HEADS_UP = 1028;
 
-    public static final boolean ENABLE_NOTIFICATION_STACK = SystemProperties
-            .getBoolean("persist.notifications.use_stack", false);
     protected static final boolean ENABLE_HEADS_UP = true;
     // scores above this threshold should be displayed in heads up mode.
     protected static final int INTERRUPTION_THRESHOLD = 10;
@@ -120,7 +118,7 @@
 
     // all notifications
     protected NotificationData mNotificationData = new NotificationData();
-    protected ViewGroup mPile;
+    protected NotificationStackScrollLayout mStackScroller;
 
     protected NotificationData.Entry mInterruptingNotificationEntry;
     protected long mInterruptingNotificationTime;
@@ -134,7 +132,7 @@
     protected PopupMenu mNotificationBlamePopup;
 
     protected int mCurrentUserId = 0;
-    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
 
     protected int mLayoutDirection = -1; // invalid
     private Locale mLocale;
@@ -244,21 +242,21 @@
             String action = intent.getAction();
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                updateRelatedUserCache();
+                updateCurrentProfilesCache();
                 if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
                 userSwitched(mCurrentUserId);
             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
-                updateRelatedUserCache();
+                updateCurrentProfilesCache();
             }
         }
     };
 
-    private void updateRelatedUserCache() {
-        synchronized (mRelatedUsers) {
-            mRelatedUsers.clear();
+    private void updateCurrentProfilesCache() {
+        synchronized (mCurrentProfiles) {
+            mCurrentProfiles.clear();
             if (mUserManager != null) {
-                for (UserInfo related : mUserManager.getRelatedUsers(mCurrentUserId)) {
-                    mRelatedUsers.put(related.id, related);
+                for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
+                    mCurrentProfiles.put(user.id, user);
                 }
             }
         }
@@ -361,24 +359,23 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        updateRelatedUserCache();
+        updateCurrentProfilesCache();
     }
 
     public void userSwitched(int newUserId) {
         // should be overridden
     }
 
-    public boolean notificationIsForCurrentOrRelatedUser(StatusBarNotification n) {
+    public boolean notificationIsForCurrentProfiles(StatusBarNotification n) {
         final int thisUserId = mCurrentUserId;
         final int notificationUserId = n.getUserId();
         if (DEBUG && MULTIUSER_DEBUG) {
             Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
                     n, thisUserId, notificationUserId));
         }
-        synchronized (mRelatedUsers) {
+        synchronized (mCurrentProfiles) {
             return notificationUserId == UserHandle.USER_ALL
-                    || thisUserId == notificationUserId
-                    || mRelatedUsers.get(notificationUserId) != null;
+                    || mCurrentProfiles.get(notificationUserId) != null;
         }
     }
 
@@ -973,7 +970,11 @@
         if (mPanelSlightlyVisible != visible) {
             mPanelSlightlyVisible = visible;
             try {
-                mBarService.onPanelRevealed();
+                if (visible) {
+                    mBarService.onPanelRevealed();
+                } else {
+                    mBarService.onPanelHidden();
+                }
             } catch (RemoteException ex) {
                 // Won't fail unless the world has ended.
             }
@@ -1034,7 +1035,7 @@
         }
         // Construct the expanded view.
         NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
-        if (!inflateViews(entry, mPile)) {
+        if (!inflateViews(entry, mStackScroller)) {
             handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
                     + notification);
             return null;
@@ -1258,7 +1259,7 @@
         updateNotificationVetoButton(oldEntry.row, notification);
 
         // Is this for you?
-        boolean isForCurrentUser = notificationIsForCurrentOrRelatedUser(notification);
+        boolean isForCurrentUser = notificationIsForCurrentProfiles(notification);
         if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
 
         // Restart the ticker if it's still running
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index f1c8e01..89da08f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -35,11 +37,14 @@
 
     static final boolean DEBUG = false;
     static final String TAG = "SignalClusterView";
+    static final PorterDuffColorFilter PROBLEM_FILTER
+            = new PorterDuffColorFilter(0xffab653b, PorterDuff.Mode.SRC_ATOP);
 
     NetworkController mNC;
 
     private boolean mWifiVisible = false;
     private int mWifiStrengthId = 0;
+    private boolean mInetProblem;
     private boolean mMobileVisible = false;
     private int mMobileStrengthId = 0, mMobileTypeId = 0;
     private boolean mIsAirplaneMode = false;
@@ -96,19 +101,22 @@
     }
 
     @Override
-    public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
+    public void setWifiIndicators(boolean visible, int strengthIcon, boolean problem,
+            String contentDescription) {
         mWifiVisible = visible;
         mWifiStrengthId = strengthIcon;
+        mInetProblem = problem;
         mWifiDescription = contentDescription;
 
         apply();
     }
 
     @Override
-    public void setMobileDataIndicators(boolean visible, int strengthIcon,
+    public void setMobileDataIndicators(boolean visible, int strengthIcon, boolean problem,
             int typeIcon, String contentDescription, String typeContentDescription) {
         mMobileVisible = visible;
         mMobileStrengthId = strengthIcon;
+        mInetProblem = problem;
         mMobileTypeId = typeIcon;
         mMobileDescription = contentDescription;
         mMobileTypeDescription = typeContentDescription;
@@ -158,13 +166,17 @@
         apply();
     }
 
+    private void applyInetProblem(ImageView iv) {
+        iv.setColorFilter(mInetProblem ? PROBLEM_FILTER : null);
+    }
+
     // Run after each indicator change.
     private void apply() {
         if (mWifiGroup == null) return;
 
         if (mWifiVisible) {
             mWifi.setImageResource(mWifiStrengthId);
-
+            applyInetProblem(mWifi);
             mWifiGroup.setContentDescription(mWifiDescription);
             mWifiGroup.setVisibility(View.VISIBLE);
         } else {
@@ -179,7 +191,7 @@
         if (mMobileVisible && !mIsAirplaneMode) {
             mMobile.setImageResource(mMobileStrengthId);
             mMobileType.setImageResource(mMobileTypeId);
-
+            applyInetProblem(mMobile);
             mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription);
             mMobileGroup.setVisibility(View.VISIBLE);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6be6d4d..2d2f2f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -17,45 +17,51 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.EventLog;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
-import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 public class NotificationPanelView extends PanelView {
     public static final boolean DEBUG_GESTURES = true;
 
-    Drawable mHandleBar;
-    int mHandleBarHeight;
-    View mHandleView;
-    int mFingers;
     PhoneStatusBar mStatusBar;
-    boolean mOkToFlip;
+    private NotificationStackScrollLayout mNotificationStackScroller;
+    private int[] mTempLocation = new int[2];
+    private int[] mTempChildLocation = new int[2];
+    private View mNotificationParent;
+
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     public void setStatusBar(PhoneStatusBar bar) {
+        if (mStatusBar != null) {
+            mStatusBar.setOnFlipRunnable(null);
+        }
         mStatusBar = bar;
+        if (bar != null) {
+            mStatusBar.setOnFlipRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    requestPanelHeightUpdate();
+                }
+            });
+        }
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        Resources resources = getContext().getResources();
-        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
-        mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
-        mHandleView = findViewById(R.id.handle);
+        mNotificationStackScroller = (NotificationStackScrollLayout)
+                findViewById(R.id.notification_stack_scroller);
+        mNotificationParent = findViewById(R.id.notification_container_parent);
     }
 
     @Override
@@ -80,61 +86,86 @@
         return super.dispatchPopulateAccessibilityEvent(event);
     }
 
-    // We draw the handle ourselves so that it's always glued to the bottom of the window.
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (changed) {
-            final int pl = getPaddingLeft();
-            final int pr = getPaddingRight();
-            mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-        final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
-        canvas.translate(0, off);
-        mHandleBar.setState(mHandleView.getDrawableState());
-        mHandleBar.draw(canvas);
-        canvas.translate(0, -off);
+    /**
+     * Gets the relative position of a view on the screen in regard to this view.
+     *
+     * @param requestedView the view we want to find the relative position for
+     * @return
+     */
+    private int getRelativeTop(View requestedView) {
+        getLocationOnScreen(mTempLocation);
+        requestedView.getLocationOnScreen(mTempChildLocation);
+        return mTempChildLocation[1] - mTempLocation[1];
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (DEBUG_GESTURES) {
-            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
-                EventLog.writeEvent(EventLogTags.SYSUI_NOTIFICATIONPANEL_TOUCH,
-                       event.getActionMasked(), (int) event.getX(), (int) event.getY());
-            }
+        // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
+        // implementation.
+        return super.onTouchEvent(event);
+    }
+
+    @Override
+    protected boolean isScrolledToBottom() {
+        if (!isInSettings()) {
+            return mNotificationStackScroller.isScrolledToBottom();
         }
-        if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
-            switch (event.getActionMasked()) {
-                case MotionEvent.ACTION_DOWN:
-                    mOkToFlip = getExpandedHeight() == 0;
-                    break;
-                case MotionEvent.ACTION_POINTER_DOWN:
-                    if (mOkToFlip) {
-                        float miny = event.getY(0);
-                        float maxy = miny;
-                        for (int i=1; i<event.getPointerCount(); i++) {
-                            final float y = event.getY(i);
-                            if (y < miny) miny = y;
-                            if (y > maxy) maxy = y;
-                        }
-                        if (maxy - miny < mHandleBarHeight) {
-                            if (getMeasuredHeight() < mHandleBarHeight) {
-                                mStatusBar.switchToSettings();
-                            } else {
-                                mStatusBar.flipToSettings();
-                            }
-                            mOkToFlip = false;
-                        }
-                    }
-                    break;
-            }
+        return super.isScrolledToBottom();
+    }
+
+    @Override
+    protected int getMaxPanelHeight() {
+        if (!isInSettings()) {
+            int maxPanelHeight = super.getMaxPanelHeight();
+            int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+            return maxPanelHeight - emptyBottomMargin;
         }
-        return mHandleView.dispatchTouchEvent(event);
+        return super.getMaxPanelHeight();
+    }
+
+    private boolean isInSettings() {
+        return mStatusBar != null && mStatusBar.isFlippedToSettings();
+    }
+
+    @Override
+    protected void onHeightUpdated(float expandedHeight) {
+        updateNotificationStackHeight(expandedHeight);
+    }
+
+    /**
+     * Update the height of the {@link #mNotificationStackScroller} to the new expanded height.
+     * This is much more efficient than doing it over the layout pass.
+     *
+     * @param expandedHeight the new expanded height
+     */
+    private void updateNotificationStackHeight(float expandedHeight) {
+        float childOffset = getRelativeTop(mNotificationStackScroller)
+                - mNotificationParent.getTranslationY();
+        int newStackHeight = (int) (expandedHeight - childOffset);
+        int itemHeight = mNotificationStackScroller.getItemHeight();
+        int bottomStackPeekSize = mNotificationStackScroller.getBottomStackPeekSize();
+        int minStackHeight = itemHeight + bottomStackPeekSize;
+        if (newStackHeight >= minStackHeight) {
+            mNotificationParent.setTranslationY(0);
+            mNotificationStackScroller.setCurrentStackHeight(newStackHeight);
+        } else {
+
+            // We did not reach the position yet where we actually start growing,
+            // so we translate the stack upwards.
+            int translationY = (newStackHeight - minStackHeight);
+            // A slight parallax effect is introduced in order for the stack to catch up with
+            // the top card.
+            float partiallyThere = (float) newStackHeight / minStackHeight;
+            partiallyThere = Math.max(0, partiallyThere);
+            translationY += (1 - partiallyThere) * bottomStackPeekSize;
+            mNotificationParent.setTranslationY(translationY);
+            mNotificationStackScroller.setCurrentStackHeight(
+                    (int) (expandedHeight - (childOffset + translationY)));
+        }
+    }
+
+    @Override
+    protected int getDesiredMeasureHeight() {
+        return mMaxPanelHeight;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 4b2c3e1..20fb225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -25,6 +25,7 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
@@ -69,7 +70,7 @@
 
     private View mHandleView;
     private float mPeekHeight;
-    private float mTouchOffset;
+    private float mInitialOffsetOnTouch;
     private float mExpandedFraction = 0;
     private float mExpandedHeight = 0;
     private boolean mJustPeeked;
@@ -77,6 +78,7 @@
     private boolean mRubberbanding;
     private boolean mTracking;
     private int mTrackingPointer;
+    private int mTouchSlop;
 
     private TimeAnimator mTimeAnimator;
     private ObjectAnimator mPeekAnimator;
@@ -198,7 +200,6 @@
         }
     }
 
-    private int[] mAbsPos = new int[2];
     PanelBar mBar;
 
     private final TimeListener mAnimationCallback = new TimeListener() {
@@ -220,7 +221,7 @@
     };
 
     private float mVel, mAccel;
-    private int mFullHeight = 0;
+    protected int mMaxPanelHeight = 0;
     private String mViewName;
     protected float mInitialTouchY;
     protected float mFinalTouchY;
@@ -253,13 +254,13 @@
             mTimeAnimator.start();
 
             mRubberbanding = mRubberbandingEnabled // is it enabled at all?
-                    && mExpandedHeight > getFullHeight() // are we past the end?
+                    && mExpandedHeight > getMaxPanelHeight() // are we past the end?
                     && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
             if (mRubberbanding) {
                 mClosing = true;
             } else if (mVel == 0) {
                 // if the panel is less than halfway open, close it
-                mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
+                mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f;
             } else {
                 mClosing = mExpandedHeight > 0 && mVel < 0;
             }
@@ -268,7 +269,7 @@
             if (DEBUG) logf("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
             if (DEBUG) logf("tick: before: h=%d", (int) mExpandedHeight);
 
-            final float fh = getFullHeight();
+            final float fh = getMaxPanelHeight();
             boolean braking = false;
             if (BRAKES) {
                 if (mClosing) {
@@ -351,6 +352,9 @@
         mPeekHeight = res.getDimension(R.dimen.peek_height)
             + getPaddingBottom() // our window might have a dropshadow
             - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
+
+        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+        mTouchSlop = configuration.getScaledTouchSlop();
     }
 
     private void trackMovement(MotionEvent event) {
@@ -363,10 +367,221 @@
         event.offsetLocation(-deltaX, -deltaY);
     }
 
-    // Pass all touches along to the handle, allowing the user to drag the panel closed from its interior
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        return mHandleView.dispatchTouchEvent(event);
+
+        /*
+         * We capture touch events here and update the expand height here in case according to
+         * the users fingers. This also handles multi-touch.
+         *
+         * If the user just clicks shortly, we give him a quick peek of the shade.
+         *
+         * Flinging is also enabled in order to open or close the shade.
+         */
+
+        int pointerIndex = event.findPointerIndex(mTrackingPointer);
+        if (pointerIndex < 0) {
+            pointerIndex = 0;
+            mTrackingPointer = event.getPointerId(pointerIndex);
+        }
+        final float y = event.getY(pointerIndex);
+
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                mTracking = true;
+                if (mHandleView != null) {
+                    mHandleView.setPressed(true);
+                    postInvalidate(); // catch the press state change
+                }
+
+                mInitialTouchY = y;
+                initVelocityTracker();
+                trackMovement(event);
+                mTimeAnimator.cancel(); // end any outstanding animations
+                mBar.onTrackingStarted(PanelView.this);
+                mInitialOffsetOnTouch = mExpandedHeight;
+                if (mExpandedHeight == 0) {
+                    mJustPeeked = true;
+                    runPeekAnimation();
+                }
+                break;
+
+            case MotionEvent.ACTION_POINTER_UP:
+                final int upPointer = event.getPointerId(event.getActionIndex());
+                if (mTrackingPointer == upPointer) {
+                    // gesture is ongoing, find a new pointer to track
+                    final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+                    final float newY = event.getY(newIndex);
+                    mTrackingPointer = event.getPointerId(newIndex);
+                    mInitialOffsetOnTouch = mExpandedHeight;
+                    mInitialTouchY = newY;
+                }
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                final float h = y - mInitialTouchY + mInitialOffsetOnTouch;
+                if (h > mPeekHeight) {
+                    if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
+                        mPeekAnimator.cancel();
+                    }
+                    mJustPeeked = false;
+                }
+                if (!mJustPeeked) {
+                    setExpandedHeightInternal(h);
+                    mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+                }
+
+                trackMovement(event);
+                break;
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mFinalTouchY = y;
+                mTracking = false;
+                mTrackingPointer = -1;
+                if (mHandleView != null) {
+                    mHandleView.setPressed(false);
+                    postInvalidate(); // catch the press state change
+                }
+                mBar.onTrackingStopped(PanelView.this);
+                trackMovement(event);
+
+                float vel = getCurrentVelocity();
+                fling(vel, true);
+
+                if (mVelocityTracker != null) {
+                    mVelocityTracker.recycle();
+                    mVelocityTracker = null;
+                }
+                break;
+        }
+        return true;
+    }
+
+    private float getCurrentVelocity() {
+        float vel = 0;
+        float yVel = 0, xVel = 0;
+        boolean negative = false;
+
+        // the velocitytracker might be null if we got a bad input stream
+        if (mVelocityTracker == null) {
+            return 0;
+        }
+
+        mVelocityTracker.computeCurrentVelocity(1000);
+
+        yVel = mVelocityTracker.getYVelocity();
+        negative = yVel < 0;
+
+        xVel = mVelocityTracker.getXVelocity();
+        if (xVel < 0) {
+            xVel = -xVel;
+        }
+        if (xVel > mFlingGestureMaxXVelocityPx) {
+            xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+        }
+
+        vel = (float) Math.hypot(yVel, xVel);
+        if (vel > mFlingGestureMaxOutputVelocityPx) {
+            vel = mFlingGestureMaxOutputVelocityPx;
+        }
+
+        // if you've barely moved your finger, we treat the velocity as 0
+        // preventing spurious flings due to touch screen jitter
+        final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
+        if (deltaY < mFlingGestureMinDistPx
+                || vel < mFlingExpandMinVelocityPx
+                ) {
+            vel = 0;
+        }
+
+        if (negative) {
+            vel = -vel;
+        }
+
+        if (DEBUG) {
+            logf("gesture: dy=%f vel=(%f,%f) vlinear=%f",
+                    deltaY,
+                    xVel, yVel,
+                    vel);
+        }
+        return vel;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+
+        /*
+         * If the user drags anywhere inside the panel we intercept it if he moves his finger
+         * upwards. This allows closing the shade from anywhere inside the panel.
+         *
+         * We only do this if the current content is scrolled to the bottom,
+         * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling gesture
+         * possible.
+         */
+        int pointerIndex = event.findPointerIndex(mTrackingPointer);
+        if (pointerIndex < 0) {
+            pointerIndex = 0;
+            mTrackingPointer = event.getPointerId(pointerIndex);
+        }
+        final float y = event.getY(pointerIndex);
+        boolean scrolledToBottom = isScrolledToBottom();
+
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                if (mHandleView != null) {
+                    mHandleView.setPressed(true);
+                    // catch the press state change
+                    postInvalidate();
+                }
+                mInitialTouchY = y;
+                initVelocityTracker();
+                trackMovement(event);
+                mTimeAnimator.cancel(); // end any outstanding animations
+                if (mExpandedHeight == 0 || y > getContentHeight()) {
+                    return true;
+                }
+                break;
+            case MotionEvent.ACTION_POINTER_UP:
+                final int upPointer = event.getPointerId(event.getActionIndex());
+                if (mTrackingPointer == upPointer) {
+                    // gesture is ongoing, find a new pointer to track
+                    final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+                    mTrackingPointer = event.getPointerId(newIndex);
+                    final float newY = event.getY(newIndex);
+                    mInitialTouchY = newY;
+                }
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                final float h = y - mInitialTouchY;
+                trackMovement(event);
+                if (scrolledToBottom) {
+                    if (h < -mTouchSlop) {
+                        mInitialOffsetOnTouch = mExpandedHeight;
+                        mInitialTouchY = y;
+                        mTracking = true;
+                        return true;
+                    }
+                }
+                break;
+        }
+        return false;
+    }
+
+    private void initVelocityTracker() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+        }
+        mVelocityTracker = FlingTracker.obtain();
+    }
+
+    protected boolean isScrolledToBottom() {
+        return false;
+    }
+
+    protected float getContentHeight() {
+        return mExpandedHeight;
     }
 
     @Override
@@ -375,134 +590,6 @@
         mHandleView = findViewById(R.id.handle);
 
         loadDimens();
-
-        if (DEBUG) logf("handle view: " + mHandleView);
-        if (mHandleView != null) {
-            mHandleView.setOnTouchListener(new View.OnTouchListener() {
-                @Override
-                public boolean onTouch(View v, MotionEvent event) {
-                    int pointerIndex = event.findPointerIndex(mTrackingPointer);
-                    if (pointerIndex < 0) {
-                        pointerIndex = 0;
-                        mTrackingPointer = event.getPointerId(pointerIndex);
-                    }
-                    final float y = event.getY(pointerIndex);
-                    final float rawDelta = event.getRawY() - event.getY();
-                    final float rawY = y + rawDelta;
-                    if (DEBUG) logf("handle.onTouch: a=%s p=[%d,%d] y=%.1f rawY=%.1f off=%.1f",
-                            MotionEvent.actionToString(event.getAction()),
-                            mTrackingPointer, pointerIndex,
-                            y, rawY, mTouchOffset);
-                    PanelView.this.getLocationOnScreen(mAbsPos);
-
-                    switch (event.getActionMasked()) {
-                        case MotionEvent.ACTION_DOWN:
-                            mTracking = true;
-                            mHandleView.setPressed(true);
-                            postInvalidate(); // catch the press state change
-                            mInitialTouchY = y;
-                            mVelocityTracker = FlingTracker.obtain();
-                            trackMovement(event);
-                            mTimeAnimator.cancel(); // end any outstanding animations
-                            mBar.onTrackingStarted(PanelView.this);
-                            mTouchOffset = (rawY - mAbsPos[1]) - mExpandedHeight;
-                            if (mExpandedHeight == 0) {
-                                mJustPeeked = true;
-                                runPeekAnimation();
-                            }
-                            break;
-
-                        case MotionEvent.ACTION_POINTER_UP:
-                            final int upPointer = event.getPointerId(event.getActionIndex());
-                            if (mTrackingPointer == upPointer) {
-                                // gesture is ongoing, find a new pointer to track
-                                final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
-                                final float newY = event.getY(newIndex);
-                                final float newRawY = newY + rawDelta;
-                                mTrackingPointer = event.getPointerId(newIndex);
-                                mTouchOffset = (newRawY - mAbsPos[1]) - mExpandedHeight;
-                                mInitialTouchY = newY;
-                            }
-                            break;
-
-                        case MotionEvent.ACTION_MOVE:
-                            final float h = rawY - mAbsPos[1] - mTouchOffset;
-                            if (h > mPeekHeight) {
-                                if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
-                                    mPeekAnimator.cancel();
-                                }
-                                mJustPeeked = false;
-                            }
-                            if (!mJustPeeked) {
-                                PanelView.this.setExpandedHeightInternal(h);
-                                mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
-                            }
-
-                            trackMovement(event);
-                            break;
-
-                        case MotionEvent.ACTION_UP:
-                        case MotionEvent.ACTION_CANCEL:
-                            mFinalTouchY = y;
-                            mTracking = false;
-                            mTrackingPointer = -1;
-                            mHandleView.setPressed(false);
-                            postInvalidate(); // catch the press state change
-                            mBar.onTrackingStopped(PanelView.this);
-                            trackMovement(event);
-
-                            float vel = 0, yVel = 0, xVel = 0;
-                            boolean negative = false;
-
-                            if (mVelocityTracker != null) {
-                                // the velocitytracker might be null if we got a bad input stream
-                                mVelocityTracker.computeCurrentVelocity(1000);
-
-                                yVel = mVelocityTracker.getYVelocity();
-                                negative = yVel < 0;
-
-                                xVel = mVelocityTracker.getXVelocity();
-                                if (xVel < 0) {
-                                    xVel = -xVel;
-                                }
-                                if (xVel > mFlingGestureMaxXVelocityPx) {
-                                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
-                                }
-
-                                vel = (float)Math.hypot(yVel, xVel);
-                                if (vel > mFlingGestureMaxOutputVelocityPx) {
-                                    vel = mFlingGestureMaxOutputVelocityPx;
-                                }
-
-                                mVelocityTracker.recycle();
-                                mVelocityTracker = null;
-                            }
-
-                            // if you've barely moved your finger, we treat the velocity as 0
-                            // preventing spurious flings due to touch screen jitter
-                            final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
-                            if (deltaY < mFlingGestureMinDistPx
-                                    || vel < mFlingExpandMinVelocityPx
-                                    ) {
-                                vel = 0;
-                            }
-
-                            if (negative) {
-                                vel = -vel;
-                            }
-
-                            if (DEBUG) logf("gesture: dy=%f vel=(%f,%f) vlinear=%f",
-                                    deltaY,
-                                    xVel, yVel,
-                                    vel);
-
-                            fling(vel, true);
-
-                            break;
-                    }
-                    return true;
-                }});
-        }
     }
 
     public void fling(float vel, boolean always) {
@@ -543,19 +630,18 @@
 
         // Did one of our children change size?
         int newHeight = getMeasuredHeight();
-        if (newHeight != mFullHeight) {
-            mFullHeight = newHeight;
-            // If the user isn't actively poking us, let's rubberband to the content
-            if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
-                    && mExpandedHeight > 0 && mExpandedHeight != mFullHeight) {
-                mExpandedHeight = mFullHeight;
-            }
+        if (newHeight != mMaxPanelHeight) {
+            mMaxPanelHeight = newHeight;
         }
         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                    (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
+                    getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
         setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
     }
 
+    protected int getDesiredMeasureHeight() {
+        return (int) mExpandedHeight;
+    }
+
 
     public void setExpandedHeight(float height) {
         if (DEBUG) logf("setExpandedHeight(%.1f)", height);
@@ -569,8 +655,20 @@
 
     @Override
     protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
-        if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, mFullHeight);
+        if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom,
+                (int)mExpandedHeight, mMaxPanelHeight);
         super.onLayout(changed, left, top, right, bottom);
+        requestPanelHeightUpdate();
+    }
+
+    protected void requestPanelHeightUpdate() {
+        float currentMaxPanelHeight = getMaxPanelHeight();
+
+        // If the user isn't actively poking us, let's update the height
+        if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+                && mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) {
+            setExpandedHeightInternal(currentMaxPanelHeight);
+        }
     }
 
     public void setExpandedHeightInternal(float h) {
@@ -583,7 +681,7 @@
             h = 0;
         }
 
-        float fh = getFullHeight();
+        float fh = getMaxPanelHeight();
         if (fh == 0) {
             // Hmm, full height hasn't been computed yet
         }
@@ -593,9 +691,13 @@
 
         mExpandedHeight = h;
 
-        if (DEBUG) logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
+        if (DEBUG) {
+            logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh,
+                    mTracking ? "T" : "f", mRubberbanding ? "T" : "f");
+        }
 
-        requestLayout();
+        onHeightUpdated(mExpandedHeight);
+
 //        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
 //        lp.height = (int) mExpandedHeight;
 //        setLayoutParams(lp);
@@ -603,13 +705,23 @@
         mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : h / fh);
     }
 
-    private float getFullHeight() {
-        if (mFullHeight <= 0) {
-            if (DEBUG) logf("Forcing measure() since fullHeight=" + mFullHeight);
+    protected void onHeightUpdated(float expandedHeight) {
+        requestLayout();
+    }
+
+    /**
+     * This returns the maximum height of the panel. Children should override this if their
+     * desired height is not the full height.
+     *
+     * @return the default implementation simply returns the maximum height.
+     */
+    protected int getMaxPanelHeight() {
+        if (mMaxPanelHeight <= 0) {
+            if (DEBUG) logf("Forcing measure() since mMaxPanelHeight=" + mMaxPanelHeight);
             measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
         }
-        return mFullHeight;
+        return mMaxPanelHeight;
     }
 
     public void setExpandedFraction(float frac) {
@@ -621,7 +733,7 @@
             }
             frac = 0;
         }
-        setExpandedHeight(getFullHeight() * frac);
+        setExpandedHeight(getMaxPanelHeight() * frac);
     }
 
     public float getExpandedHeight() {
@@ -633,7 +745,7 @@
     }
 
     public boolean isFullyExpanded() {
-        return mExpandedHeight >= getFullHeight();
+        return mExpandedHeight >= getMaxPanelHeight();
     }
 
     public boolean isFullyCollapsed() {
@@ -681,12 +793,12 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(String.format("[PanelView(%s): expandedHeight=%f fullHeight=%f closing=%s"
+        pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
                 + " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
                 + "]",
                 this.getClass().getSimpleName(),
                 getExpandedHeight(),
-                getFullHeight(),
+                getMaxPanelHeight(),
                 mClosing?"T":"f",
                 mTracking?"T":"f",
                 mRubberbanding?"T":"f",
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index adfa118..4730f2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -86,7 +86,6 @@
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
@@ -101,8 +100,6 @@
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
-import com.android.systemui.statusbar.policy.OnSizeChangedListener;
 import com.android.systemui.statusbar.policy.RotationLockController;
 
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -172,7 +169,7 @@
     Display mDisplay;
     Point mCurrentDisplaySize = new Point();
     private float mHeadsUpVerticalOffset;
-    private int[] mPilePosition = new int[2];
+    private int[] mStackScrollerPosition = new int[2];
 
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
@@ -198,7 +195,6 @@
 
     // expanded notifications
     NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
-    View mNotificationScroller;
     View mExpandedContents;
     int mNotificationPanelGravity;
     int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
@@ -350,6 +346,12 @@
             }
         }};
 
+    private Runnable mOnFlipRunnable;
+
+    public void setOnFlipRunnable(Runnable onFlipRunnable) {
+        mOnFlipRunnable = onFlipRunnable;
+    }
+
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
@@ -417,7 +419,8 @@
         PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
         mStatusBarView.setPanelHolder(holder);
 
-        mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
+        mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
+                R.id.notification_panel);
         mNotificationPanel.setStatusBar(this);
         mNotificationPanelIsFullScreenWidth =
             (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
@@ -443,7 +446,8 @@
             mHeadsUpNotificationView.setBar(this);
         }
         if (MULTIUSER_DEBUG) {
-            mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(R.id.header_debug_info);
+            mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
+                    R.id.header_debug_info);
             mNotificationPanelDebugText.setVisibility(View.VISIBLE);
         }
 
@@ -482,33 +486,11 @@
         mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
         mTickerView = mStatusBarView.findViewById(R.id.ticker);
 
-        View legacyScrollView = mStatusBarWindow.findViewById(R.id.scroll);
-        NotificationStackScrollLayout notificationStack
-                = (NotificationStackScrollLayout) mStatusBarWindow
-                .findViewById(R.id.notification_stack_scroller);
-        if (ENABLE_NOTIFICATION_STACK) {
-            notificationStack.setLongPressListener(getNotificationLongClicker());
-            mPile = notificationStack;
-            legacyScrollView.setVisibility(View.GONE);
+        mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+                R.id.notification_stack_scroller);
+        mStackScroller.setLongPressListener(getNotificationLongClicker());
 
-            // The scrollview and the notification container are unified now!
-            // TODO: remove mNotificationScroller entirely once we fully switch to the new Layout
-            mNotificationScroller = notificationStack;
-        } else {
-            mNotificationScroller = legacyScrollView;
-            // less drawing during pulldowns
-            mNotificationScroller.setVerticalScrollBarEnabled(false);
-            NotificationRowLayout rowLayout
-                    = (NotificationRowLayout) mStatusBarWindow.findViewById(R.id.latestItems);
-            rowLayout.setLayoutTransitionsEnabled(false);
-            rowLayout.setLongPressListener(getNotificationLongClicker());
-            mPile = rowLayout;
-            notificationStack.setVisibility(View.GONE);
-        }
-
-        mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
-
-
+        mExpandedContents = mStackScroller;
 
         mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
 
@@ -551,7 +533,8 @@
             }
         }
         if (mHasFlipSettings) {
-            mNotificationButton = (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
+            mNotificationButton = (ImageView) mStatusBarWindow.findViewById(
+                    R.id.notification_button);
             if (mNotificationButton != null) {
                 mNotificationButton.setOnClickListener(mNotificationButtonListener);
             }
@@ -593,17 +576,18 @@
         if (isAPhone) {
             mEmergencyCallLabel =
                     (TextView) mStatusBarWindow.findViewById(R.id.emergency_calls_only);
-            if (mEmergencyCallLabel != null) {
-                mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
-                mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
-                    public void onClick(View v) { }});
-                mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-                    @Override
-                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                        updateCarrierLabelVisibility(false);
-                    }});
-            }
+            // TODO: Uncomment when correctly positioned
+//            if (mEmergencyCallLabel != null) {
+//                mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
+//                mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
+//                    public void onClick(View v) { }});
+//                mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+//                    @Override
+//                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
+//                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
+//                        updateCarrierLabelVisibility(false);
+//                    }});
+//            }
         }
 
         mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
@@ -621,13 +605,12 @@
             }
 
             // set up the dynamic hide/show of the label
-            if (!ENABLE_NOTIFICATION_STACK)
-                ((NotificationRowLayout) mPile).setOnSizeChangedListener(new OnSizeChangedListener() {
-                @Override
-                public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
-                    updateCarrierLabelVisibility(false);
-                }
-            });
+            // TODO: uncomment, handle this for the Stack scroller aswell
+//                ((NotificationRowLayout) mStackScroller)
+// .setOnSizeChangedListener(new OnSizeChangedListener() {
+//                @Override
+//                public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
+//                    updateCarrierLabelVisibility(false);
         }
 
         // Quick Settings (where available, some restrictions apply)
@@ -1066,7 +1049,7 @@
     }
 
     private void loadNotificationShade() {
-        if (mPile == null) return;
+        if (mStackScroller == null) return;
 
         int N = mNotificationData.size();
 
@@ -1078,8 +1061,8 @@
             Entry ent = mNotificationData.get(N-i-1);
             if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
 
-            // TODO How do we want to badge notifcations from related users.
-            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+            // TODO How do we want to badge notifcations from profiles.
+            if (!notificationIsForCurrentProfiles(ent.notification)) continue;
 
             final int vis = ent.notification.getNotification().visibility;
             if (vis != Notification.VISIBILITY_SECRET) {
@@ -1092,21 +1075,21 @@
         }
 
         ArrayList<View> toRemove = new ArrayList<View>();
-        for (int i=0; i<mPile.getChildCount(); i++) {
-            View child = mPile.getChildAt(i);
+        for (int i=0; i< mStackScroller.getChildCount(); i++) {
+            View child = mStackScroller.getChildAt(i);
             if (!toShow.contains(child)) {
                 toRemove.add(child);
             }
         }
 
         for (View remove : toRemove) {
-            mPile.removeView(remove);
+            mStackScroller.removeView(remove);
         }
 
         for (int i=0; i<toShow.size(); i++) {
             View v = toShow.get(i);
             if (v.getParent() == null) {
-                mPile.addView(v, i);
+                mStackScroller.addView(v, i);
             }
         }
 
@@ -1138,7 +1121,7 @@
             Entry ent = mNotificationData.get(N-i-1);
             if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE)
                     || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
-            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+            if (!notificationIsForCurrentProfiles(ent.notification)) continue;
             if (isLockscreenPublicMode()
                     && ent.notification.getNotification().visibility
                             == Notification.VISIBILITY_SECRET
@@ -1178,15 +1161,17 @@
         // The idea here is to only show the carrier label when there is enough room to see it,
         // i.e. when there aren't enough notifications to fill the panel.
         if (SPEW) {
-            Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
-                    mPile.getHeight(), mNotificationScroller.getHeight(), mCarrierLabelHeight));
+            Log.d(TAG, String.format("stackScrollerh=%d scrollh=%d carrierh=%d",
+                    mStackScroller.getHeight(), mStackScroller.getHeight(),
+                    mCarrierLabelHeight));
         }
 
         final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
         final boolean makeVisible =
             !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
-            && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight)
-            && mNotificationScroller.getVisibility() == View.VISIBLE;
+            && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
+                    - mCarrierLabelHeight - mNotificationHeaderHeight)
+            && mStackScroller.getVisibility() == View.VISIBLE;
 
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -1229,7 +1214,7 @@
         if (mHasFlipSettings
                 && mFlipSettingsView != null
                 && mFlipSettingsView.getVisibility() == View.VISIBLE
-                && mNotificationScroller.getVisibility() != View.VISIBLE) {
+                && mStackScroller.getVisibility() != View.VISIBLE) {
             // the flip settings panel is unequivocally showing; we should not be shown
             mClearButton.setVisibility(View.INVISIBLE);
         } else if (mClearButton.isShown()) {
@@ -1483,9 +1468,6 @@
         }
 
         mExpandedVisible = true;
-        if(!ENABLE_NOTIFICATION_STACK) {
-            ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(true);
-        }
         if (mNavigationBarView != null)
             mNavigationBarView.setSlippery(true);
 
@@ -1600,7 +1582,7 @@
         }
 
         mNotificationPanel.expand();
-        if (mHasFlipSettings && mNotificationScroller.getVisibility() != View.VISIBLE) {
+        if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) {
             flipToNotifications();
         }
 
@@ -1614,11 +1596,11 @@
         if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
         if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
-        mNotificationScroller.setVisibility(View.VISIBLE);
+        mStackScroller.setVisibility(View.VISIBLE);
         mScrollViewAnim = start(
             startDelay(FLIP_DURATION_OUT,
                 interpolator(mDecelerateInterpolator,
-                    ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 0f, 1f)
+                    ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f)
                         .setDuration(FLIP_DURATION_IN)
                     )));
         mFlipSettingsViewAnim = start(
@@ -1645,6 +1627,9 @@
                 updateCarrierLabelVisibility(false);
             }
         }, FLIP_DURATION - 150);
+        if (mOnFlipRunnable != null) {
+            mOnFlipRunnable.run();
+        }
     }
 
     @Override
@@ -1676,11 +1661,21 @@
         mFlipSettingsView.setScaleX(1f);
         mFlipSettingsView.setVisibility(View.VISIBLE);
         mSettingsButton.setVisibility(View.GONE);
-        mNotificationScroller.setVisibility(View.GONE);
-        mNotificationScroller.setScaleX(0f);
+        mStackScroller.setVisibility(View.GONE);
+        mStackScroller.setScaleX(0f);
         mNotificationButton.setVisibility(View.VISIBLE);
         mNotificationButton.setAlpha(1f);
         mClearButton.setVisibility(View.GONE);
+        if (mOnFlipRunnable != null) {
+            mOnFlipRunnable.run();
+        }
+    }
+
+    public boolean isFlippedToSettings() {
+        if (mFlipSettingsView != null) {
+            return mFlipSettingsView.getVisibility() == View.VISIBLE;
+        }
+        return false;
     }
 
     public void flipToSettings() {
@@ -1704,15 +1699,15 @@
         mScrollViewAnim = start(
             setVisibilityWhenDone(
                 interpolator(mAccelerateInterpolator,
-                        ObjectAnimator.ofFloat(mNotificationScroller, View.SCALE_X, 1f, 0f)
+                        ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f)
                         )
                     .setDuration(FLIP_DURATION_OUT),
-                    mNotificationScroller, View.INVISIBLE));
+                    mStackScroller, View.INVISIBLE));
         mSettingsButtonAnim = start(
             setVisibilityWhenDone(
                 ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
                     .setDuration(FLIP_DURATION),
-                    mNotificationScroller, View.INVISIBLE));
+                    mStackScroller, View.INVISIBLE));
         mNotificationButton.setVisibility(View.VISIBLE);
         mNotificationButtonAnim = start(
             ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
@@ -1727,6 +1722,9 @@
                 updateCarrierLabelVisibility(false);
             }
         }, FLIP_DURATION - 150);
+        if (mOnFlipRunnable != null) {
+            mOnFlipRunnable.run();
+        }
     }
 
     public void flipPanels() {
@@ -1766,8 +1764,8 @@
             if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
             if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
-            mNotificationScroller.setScaleX(1f);
-            mNotificationScroller.setVisibility(View.VISIBLE);
+            mStackScroller.setScaleX(1f);
+            mStackScroller.setVisibility(View.VISIBLE);
             mSettingsButton.setAlpha(1f);
             mSettingsButton.setVisibility(View.VISIBLE);
             mNotificationPanel.setVisibility(View.GONE);
@@ -1777,9 +1775,6 @@
         }
 
         mExpandedVisible = false;
-        if(!ENABLE_NOTIFICATION_STACK) {
-            ((NotificationRowLayout) mPile).setLayoutTransitionsEnabled(false);
-        }
         if (mNavigationBarView != null)
             mNavigationBarView.setSlippery(false);
         visibilityChanged(false);
@@ -1806,53 +1801,6 @@
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
     }
 
-    /**
-     * Enables or disables layers on the children of the notifications pile.
-     *
-     * When layers are enabled, this method attempts to enable layers for the minimal
-     * number of children. Only children visible when the notification area is fully
-     * expanded will receive a layer. The technique used in this method might cause
-     * more children than necessary to get a layer (at most one extra child with the
-     * current UI.)
-     *
-     * @param layerType {@link View#LAYER_TYPE_NONE} or {@link View#LAYER_TYPE_HARDWARE}
-     */
-    private void setPileLayers(int layerType) {
-        final int count = mPile.getChildCount();
-
-        switch (layerType) {
-            case View.LAYER_TYPE_NONE:
-                for (int i = 0; i < count; i++) {
-                    mPile.getChildAt(i).setLayerType(layerType, null);
-                }
-                break;
-            case View.LAYER_TYPE_HARDWARE:
-                final int[] location = new int[2];
-                mNotificationPanel.getLocationInWindow(location);
-
-                final int left = location[0];
-                final int top = location[1];
-                final int right = left + mNotificationPanel.getWidth();
-                final int bottom = top + getExpandedViewMaxHeight();
-
-                final Rect childBounds = new Rect();
-
-                for (int i = 0; i < count; i++) {
-                    final View view = mPile.getChildAt(i);
-                    view.getLocationInWindow(location);
-
-                    childBounds.set(location[0], location[1],
-                            location[0] + view.getWidth(), location[1] + view.getHeight());
-
-                    if (childBounds.intersects(left, top, right, bottom)) {
-                        view.setLayerType(layerType, null);
-                    }
-                }
-
-                break;
-        }
-    }
-
     public boolean interceptTouchEvent(MotionEvent event) {
         if (DEBUG_GESTURES) {
             if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -2150,7 +2098,7 @@
         if (!isDeviceProvisioned()) return;
 
         // not for you
-        if (!notificationIsForCurrentOrRelatedUser(n)) return;
+        if (!notificationIsForCurrentProfiles(n)) return;
 
         // Show the ticker if one is requested. Also don't do this
         // until status bar window is attached to the window manager,
@@ -2230,11 +2178,11 @@
             pw.println("  mTicking=" + mTicking);
             pw.println("  mTracking=" + mTracking);
             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
-            pw.println("  mPile: " + viewInfo(mPile));
+            pw.println("  mStackScroller: " + viewInfo(mStackScroller));
             pw.println("  mTickerView: " + viewInfo(mTickerView));
-            pw.println("  mNotificationScroller: " + viewInfo(mNotificationScroller)
-                    + " scroll " + mNotificationScroller.getScrollX()
-                    + "," + mNotificationScroller.getScrollY());
+            pw.println("  mStackScroller: " + viewInfo(mStackScroller)
+                    + " scroll " + mStackScroller.getScrollX()
+                    + "," + mStackScroller.getScrollY());
         }
 
         pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2409,8 +2357,8 @@
 
         if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) {
             mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx);
-            mPile.getLocationOnScreen(mPilePosition);
-            mHeadsUpVerticalOffset = mPilePosition[1] - mNaturalBarHeight;
+            mStackScroller.getLocationOnScreen(mStackScrollerPosition);
+            mHeadsUpVerticalOffset = mStackScrollerPosition[1] - mNaturalBarHeight;
         }
 
         updateCarrierLabelVisibility(false);
@@ -2428,7 +2376,6 @@
 
     private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
         public void onClick(View v) {
-            // TODO: Handle this better with notification stack scroller
             synchronized (mNotificationData) {
                 mPostCollapseCleanup = new Runnable() {
                     @Override
@@ -2437,86 +2384,14 @@
                             Log.v(TAG, "running post-collapse cleanup");
                         }
                         try {
-                            if (!ENABLE_NOTIFICATION_STACK) {
-                                ((NotificationRowLayout) mPile).setViewRemoval(true);
-                            }
                             mBarService.onClearAllNotifications(mCurrentUserId);
                         } catch (Exception ex) { }
                     }
                 };
 
-                if(ENABLE_NOTIFICATION_STACK) {
-                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-                    return;
-                }
-
-                // animate-swipe all dismissable notifications, then animate the shade closed
-                int numChildren = mPile.getChildCount();
-
-                int scrollTop = mNotificationScroller.getScrollY();
-                int scrollBottom = scrollTop + mNotificationScroller.getHeight();
-                final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
-                for (int i=0; i<numChildren; i++) {
-                    final View child = mPile.getChildAt(i);
-                    if (((SwipeHelper.Callback) mPile).canChildBeDismissed(child)
-                            && child.getBottom() > scrollTop && child.getTop() < scrollBottom) {
-                        snapshot.add(child);
-                    }
-                }
-                if (snapshot.isEmpty()) {
-                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-                    return;
-                }
-                new Thread(new Runnable() {
-                    @Override
-                    public void run() {
-                        // Decrease the delay for every row we animate to give the sense of
-                        // accelerating the swipes
-                        final int ROW_DELAY_DECREMENT = 10;
-                        int currentDelay = 140;
-                        int totalDelay = 0;
-
-
-                        if(!ENABLE_NOTIFICATION_STACK) {
-                            // Set the shade-animating state to avoid doing other work during
-                            // all of these animations. In particular, avoid layout and
-                            // redrawing when collapsing the shade.
-                            ((NotificationRowLayout) mPile).setViewRemoval(false);
-                        }
-
-                        View sampleView = snapshot.get(0);
-                        int width = sampleView.getWidth();
-                        final int dir = sampleView.isLayoutRtl() ? -1 : +1;
-                        final int velocity = dir * width * 8; // 1000/8 = 125 ms duration
-                        for (final View _v : snapshot) {
-                            mHandler.postDelayed(new Runnable() {
-                                @Override
-                                public void run() {
-                                    if (!ENABLE_NOTIFICATION_STACK) {
-                                        ((NotificationRowLayout) mPile).dismissRowAnimated(
-                                                _v, velocity);
-                                    } else {
-                                        ((NotificationStackScrollLayout) mPile).dismissRowAnimated(
-                                                _v, velocity);
-                                    }
-                                }
-                            }, totalDelay);
-                            currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
-                            totalDelay += currentDelay;
-                        }
-                        // Delay the collapse animation until after all swipe animations have
-                        // finished. Provide some buffer because there may be some extra delay
-                        // before actually starting each swipe animation. Ideally, we'd
-                        // synchronize the end of those animations with the start of the collaps
-                        // exactly.
-                        mHandler.postDelayed(new Runnable() {
-                            @Override
-                            public void run() {
-                                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-                            }
-                        }, totalDelay + 225);
-                    }
-                }).start();
+                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+                return;
+                // TODO: Handle this better with notification stack scroller
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index aed9a71..d67f7cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -911,6 +911,7 @@
                 d.getWindow().setAttributes(lp);
             }
         };
+        v.setAutoActivate(true);
         v.setAdapter(new ZenModeViewAdapter(mContext) {
             @Override
             public void configure() {
@@ -928,7 +929,6 @@
         d.create();
         d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
         WindowManager.LayoutParams lp = d.getWindow().getAttributes();
-        lp.horizontalMargin = 0;
         lp.width = mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_dialog_width);
         d.getWindow().setAttributes(lp);
         d.show();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 925e0d8..a7121c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -24,14 +24,14 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewRootImpl;
 import android.widget.FrameLayout;
-import android.widget.ScrollView;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 
 public class StatusBarWindowView extends FrameLayout
@@ -40,9 +40,8 @@
     public static final boolean DEBUG = BaseStatusBar.DEBUG;
 
     private ExpandHelper mExpandHelper;
-    private ViewGroup latestItems;
+    private NotificationStackScrollLayout mStackScrollLayout;
     private NotificationPanelView mNotificationPanel;
-    private ScrollView mScrollView;
 
     PhoneStatusBar mService;
 
@@ -56,19 +55,15 @@
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
 
-        if (BaseStatusBar.ENABLE_NOTIFICATION_STACK) {
-            latestItems = (ViewGroup) findViewById(R.id.notification_stack_scroller);
-        } else {
-            latestItems = (ViewGroup) findViewById(R.id.latestItems);
-        }
-        mScrollView = (ScrollView) findViewById(R.id.scroll);
+        mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
+                R.id.notification_stack_scroller);
         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
         int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
-        mExpandHelper = new ExpandHelper(getContext(), (ExpandHelper.Callback) latestItems,
+        mExpandHelper = new ExpandHelper(getContext(), mStackScrollLayout,
                 minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
-        mExpandHelper.setScrollView(mScrollView);
+        mExpandHelper.setScrollAdapter(mStackScrollLayout);
 
         // We really need to be able to animate while window animations are going on
         // so that activities may be started asynchronously from panel animations
@@ -94,7 +89,8 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean intercept = false;
-        if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) {
+        if (mNotificationPanel.isFullyExpanded()
+                && mStackScrollLayout.getVisibility() == View.VISIBLE) {
             intercept = mExpandHelper.onInterceptTouchEvent(ev);
         }
         if (!intercept) {
@@ -103,7 +99,7 @@
         if (intercept) {
             MotionEvent cancellation = MotionEvent.obtain(ev);
             cancellation.setAction(MotionEvent.ACTION_CANCEL);
-            latestItems.onInterceptTouchEvent(cancellation);
+            mStackScrollLayout.onInterceptTouchEvent(cancellation);
             cancellation.recycle();
         }
         return intercept;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index d1a9d57..49cf78b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -16,11 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.Typeface;
 import android.graphics.drawable.ShapeDrawable;
@@ -39,14 +36,12 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
 
 public class ZenModeView extends RelativeLayout {
@@ -63,20 +58,21 @@
 
     private static final long DURATION = new ValueAnimator().getDuration();
     private static final long PAGER_DURATION = DURATION / 2;
-    private static final float BOUNCE_SCALE = 0.8f;
     private static final long CLOSE_DELAY = 600;
+    private static final long AUTO_ACTIVATE_DELAY = 100;
 
     private final Context mContext;
-    private final Paint mPathPaint;
-    private final ImageView mSettingsButton;
     private final TextView mModeText;
     private final Switch mModeSwitch;
     private final View mDivider;
     private final UntilPager mUntilPager;
     private final ProgressDots mProgressDots;
+    private final View mDivider2;
+    private final TextView mSettingsButton;
 
     private Adapter mAdapter;
     private boolean mInit;
+    private boolean mAutoActivate;
 
     public ZenModeView(Context context) {
         this(context, null);
@@ -90,29 +86,9 @@
         final int iconSize = mContext.getResources()
                 .getDimensionPixelSize(com.android.internal.R.dimen.notification_large_icon_width);
         final int topRowSize = iconSize * 2 / 3;
-        final int p = topRowSize / 7;
+        final int p = topRowSize / 3;
 
-        mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mPathPaint.setStyle(Paint.Style.STROKE);
-        mPathPaint.setColor(GRAY);
-        mPathPaint.setStrokeWidth(p / 2);
-
-        mSettingsButton = new ImageView(mContext);
-        mSettingsButton.setPadding(p, p, p, p);
-        mSettingsButton.setImageResource(R.drawable.ic_notify_settings_normal);
-        LayoutParams lp = new LayoutParams(topRowSize, topRowSize);
-        lp.topMargin = p;
-        lp.leftMargin = p;
-        addView(mSettingsButton, lp);
-        mSettingsButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                if (mAdapter != null) {
-                    mAdapter.configure();
-                }
-                bounce(mSettingsButton, null);
-            }
-        });
+        LayoutParams lp = null;
 
         mModeText = new TextView(mContext);
         mModeText.setText(MODE_LABEL);
@@ -120,11 +96,10 @@
         mModeText.setTextColor(GRAY);
         mModeText.setTypeface(CONDENSED);
         mModeText.setAllCaps(true);
-        mModeText.setGravity(Gravity.CENTER);
-        mModeText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mModeText.getTextSize() * 1.1f);
+        mModeText.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        mModeText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mModeText.getTextSize() * 1.5f);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
-        lp.topMargin = p;
-        lp.addRule(CENTER_HORIZONTAL);
+        lp.leftMargin = p;
         addView(mModeText, lp);
 
         mModeSwitch = new Switch(mContext);
@@ -132,6 +107,7 @@
         mModeSwitch.setSwitchTypeface(CONDENSED);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
         lp.topMargin = p;
+        lp.rightMargin = p;
         lp.addRule(ALIGN_PARENT_RIGHT);
         lp.addRule(ALIGN_BASELINE, mModeText.getId());
         addView(mModeSwitch, lp);
@@ -154,11 +130,10 @@
         mDivider.setBackgroundColor(GRAY);
         lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
         lp.addRule(BELOW, mModeText.getId());
-        lp.topMargin = p;
-        lp.bottomMargin = p * 2;
+        lp.bottomMargin = p;
         addView(mDivider, lp);
 
-        mUntilPager = new UntilPager(mContext, mPathPaint, iconSize * 3 / 4);
+        mUntilPager = new UntilPager(mContext, iconSize * 3 / 4);
         mUntilPager.setId(android.R.id.tabhost);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         lp.leftMargin = lp.rightMargin = iconSize / 2;
@@ -167,10 +142,41 @@
         addView(mUntilPager, lp);
 
         mProgressDots = new ProgressDots(mContext, iconSize / 5);
+        mProgressDots.setId(android.R.id.progress);
         lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         lp.addRule(CENTER_HORIZONTAL);
         lp.addRule(BELOW, mUntilPager.getId());
         addView(mProgressDots, lp);
+
+        mDivider2 = new View(mContext);
+        mDivider2.setId(android.R.id.widget_frame);
+        mDivider2.setBackgroundColor(GRAY);
+        lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
+        lp.addRule(BELOW, mProgressDots.getId());
+        addView(mDivider2, lp);
+
+        mSettingsButton = new TextView(mContext);
+        mSettingsButton.setTypeface(CONDENSED);
+        mSettingsButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSettingsButton.getTextSize() * 1.3f);
+        mSettingsButton.setPadding(p, p, p, p);
+        mSettingsButton.setText("More settings...");
+        lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+        lp.addRule(BELOW, mDivider2.getId());
+        addView(mSettingsButton, lp);
+        mSettingsButton.setOnTouchListener(new OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                    mSettingsButton.setBackgroundColor(DARK_GRAY);
+                } else if (event.getAction() == MotionEvent.ACTION_UP) {
+                    mSettingsButton.setBackground(null);
+                    if (mAdapter != null) {
+                        mAdapter.configure();
+                    }
+                }
+                return true;
+            }
+        });
     }
 
     public void setAdapter(Adapter adapter) {
@@ -189,6 +195,27 @@
         updateState(false);
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mAutoActivate) {
+            mAutoActivate = false;
+            postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    if (!mModeSwitch.isChecked()) {
+                        mInit = false;
+                        mModeSwitch.setChecked(true);
+                    }
+                }
+            }, AUTO_ACTIVATE_DELAY);
+        }
+    }
+
+    public void setAutoActivate(boolean value) {
+        mAutoActivate = value;
+    }
+
     private void updateState(boolean animate) {
         mUntilPager.updateState();
         mModeSwitch.setChecked(mAdapter.getMode());
@@ -199,23 +226,6 @@
         Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
     }
 
-    private static void bounce(final View v, final Runnable midBounce) {
-        v.animate().scaleX(BOUNCE_SCALE).scaleY(BOUNCE_SCALE).setDuration(DURATION / 3)
-            .setListener(new AnimatorListenerAdapter() {
-                private boolean mFired;
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (!mFired) {
-                        mFired = true;
-                        if (midBounce != null) {
-                            midBounce.run();
-                        }
-                        v.animate().scaleX(1).scaleY(1).setListener(null).start();
-                    }
-                }
-            }).start();
-    }
-
     private final class UntilView extends FrameLayout {
         private static final boolean SUPPORT_LINKS = false;
 
@@ -223,7 +233,7 @@
         public UntilView(Context context) {
             super(context);
             mText = new TextView(mContext);
-            mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText.getTextSize() * 1.2f);
+            mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText.getTextSize() * 1.3f);
             mText.setTypeface(CONDENSED);
             mText.setTextColor(GRAY);
             mText.setGravity(Gravity.CENTER);
@@ -284,7 +294,7 @@
         private int mCurrent;
         private float mDownX;
 
-        public UntilPager(Context context, Paint pathPaint, int iconSize) {
+        public UntilPager(Context context, int iconSize) {
             super(context);
             mViews = new UntilView[3];
             for (int i = 0; i < mViews.length; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 09f1695..92c008e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -126,6 +126,7 @@
     private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
     private String mConnectedNetworkTypeName;
     private int mInetCondition = 0;
+    private int mLastInetCondition = 0;
     private static final int INET_CONDITION_THRESHOLD = 50;
 
     private boolean mAirplaneMode = false;
@@ -156,9 +157,9 @@
     boolean mDataAndWifiStacked = false;
 
     public interface SignalCluster {
-        void setWifiIndicators(boolean visible, int strengthIcon,
+        void setWifiIndicators(boolean visible, int strengthIcon, boolean problem,
                 String contentDescription);
-        void setMobileDataIndicators(boolean visible, int strengthIcon,
+        void setMobileDataIndicators(boolean visible, int strengthIcon, boolean problem,
                 int typeIcon, String contentDescription, String typeContentDescription);
         void setIsAirplaneMode(boolean is, int airplaneIcon);
     }
@@ -288,6 +289,7 @@
                 // only show wifi in the cluster if connected or if wifi-only
                 mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
                 mWifiIconId,
+                mInetCondition == 0,
                 mContentDescriptionWifi);
 
         if (mIsWimaxEnabled && mWimaxConnected) {
@@ -295,6 +297,7 @@
             cluster.setMobileDataIndicators(
                     true,
                     mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
+                    mInetCondition == 0,
                     mDataTypeIconId,
                     mContentDescriptionWimax,
                     mContentDescriptionDataType);
@@ -303,6 +306,7 @@
             cluster.setMobileDataIndicators(
                     mHasMobileDataFeature,
                     mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
+                    mInetCondition == 0,
                     mDataTypeIconId,
                     mContentDescriptionPhoneSignal,
                     mContentDescriptionDataType);
@@ -1145,6 +1149,7 @@
 
         if (mLastPhoneSignalIconId          != mPhoneSignalIconId
          || mLastWifiIconId                 != mWifiIconId
+         || mLastInetCondition              != mInetCondition
          || mLastWimaxIconId                != mWimaxIconId
          || mLastDataTypeIconId             != mDataTypeIconId
          || mLastAirplaneMode               != mAirplaneMode
@@ -1179,6 +1184,10 @@
             mLastWifiIconId = mWifiIconId;
         }
 
+        if (mLastInetCondition != mInetCondition) {
+            mLastInetCondition = mInetCondition;
+        }
+
         // the wimax icon on phones
         if (mLastWimaxIconId != mWimaxIconId) {
             mLastWimaxIconId = mWimaxIconId;
@@ -1424,6 +1433,7 @@
                     cluster.setWifiIndicators(
                             show,
                             iconId,
+                            mDemoInetCondition == 0,
                             "Demo");
                 }
             }
@@ -1456,6 +1466,7 @@
                     cluster.setMobileDataIndicators(
                             show,
                             iconId,
+                            mDemoInetCondition == 0,
                             mDemoDataTypeIconId,
                             "Demo",
                             "Demo");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java
new file mode 100644
index 0000000..f35e22d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.view.View;
+
+/**
+ * A scroll adapter which can be queried for meta information about the scroll state
+ */
+public interface ScrollAdapter {
+
+    /**
+     * @return Whether the view returned by {@link #getHostView()} is scrolled to the top
+     */
+    public boolean isScrolledToTop();
+
+    /**
+     * @return Whether the view returned by {@link #getHostView()} is scrolled to the bottom
+     */
+    public boolean isScrolledToBottom();
+
+    /**
+     * @return The view in which the scrolling is performed
+     */
+    public View getHostView();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index edac3a7..e2d6c5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -22,6 +22,7 @@
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
+
 import android.util.AttributeSet;
 import android.util.Log;
 
@@ -30,19 +31,20 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.widget.OverScroller;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 /**
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
 public class NotificationStackScrollLayout extends ViewGroup
-        implements SwipeHelper.Callback, ExpandHelper.Callback {
+        implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter {
 
     private static final String TAG = "NotificationStackScrollLayout";
     private static final boolean DEBUG = false;
@@ -53,7 +55,7 @@
     private static final int INVALID_POINTER = -1;
 
     private SwipeHelper mSwipeHelper;
-    private boolean mAllowScrolling = true;
+    private boolean mSwipingInProgress = true;
     private int mCurrentStackHeight = Integer.MAX_VALUE;
     private int mOwnScrollY;
     private int mMaxLayoutHeight;
@@ -86,7 +88,9 @@
     /**
      * The current State this Layout is in
      */
-    private StackScrollState mCurrentStackScrollState;
+    private final StackScrollState mCurrentStackScrollState = new StackScrollState(this);
+    
+    private OnChildLocationsChangedListener mListener;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -153,7 +157,6 @@
         // currently the padding is in the elements themself
         mPaddingBetweenElements = 0;
         mStackScrollAlgorithm = new StackScrollAlgorithm(context);
-        mCurrentStackScrollState = null;
     }
 
     @Override
@@ -188,6 +191,24 @@
         updateContentHeight();
     }
 
+    public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Returns the location the given child is currently rendered at.
+     *
+     * @param child the child to get the location for
+     * @return one of {@link ViewState}'s <code>LOCATION_*</code> constants
+     */
+    public int getChildLocation(View child) {
+        ViewState childViewState = mCurrentStackScrollState.getViewStateForView(child);
+        if (childViewState == null) {
+            return ViewState.LOCATION_UNKNOWN;
+        }
+        return childViewState.location;
+    }
+
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
         updateAlgorithmHeight();
@@ -203,13 +224,13 @@
      */
     private void updateChildren() {
         if (!isCurrentlyAnimating()) {
-            if (mCurrentStackScrollState == null) {
-                mCurrentStackScrollState = new StackScrollState(this);
-            }
             mCurrentStackScrollState.setScrollY(mOwnScrollY);
             mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
             mCurrentStackScrollState.apply();
             mOwnScrollY = mCurrentStackScrollState.getScrollY();
+            if (mListener != null) {
+                mListener.onChildLocationsChanged(this);
+            }
         } else {
             // TODO: handle animation
         }
@@ -258,7 +279,7 @@
     }
 
     /**
-     * Get the current height of the view. This is at most the size of the view given by a the
+     * Get the current height of the view. This is at most the msize of the view given by a the
      * layout but it can also be made smaller by setting {@link #mCurrentStackHeight}
      *
      * @return either the layout height or the externally defined height, whichever is smaller
@@ -267,6 +288,14 @@
         return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
     }
 
+    public int getItemHeight() {
+        return mCollapsedSize;
+    }
+
+    public int getBottomStackPeekSize() {
+        return mBottomStackPeekSize;
+    }
+
     public void setLongPressListener(View.OnLongClickListener listener) {
         mSwipeHelper.setLongPressListener(listener);
     }
@@ -277,15 +306,15 @@
         if (veto != null && veto.getVisibility() != View.GONE) {
             veto.performClick();
         }
-        allowScrolling(true);
+        setSwipingInProgress(false);
     }
 
     public void onBeginDrag(View v) {
-        allowScrolling(false);
+        setSwipingInProgress(true);
     }
 
     public void onDragCancelled(View v) {
-        allowScrolling(true);
+        setSwipingInProgress(false);
     }
 
     public View getChildAtPosition(MotionEvent ev) {
@@ -344,8 +373,11 @@
         return (veto != null && veto.getVisibility() != View.GONE);
     }
 
-    private void allowScrolling(boolean allow) {
-        mAllowScrolling = allow;
+    private void setSwipingInProgress(boolean isSwiped) {
+        mSwipingInProgress = isSwiped;
+        if(isSwiped) {
+            requestDisallowInterceptTouchEvent(true);
+        }
     }
 
     @Override
@@ -365,7 +397,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean scrollerWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollerWantsIt = onScrollTouch(ev);
         }
         boolean horizontalSwipeWantsIt = false;
@@ -388,12 +420,6 @@
                 }
                 boolean isBeingDragged = !mScroller.isFinished();
                 setIsBeingDragged(isBeingDragged);
-                if (isBeingDragged) {
-                    final ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
-                }
 
                 /*
                  * If being flinged and user touches, stop the fling. isFinished
@@ -418,10 +444,6 @@
                 final int y = (int) ev.getY(activePointerIndex);
                 int deltaY = mLastMotionY - y;
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
-                    final ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
                     setIsBeingDragged(true);
                     if (deltaY > 0) {
                         deltaY -= mTouchSlop;
@@ -621,7 +643,7 @@
         if (getChildCount() > 0) {
             int contentHeight = getContentHeight();
             scrollRange = Math.max(0,
-                    contentHeight - mMaxLayoutHeight + mCollapsedSize);
+                    contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
         }
         return scrollRange;
     }
@@ -676,7 +698,7 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean scrollWantsIt = false;
-        if (mAllowScrolling) {
+        if (!mSwipingInProgress) {
             scrollWantsIt = onInterceptTouchEventScroll(ev);
         }
         boolean swipeWantsIt = false;
@@ -687,6 +709,12 @@
                 super.onInterceptTouchEvent(ev);
     }
 
+    @Override
+    protected void onViewRemoved(View child) {
+        super.onViewRemoved(child);
+        mCurrentStackScrollState.removeViewStateForView(child);
+    }
+
     private boolean onInterceptTouchEventScroll(MotionEvent ev) {
         /*
          * This method JUST determines whether we want to intercept the motion.
@@ -742,10 +770,6 @@
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
                     mVelocityTracker.addMovement(ev);
-                    final ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
                 }
                 break;
             }
@@ -802,6 +826,7 @@
     private void setIsBeingDragged(boolean isDragged) {
         mIsBeingDragged = isDragged;
         if (isDragged) {
+            requestDisallowInterceptTouchEvent(true);
             mSwipeHelper.removeLongPressCallback();
         }
     }
@@ -813,4 +838,30 @@
             mSwipeHelper.removeLongPressCallback();
         }
     }
+
+    @Override
+    public boolean isScrolledToTop() {
+        return mOwnScrollY == 0;
+    }
+
+    @Override
+    public boolean isScrolledToBottom() {
+        return mOwnScrollY >= getScrollRange();
+    }
+
+    @Override
+    public View getHostView() {
+        return this;
+    }
+
+    public int getEmptyBottomMargin() {
+        return Math.max(getHeight() - mContentHeight, 0);
+    }
+
+    /**
+     * A listener that is notified when some child locations might have changed.
+     */
+    public interface OnChildLocationsChangedListener {
+        public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 9db4e77..4745f3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.stack;
 
 import android.content.Context;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import com.android.systemui.R;
@@ -28,6 +29,8 @@
  */
 public class StackScrollAlgorithm {
 
+    private static final String LOG_TAG = "StackScrollAlgorithm";
+
     private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
     private static final int MAX_ITEMS_IN_TOP_STACK = 3;
 
@@ -83,7 +86,7 @@
         // First we reset the view states to their default values.
         resultState.resetViewStates();
 
-        // The first element is always in there so it's initialized with 1.0f.
+        // The first element is always in there so it's initialized with 1.0f;
         algorithmState.itemsInTopStack = 1.0f;
         algorithmState.partialInTop = 0.0f;
         algorithmState.lastTopStackIndex = 0;
@@ -99,7 +102,7 @@
         // Phase 3:
         updateZValuesForState(resultState, algorithmState);
 
-        // Write the algorithm state to the result.
+        // write the algorithm state to the result
         resultState.setScrollY(algorithmState.scrollY);
     }
 
@@ -130,6 +133,7 @@
             View child = hostView.getChildAt(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             childViewState.yTranslation = currentYPosition;
+            childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
             int childHeight = child.getHeight();
             // The y position after this element
             float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
@@ -143,12 +147,12 @@
                 nextYPosition = updateStateForTopStackChild(algorithmState,
                         numberOfElementsCompletelyIn,
                         i, childViewState);
-
             } else if (i == algorithmState.lastTopStackIndex) {
                 // Case 2:
                 // First element of regular scrollview comes next, so the position is just the
                 // scrolling position
-                nextYPosition = scrollOffset;
+                nextYPosition = Math.min(scrollOffset, transitioningPositionStart);
+                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
             } else if (nextYPosition >= transitioningPositionStart) {
                 if (currentYPosition >= transitioningPositionStart) {
                     // Case 3:
@@ -156,8 +160,6 @@
                     // bottom of the screen so we are fully in the bottom stack
                     nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
                             transitioningPositionStart, childViewState, childHeight);
-
-
                 } else {
                     // Case 4:
                     // According to the regular scroll view we are currently translating out of /
@@ -167,7 +169,18 @@
                             currentYPosition, childViewState,
                             childHeight, nextYPosition);
                 }
+            } else {
+                childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
             }
+            // The first card is always rendered.
+            if (i == 0) {
+                childViewState.alpha = 1.0f;
+                childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
+            }
+            if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) {
+                Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
+            }
+            nextYPosition = Math.max(0, nextYPosition);
             currentYPosition = nextYPosition;
             yPositionInScrollView = yPositionInScrollViewAfterElement;
         }
@@ -192,6 +205,8 @@
         if (childHeight != (int) newSize) {
             childViewState.height = (int) newSize;
         }
+        childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+
         return nextYPosition;
     }
 
@@ -206,6 +221,7 @@
             nextYPosition = transitioningPositionStart
                     + mBottomStackIndentationFunctor.getValue(
                             algorithmState.itemsInBottomStack);
+            childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
         } else {
             // we are fully inside the stack
             if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
@@ -214,6 +230,7 @@
                     > MAX_ITEMS_IN_BOTTOM_STACK + 1) {
                 childViewState.alpha = 1.0f - algorithmState.partialInBottom;
             }
+            childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
             nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
         }
         // TODO: only temporarily collapse
@@ -237,14 +254,18 @@
             nextYPosition = mCollapsedSize + mPaddingBetweenElements -
                     mTopStackIndentationFunctor.getValue(
                             algorithmState.itemsInTopStack - i - 1);
-            if (paddedIndex == 0 && i != 0) {
+            nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize
+                    - mBottomStackPeekSize);
+            if (paddedIndex == 0) {
                 childViewState.alpha = 1.0f - algorithmState.partialInTop;
+                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+            } else {
+                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
             }
         } else {
-            // We are hidden behind the top card and faded out, so we can hide ourselfs
-            if (i != 0) {
-                childViewState.alpha = 0.0f;
-            }
+            // We are hidden behind the top card and faded out, so we can hide ourselves.
+            childViewState.alpha = 0.0f;
+            childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
         }
         return nextYPosition;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index f72a52f..67a1735 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -45,7 +45,7 @@
 
     public StackScrollState(ViewGroup hostView) {
         mHostView = hostView;
-        mStateMap = new HashMap<View, ViewState>(mHostView.getChildCount());
+        mStateMap = new HashMap<View, ViewState>();
     }
 
     public ViewGroup getHostView() {
@@ -72,6 +72,10 @@
         return mStateMap.get(requestedView);
     }
 
+    public void removeViewStateForView(View child) {
+        mStateMap.remove(child);
+    }
+
     /**
      * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
      * The properties are only applied if they effectively changed.
@@ -144,10 +148,28 @@
     }
 
 
-    public class ViewState {
+    public static class ViewState {
+
+        // These are flags such that we can create masks for filtering.
+
+        public static final int LOCATION_UNKNOWN = 0x00;
+        public static final int LOCATION_FIRST_CARD = 0x01;
+        public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
+        public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
+        public static final int LOCATION_MAIN_AREA = 0x08;
+        public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
+        public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
+
         float alpha;
         float yTranslation;
         float zTranslation;
         int height;
+
+        /**
+         * The location this view is currently rendered at.
+         *
+         * <p>See <code>LOCATION_</code> flags.</p>
+         */
+        int location;
     }
 }
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index ef640d5..03d920a 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -1,10 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.vpndialogs">
 
     <application android:label="VpnDialogs"
             android:allowBackup="false" >
         <activity android:name=".ConfirmDialog"
-                android:theme="@*android:style/Theme.Holo.Dialog.Alert">
+                android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.DEFAULT"/>
@@ -12,7 +30,7 @@
         </activity>
 
         <activity android:name=".ManageDialog"
-                android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+                android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
                 android:noHistory="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/packages/WallpaperCropper/AndroidManifest.xml b/packages/WallpaperCropper/AndroidManifest.xml
index 27755bd..81d1085 100644
--- a/packages/WallpaperCropper/AndroidManifest.xml
+++ b/packages/WallpaperCropper/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.wallpapercropper" >
         <uses-permission android:name="android.permission.SET_WALLPAPER" />
diff --git a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
index 97d7001..cf78989 100644
--- a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
+++ b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
@@ -28,7 +28,7 @@
         android:layout_height="match_parent" />
     <ProgressBar
         android:id="@+id/loading"
-        style="@android:style/Widget.Holo.ProgressBar.Large"
+        style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Large"
         android:visibility="invisible"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml
index 2b63fe0..b27a387 100644
--- a/packages/WallpaperCropper/res/values/styles.xml
+++ b/packages/WallpaperCropper/res/values/styles.xml
@@ -15,13 +15,13 @@
 -->
 
 <resources>
-    <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
+    <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
         <item name="android:windowFullscreen">true</item>
         <item name="android:windowActionBarOverlay">true</item>
     </style>
 
-    <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
+    <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.Light.ActionBar">
         <item name="android:displayOptions">showCustom</item>
         <item name="android:background">#88000000</item>
     </style>
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index fb002d2..5c8a8ef8 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -365,12 +365,6 @@
 
         Point inSize = mCropView.getSourceDimensions();
 
-        // Due to rounding errors in the cropview renderer the edges can be slightly offset
-        // therefore we ensure that the boundaries are sanely defined
-        cropRect.left = Math.max(0, cropRect.left);
-        cropRect.right = Math.min(inSize.x, cropRect.right);
-        cropRect.top = Math.max(0, cropRect.top);
-        cropRect.bottom = Math.min(inSize.y, cropRect.bottom);
         int cropRotation = mCropView.getImageRotation();
         float cropScale = mCropView.getWidth() / (float) cropRect.width();
 
@@ -381,6 +375,13 @@
         rotatedInSize[0] = Math.abs(rotatedInSize[0]);
         rotatedInSize[1] = Math.abs(rotatedInSize[1]);
 
+        // Due to rounding errors in the cropview renderer the edges can be slightly offset
+        // therefore we ensure that the boundaries are sanely defined
+        cropRect.left = Math.max(0, cropRect.left);
+        cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
+        cropRect.top = Math.max(0, cropRect.top);
+        cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
+
         // ADJUST CROP WIDTH
         // Extend the crop all the way to the right, for parallax
         // (or all the way to the left, in RTL)
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 0120a03..c6972b1 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -121,13 +121,14 @@
         filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
         context.registerReceiver(mBroadcastReceiver, filter);
 
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
         // get notified of phone state changes
         TelephonyManager telephonyManager =
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
-        ConnectivityManager cm = (ConnectivityManager)
-                context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
                 mAirplaneModeObserver);
@@ -267,7 +268,7 @@
         if (Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
             mItems.add(
-                new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+                new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
                         R.string.global_action_bug_report) {
 
                     public void onPress() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a65f677..79ed866 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -25,6 +25,8 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.app.ActivityOptions;
+import android.os.Looper;
+import android.transition.Fade;
 import android.transition.Scene;
 import android.transition.Transition;
 import android.transition.TransitionInflater;
@@ -109,7 +111,6 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -145,6 +146,7 @@
     TypedValue mFixedWidthMinor;
     TypedValue mFixedHeightMajor;
     TypedValue mFixedHeightMinor;
+    TypedValue mOutsetBottom;
 
     // This is the top-level view of the window, containing the window decor.
     private DecorView mDecor;
@@ -252,8 +254,10 @@
 
     private ActivityOptions mActivityOptions;
     private SceneTransitionListener mSceneTransitionListener;
-    private boolean mTriggerEarly = true;
+    private boolean mAllowEnterOverlap = true;
+    private boolean mAllowExitOverlap = true;
     private Map<String, String> mSharedElementsMap;
+    private ArrayList<View> mTransitioningViews;
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -2370,7 +2374,6 @@
                     } else {
                         h = 0;
                     }
-
                     if (h > 0) {
                         final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
                         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
@@ -2379,6 +2382,15 @@
                 }
             }
 
+            if (mOutsetBottom != null) {
+                int mode = MeasureSpec.getMode(heightMeasureSpec);
+                if (mode != MeasureSpec.UNSPECIFIED) {
+                    int outset = (int) mOutsetBottom.getDimension(metrics);
+                    int height = MeasureSpec.getSize(heightMeasureSpec);
+                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(height + outset, mode);
+                }
+            }
+
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
             int width = getMeasuredWidth();
@@ -2993,6 +3005,10 @@
         if (a.getBoolean(com.android.internal.R.styleable.Window_windowContentTransitions, false)) {
             requestFeature(FEATURE_CONTENT_TRANSITIONS);
         }
+        if (a.hasValue(com.android.internal.R.styleable.Window_windowOutsetBottom)) {
+            if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
+            a.getValue(com.android.internal.R.styleable.Window_windowOutsetBottom, mOutsetBottom);
+        }
 
         final Context context = getContext();
         final int targetSdk = context.getApplicationInfo().targetSdkVersion;
@@ -4068,14 +4084,26 @@
     }
 
     @Override
-    public void setTransitionOptions(ActivityOptions options, SceneTransitionListener listener) {
+    public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
         mSceneTransitionListener = listener;
-        mActivityOptions = options;
+        ActivityOptions activityOptions = null;
+        if (options != null) {
+            activityOptions = new ActivityOptions(options);
+            if (activityOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
+                activityOptions = null;
+            }
+        }
+        mActivityOptions = activityOptions;
     }
 
     @Override
-    public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
-        mTriggerEarly = triggerEarly;
+    public void setAllowOverlappingEnterTransition(boolean allow) {
+        mAllowEnterOverlap = allow;
+    }
+
+    @Override
+    public void setAllowOverlappingExitTransition(boolean allow) {
+        mAllowExitOverlap = allow;
     }
 
     @Override
@@ -4084,7 +4112,50 @@
     }
 
     @Override
-    public Bundle startExitTransition(ActivityOptions activityOptions) {
+    public void restoreViewVisibilityAfterTransitionToCallee() {
+        if (mTransitioningViews != null) {
+            setViewVisibility(mTransitioningViews, View.VISIBLE);
+        }
+    }
+
+    @Override
+    public void startExitTransitionToCaller(final Runnable onTransitionEnd) {
+        Transition transition;
+        if (mContentScene == null || mTransitionManager == null || mActivityOptions == null
+                || (transition = mTransitionManager.getEnterTransition(mContentScene)) == null) {
+            onTransitionEnd.run();
+            return;
+        }
+        if (mAllowExitOverlap) {
+            TransitionSet transitionSet = new TransitionSet();
+            transitionSet.addTransition(transition);
+            Fade fade = new Fade();
+            transitionSet.addTransition(fade);
+            transition = transitionSet;
+        }
+
+        final ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
+        mapSharedElements(sharedElements);
+        final Bundle sharedElementArgs = new Bundle();
+        captureTerminalSharedElementState(sharedElements, sharedElementArgs);
+
+        final ArrayList<View> transitioningViews = new ArrayList<View>();
+        mDecor.captureTransitioningViews(transitioningViews);
+        transitioningViews.removeAll(sharedElements.values());
+
+        mSceneTransitionListener.convertToTranslucent();
+        transition = transition.clone();
+        Rect epicenter = calcEpicenter(sharedElements, mActivityOptions.getSharedElementNames());
+        transition.setEpicenterCallback(new FixedEpicenterCallback(epicenter));
+        ExitSceneBack exitScene =
+                new ExitSceneBack(onTransitionEnd, sharedElementArgs, sharedElements.values());
+        exitScene.start(transition);
+        mTransitionManager.beginDelayedTransition(mDecor, transition);
+        setViewVisibility(transitioningViews, View.INVISIBLE);
+    }
+
+    @Override
+    public Bundle startExitTransitionToCallee(Bundle options) {
         if (mContentScene == null) {
             return null;
         }
@@ -4093,16 +4164,15 @@
             return null;
         }
 
+        ActivityOptions activityOptions = new ActivityOptions(options);
         ArrayMap<String, View> sharedElements = findSharedElements(activityOptions);
 
         // Find exiting Views and shared elements
-        final ArrayList<View> transitioningViews = new ArrayList<View>();
-        mDecor.captureTransitioningViews(transitioningViews);
-        transitioningViews.removeAll(sharedElements.values());
+        ArrayList<View> transitioningViews = captureTransitioningViews(sharedElements.values());
 
-        Transition exitTransition = cloneAndSetTransitionTargets(transition,
+        Transition exitTransition = addTransitionTargets(transition,
                 transitioningViews, true);
-        Transition sharedElementTransition = cloneAndSetTransitionTargets(transition,
+        Transition sharedElementTransition = addTransitionTargets(transition,
                 transitioningViews, false);
 
         // transitionSet is the total exit transition, including hero animation.
@@ -4110,8 +4180,12 @@
         transitionSet.addTransition(exitTransition);
         transitionSet.addTransition(sharedElementTransition);
 
+        Rect epicenter = calcEpicenter(sharedElements, activityOptions.getSharedElementNames());
+        FixedEpicenterCallback epicenterCallback = new FixedEpicenterCallback(epicenter);
+        transitionSet.setEpicenterCallback(epicenterCallback);
+
         updateExitActivityOptions(activityOptions, sharedElements,
-                sharedElementTransition, exitTransition);
+                sharedElementTransition, transitioningViews, exitTransition, epicenterCallback);
 
         // Start exiting the Views that need to exit
         TransitionManager.beginDelayedTransition(mDecor, transitionSet);
@@ -4120,6 +4194,14 @@
         return activityOptions.toBundle();
     }
 
+    private ArrayList<View> captureTransitioningViews(Collection<View> sharedElements) {
+        mTransitioningViews = new ArrayList<View>();
+        mDecor.captureTransitioningViews(mTransitioningViews);
+        ArrayList<View> transitioningViews = (ArrayList<View>) mTransitioningViews.clone();
+        transitioningViews.removeAll(sharedElements);
+        return transitioningViews;
+    }
+
     private ArrayMap<String, View> findSharedElements(ActivityOptions activityOptions) {
         ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
         mDecor.findSharedElements(sharedElements);
@@ -4136,9 +4218,18 @@
         return sharedElements;
     }
 
+    private static void runOnUiThread(Handler handler, Runnable runnable) {
+        if (handler.getLooper() != Looper.myLooper()) {
+            handler.post(runnable);
+        } else {
+            runnable.run();
+        }
+    }
+
     private void updateExitActivityOptions(ActivityOptions activityOptions,
             final Map<String, View> sharedElements, Transition sharedElementTransition,
-            Transition exitTransition) {
+            final ArrayList<View> transitioningViews, Transition exitTransition,
+            final Transition.EpicenterCallback epicenterCallback) {
 
         // Schedule capturing of the shared element state
         final Bundle sharedElementArgs = new Bundle();
@@ -4146,30 +4237,88 @@
 
         ActivityOptions.SharedElementSource sharedElementSource
                 = new ActivityOptions.SharedElementSource() {
+            private Handler mHandler = new Handler();
+
             @Override
             public Bundle getSharedElementExitState() {
                 return sharedElementArgs;
             }
 
             @Override
-            public void acceptedSharedElements(ArrayList<String> sharedElementNames) {
+            public void acceptedSharedElements(final ArrayList<String> sharedElementNames) {
                 if (sharedElementNames.size() == sharedElements.size()) {
                     return; // They were all accepted
                 }
-                Transition transition = mTransitionManager.getExitTransition(mContentScene).clone();
-                TransitionManager.beginDelayedTransition(mDecor, transition);
-                for (String name: sharedElements.keySet()) {
-                    if (!sharedElementNames.contains(name)) {
-                        sharedElements.get(name).setVisibility(View.INVISIBLE);
+                runOnUiThread(mHandler, new Runnable() {
+                    @Override
+                    public void run() {
+                        Transition transition = mTransitionManager.getExitTransition(mContentScene);
+                        transition = transition.clone();
+                        transition.setEpicenterCallback(epicenterCallback);
+                        TransitionManager.beginDelayedTransition(mDecor, transition);
+                        for (String name : sharedElements.keySet()) {
+                            if (!sharedElementNames.contains(name)) {
+                                sharedElements.get(name).setVisibility(View.INVISIBLE);
+                            }
+                        }
+                        sharedElements.keySet().retainAll(sharedElementNames);
                     }
-                }
-                sharedElements.keySet().retainAll(sharedElementNames);
+                });
             }
 
             @Override
             public void hideSharedElements() {
                 if (sharedElements != null) {
-                    setViewVisibility(sharedElements.values(), View.INVISIBLE);
+                    runOnUiThread(mHandler, new Runnable() {
+                        @Override
+                        public void run() {
+                            setViewVisibility(sharedElements.values(), View.INVISIBLE);
+                        }
+                    });
+                }
+            }
+
+            @Override
+            public void restore(final Bundle sharedElementState) {
+                runOnUiThread(mHandler, new Runnable() {
+                    @Override
+                    public void run() {
+                        mTransitioningViews = null;
+                        Transition transition = mTransitionManager.getExitTransition(mContentScene);
+                        transition = transition.clone();
+                        transition.setEpicenterCallback(epicenterCallback);
+                        setSharedElementState(sharedElements, sharedElementState);
+                        setViewVisibility(sharedElements.values(), View.VISIBLE);
+                        if (mSceneTransitionListener != null) {
+                            mSceneTransitionListener.sharedElementStart(transition);
+                            mDecor.getViewTreeObserver().addOnPreDrawListener(
+                                    new ViewTreeObserver.OnPreDrawListener() {
+                                        @Override
+                                        public boolean onPreDraw() {
+                                            mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+                                            mSceneTransitionListener.sharedElementEnd();
+                                            return true;
+                                        }
+                                    });
+                        }
+                        TransitionManager.beginDelayedTransition(mDecor, transition);
+                        setViewVisibility(transitioningViews, View.VISIBLE);
+                        for (View sharedElement: sharedElements.values()) {
+                            sharedElement.requestLayout();
+                        }
+                    }
+                });
+            }
+
+            @Override
+            public void prepareForRestore() {
+                if (mTransitioningViews != null) {
+                    runOnUiThread(mHandler, new Runnable() {
+                        @Override
+                        public void run() {
+                            setViewVisibility(mTransitioningViews, View.INVISIBLE);
+                        }
+                    });
                 }
             }
         };
@@ -4194,22 +4343,18 @@
         });
     }
 
-    private static Transition cloneAndSetTransitionTargets(Transition transition,
-            List<View> views, boolean add) {
-        transition = transition.clone();
-        if (!transition.getTargetIds().isEmpty() || !transition.getTargets().isEmpty()) {
-            TransitionSet set = new TransitionSet();
-            set.addTransition(transition);
-            transition = set;
-        }
+    private static Transition addTransitionTargets(Transition transition, Collection<View> views,
+            boolean add) {
+        TransitionSet set = new TransitionSet();
+        set.addTransition(transition.clone());
         for (View view: views) {
             if (add) {
-                transition.addTarget(view);
+                set.addTarget(view);
             } else {
-                transition.excludeTarget(view, true);
+                set.excludeTarget(view, true);
             }
         }
-        return transition;
+        return set;
     }
 
     private static void setViewVisibility(Collection<View> views, int visibility) {
@@ -4218,6 +4363,14 @@
         }
     }
 
+    private static void setSharedElementState(Map<String, View> sharedElements,
+            Bundle sharedElementState) {
+        int[] tempLoc = new int[2];
+        for (Map.Entry<String, View> entry: sharedElements.entrySet()) {
+            setSharedElementState(entry.getValue(), entry.getKey(), sharedElementState, tempLoc);
+        }
+    }
+
     /**
      * Sets the captured values from a previous
      * {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
@@ -4234,23 +4387,27 @@
             return;
         }
 
-        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
-        view.getLocationOnScreen(tempLoc);
-        int offsetX = x - tempLoc[0];
-        view.offsetLeftAndRight(offsetX);
-
-        int width = sharedElementBundle.getInt(KEY_WIDTH);
-        view.setRight(view.getLeft() + width);
-
-        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
-        int offsetY = y - tempLoc[1];
-        view.offsetTopAndBottom(offsetY);
-
-        int height = sharedElementBundle.getInt(KEY_HEIGHT);
-        view.setBottom(view.getTop() + height);
-
         float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
         view.setTranslationZ(z);
+
+        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
+        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
+        int width = sharedElementBundle.getInt(KEY_WIDTH);
+        int height = sharedElementBundle.getInt(KEY_HEIGHT);
+
+        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
+        view.measure(widthSpec, heightSpec);
+
+        ViewGroup parent = (ViewGroup) view.getParent();
+        parent.getLocationOnScreen(tempLoc);
+        int left = x - tempLoc[0];
+        int top = y - tempLoc[1];
+        int right = left + width;
+        int bottom = top + height;
+        view.layout(left, top, right, bottom);
+
+        view.requestLayout();
     }
 
     /**
@@ -4284,6 +4441,124 @@
         transitionArgs.putBundle(name, sharedElementBundle);
     }
 
+    private void mapSharedElements(ArrayMap<String, View> sharedElements) {
+        ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
+        if (sharedElementNames != null) {
+            mDecor.findSharedElements(sharedElements);
+            if (mSharedElementsMap != null) {
+                for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
+                    View sharedElement = sharedElements.remove(entry.getValue());
+                    if (sharedElement != null) {
+                        sharedElements.put(entry.getKey(), sharedElement);
+                    }
+                }
+            }
+            sharedElements.keySet().retainAll(sharedElementNames);
+        }
+    }
+
+    private static Rect calcEpicenter(ArrayMap<String, View> sharedElements,
+            ArrayList<String> sharedElementNames) {
+        if (sharedElementNames != null) {
+            for (String name: sharedElementNames) {
+                if (name.startsWith("android:")) {
+                    return null;
+                }
+                View view = sharedElements.get(name);
+                if (view != null) {
+                    int[] loc = new int[2];
+                    view.getLocationOnScreen(loc);
+                    int left = loc[0] + Math.round(view.getTranslationX());
+                    int top = loc[1] + Math.round(view.getTranslationY());
+                    int right = left + view.getWidth();
+                    int bottom = top + view.getHeight();
+                    return new Rect(left, top, right, bottom);
+                }
+            }
+        }
+        return null;
+    }
+
+    private class ExitSceneBack extends Transition.TransitionListenerAdapter implements
+            Animator.AnimatorListener {
+        private boolean mExitTransitionComplete;
+        private boolean mBackgroundFadeComplete;
+        private boolean mOnCompleteExecuted;
+        private boolean mSharedElementTransitioned;
+        private Runnable mOnComplete;
+        private Bundle mSharedElementArgs;
+        private Collection<View> mSharedElements;
+
+        public ExitSceneBack(Runnable onComplete, Bundle sharedElementArgs,
+                Collection<View> sharedElements) {
+            mOnComplete = onComplete;
+            mSharedElementArgs = sharedElementArgs;
+            mSharedElements = sharedElements;
+        }
+
+        public void start(Transition exitTransition) {
+            if (mActivityOptions != null) {
+                mActivityOptions.dispatchPrepareRestore();
+            }
+            exitTransition.addListener(this);
+            Drawable background = mDecor.getBackground();
+            if (background != null) {
+                ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 0);
+                animator.addListener(this);
+                animator.start();
+            } else {
+                mBackgroundFadeComplete = true;
+                startCalledActivityEnter();
+            }
+        }
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            transition.removeListener(this);
+            mExitTransitionComplete = true;
+            notifyComplete();
+            if (!mAllowExitOverlap) {
+                startCalledActivityEnter();
+            }
+        }
+
+        private void notifyComplete() {
+            if (mExitTransitionComplete && mBackgroundFadeComplete
+                    && mSharedElementTransitioned && !mOnCompleteExecuted) {
+                mOnComplete.run();
+                mSceneTransitionListener.nullPendingTransition();
+                mOnCompleteExecuted = true;
+            }
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mBackgroundFadeComplete = true;
+            if (mAllowExitOverlap) {
+                startCalledActivityEnter();
+            }
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+
+        private void startCalledActivityEnter() {
+            mActivityOptions.dispatchRestore(mSharedElementArgs);
+            setViewVisibility(mSharedElements, View.INVISIBLE);
+            mSharedElementTransitioned = true;
+            notifyComplete();
+        }
+    }
+
     /**
      * Provides code for handling the Activity transition entering scene.
      * When the first scene is laid out (onPreDraw), it makes views invisible.
@@ -4304,6 +4579,7 @@
         private boolean mEnterTransitionStarted;
         private ArrayMap<String, View> mSharedElementTargets = new ArrayMap<String, View>();
         private ArrayList<View> mEnteringViews = new ArrayList<View>();
+        private Transition.EpicenterCallback mEpicenterCallback;
 
         public EnterScene() {
             mSceneTransitionListener.nullPendingTransition();
@@ -4322,33 +4598,25 @@
             if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
                 mEnterTransitionStarted = true;
                 mDecor.captureTransitioningViews(mEnteringViews);
-                ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
-                if (sharedElementNames != null) {
-                    mDecor.findSharedElements(mSharedElementTargets);
-                    if (mSharedElementsMap != null) {
-                        for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
-                            View sharedElement = mSharedElementTargets.remove(entry.getValue());
-                            if (sharedElement != null) {
-                                mSharedElementTargets.put(entry.getKey(), sharedElement);
-                            }
-                        }
-                    }
-                    mSharedElementTargets.keySet().retainAll(sharedElementNames);
-                    mEnteringViews.removeAll(mSharedElementTargets.values());
-                }
+                mapSharedElements(mSharedElementTargets);
+                mEnteringViews.removeAll(mSharedElementTargets.values());
+                Rect epicenter = calcEpicenter(mSharedElementTargets,
+                        mActivityOptions.getSharedElementNames());
+                mEpicenterCallback = new FixedEpicenterCallback(epicenter);
 
                 setViewVisibility(mEnteringViews, View.INVISIBLE);
                 setViewVisibility(mSharedElementTargets.values(), View.INVISIBLE);
-                if (mTriggerEarly) {
+                if (mAllowEnterOverlap) {
                     beginEnterScene();
                 }
                 observer.addOnPreDrawListener(this);
+                return false;
             } else {
                 mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
                 mActivityOptions.dispatchSceneTransitionStarted(this,
                         new ArrayList<String>(mSharedElementTargets.keySet()));
+                return !mSharedElementReadyReceived;
             }
-            return true;
         }
 
         public void start() {
@@ -4362,43 +4630,48 @@
         }
 
         @Override
-        public void sharedElementTransitionComplete(Bundle transitionArgs) {
+        public void sharedElementTransitionComplete(final Bundle transitionArgs) {
             if (!mSharedElementReadyReceived) {
                 mSharedElementReadyReceived = true;
                 mHandler.removeCallbacks(this);
                 mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
                 if (!mSharedElementTargets.isEmpty()) {
-                    Transition transition = getTransitionManager().getEnterTransition(
-                            mContentScene);
-                    if (transition == null) {
-                        transition = TransitionManager.getDefaultTransition();
-                    }
-                    transition = transition.clone();
-                    if (transitionArgs == null) {
-                        TransitionManager.beginDelayedTransition(mDecor, transition);
-                        setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
-                    } else {
-                        int[] tempLoc = new int[2];
-                        for (Map.Entry<String, View> entry: mSharedElementTargets.entrySet()) {
-                            setSharedElementState(entry.getValue(), entry.getKey(), transitionArgs,
-                                    tempLoc);
+                    runOnUiThread(mHandler, new Runnable() {
+                        @Override
+                        public void run() {
+                            Transition transition = getTransitionManager().getEnterTransition(
+                                    mContentScene);
+                            if (transition == null) {
+                                transition = TransitionManager.getDefaultTransition();
+                            }
+                            transition = addTransitionTargets(transition,
+                                    mSharedElementTargets.values(),
+                                    true);
+                            transition.setEpicenterCallback(mEpicenterCallback);
+                            if (transitionArgs == null) {
+                                TransitionManager.beginDelayedTransition(mDecor, transition);
+                                setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+                            } else {
+                                mSceneTransitionListener.sharedElementStart(transition);
+                                setSharedElementState(mSharedElementTargets, transitionArgs);
+                                setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+                                mDecor.getViewTreeObserver().addOnPreDrawListener(
+                                        new ViewTreeObserver.OnPreDrawListener() {
+                                            @Override
+                                            public boolean onPreDraw() {
+                                                mDecor.getViewTreeObserver()
+                                                        .removeOnPreDrawListener(this);
+                                                mSceneTransitionListener.sharedElementEnd();
+                                                mActivityOptions.dispatchSharedElementsReady();
+                                                return true;
+                                            }
+                                        });
+                                TransitionManager.beginDelayedTransition(mDecor, transition);
+                            }
                         }
-                        setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
-                        mSceneTransitionListener.sharedElementStart(transition);
-                        mDecor.getViewTreeObserver().addOnPreDrawListener(
-                                new ViewTreeObserver.OnPreDrawListener() {
-                                    @Override
-                                    public boolean onPreDraw() {
-                                        mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
-                                        mSceneTransitionListener.sharedElementEnd();
-                                        mActivityOptions.dispatchSharedElementsReady();
-                                        return true;
-                                    }
-                                });
-                        TransitionManager.beginDelayedTransition(mDecor, transition);
-                    }
+                    });
                 }
-                if (mTriggerEarly) {
+                if (mAllowEnterOverlap) {
                     fadeInBackground();
                 }
             }
@@ -4423,9 +4696,14 @@
             mAllDone = true;
             sharedElementTransitionComplete(null);
             mHandler.removeCallbacks(this);
-            if (!mTriggerEarly) {
-                beginEnterScene();
-                fadeInBackground();
+            if (!mAllowEnterOverlap) {
+                runOnUiThread(mHandler, new Runnable() {
+                    @Override
+                    public void run() {
+                        beginEnterScene();
+                        fadeInBackground();
+                    }
+                });
             }
         }
 
@@ -4449,10 +4727,25 @@
         private void beginEnterScene() {
             Transition transition = getTransitionManager().getEnterTransition(mContentScene);
             if (transition == null) {
-                transition = TransitionManager.getDefaultTransition().clone();
+                transition = TransitionManager.getDefaultTransition();
             }
+            transition = addTransitionTargets(transition, mEnteringViews, true);
+            transition.setEpicenterCallback(mEpicenterCallback);
             TransitionManager.beginDelayedTransition(mDecor, transition);
             setViewVisibility(mEnteringViews, View.VISIBLE);
         }
     }
+
+    private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
+        private Rect mEpicenter;
+
+        public FixedEpicenterCallback(Rect epicenter) {
+            mEpicenter = epicenter;
+        }
+
+        @Override
+        public Rect getEpicenter(Transition transition) {
+            return mEpicenter;
+        }
+    };
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ededbb2..ccdacea 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3417,8 +3417,9 @@
             }
 
             final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
+            final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
             if (appWindow) {
-                if (showWhenLocked) {
+                if (showWhenLocked || (dismissKeyguard && !isKeyguardSecure())) {
                     mAppsToBeHidden.remove(win.getAppToken());
                 } else {
                     mAppsToBeHidden.add(win.getAppToken());
@@ -3435,8 +3436,7 @@
                             mHideLockScreen = true;
                             mForceStatusBarFromKeyguard = false;
                         }
-                        if ((fl & FLAG_DISMISS_KEYGUARD) != 0
-                                && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                        if (dismissKeyguard && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
                             if (DEBUG_LAYOUT) Slog.v(TAG,
                                     "Setting mDismissKeyguard true by win " + win);
                             mDismissKeyguard = mWinDismissingKeyguard == win ?
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 714e835..6178994 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -225,9 +225,13 @@
         validate();
         //android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
 
+        Surface s = null;
+        if (sur != null) {
+            s = new Surface(sur);
+        }
         mWidth = w;
         mHeight = h;
-        nContextSetSurfaceTexture(w, h, sur);
+        nContextSetSurface(w, h, s);
     }
 
     /**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b7c1704..2f56e62 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1751,7 +1751,8 @@
                 for (int i = 0; i < N; i++) {
                     AppWidgetId id = mAppWidgetIds.get(i);
                     if (backupTarget.equals(id.host.packageName)
-                            || backupTarget.equals(id.provider.info.provider.getPackageName())) {
+                            || (id.provider != null && backupTarget.equals(
+                                    id.provider.info.provider.getPackageName()))) {
                         serializeAppWidgetId(out, id);
                     }
                 }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1a1512f..0b688b6 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2035,6 +2035,7 @@
         BackupState mCurrentState;
 
         // carried information about the current in-flight operation
+        IBackupAgent mAgentBinder;
         PackageInfo mCurrentPackage;
         File mSavedStateName;
         File mBackupDataName;
@@ -2097,6 +2098,7 @@
                 addBackupTrace(b.toString());
             }
 
+            mAgentBinder = null;
             mStatus = BackupConstants.TRANSPORT_OK;
 
             // Sanity check: if the queue is empty we have no work to do.
@@ -2228,6 +2230,7 @@
                             IApplicationThread.BACKUP_MODE_INCREMENTAL);
                     addBackupTrace("agent bound; a? = " + (agent != null));
                     if (agent != null) {
+                        mAgentBinder = agent;
                         mStatus = invokeAgentForBackup(request.packageName, agent, mTransport);
                         // at this point we'll either get a completion callback from the
                         // agent, or a timeout message on the main handler.  either way, we're
@@ -2253,6 +2256,7 @@
                 // That means we need to direct to the next state ourselves.
                 if (mStatus != BackupConstants.TRANSPORT_OK) {
                     BackupState nextState = BackupState.RUNNING_QUEUE;
+                    mAgentBinder = null;
 
                     // An agent-level failure means we reenqueue this one agent for
                     // a later retry, but otherwise proceed normally.
@@ -2274,6 +2278,7 @@
 
                     executeNextState(nextState);
                 } else {
+                    // success case
                     addBackupTrace("expecting completion/timeout callback");
                 }
             }
@@ -2402,14 +2407,52 @@
             return BackupConstants.TRANSPORT_OK;
         }
 
+        public void failAgent(IBackupAgent agent, String message) {
+            try {
+                agent.fail(message);
+            } catch (Exception e) {
+                Slog.w(TAG, "Error conveying failure to " + mCurrentPackage.packageName);
+            }
+        }
+
         @Override
         public void operationComplete() {
-            // Okay, the agent successfully reported back to us.  The next thing we do is
-            // push the app widget state for the app, if any.
+            // Okay, the agent successfully reported back to us!
             final String pkgName = mCurrentPackage.packageName;
             final long filepos = mBackupDataName.length();
             FileDescriptor fd = mBackupData.getFileDescriptor();
             try {
+                // If it's a 3rd party app, see whether they wrote any protected keys
+                // and complain mightily if they are attempting shenanigans.
+                if (mCurrentPackage.applicationInfo != null &&
+                        (mCurrentPackage.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataName,
+                            ParcelFileDescriptor.MODE_READ_ONLY);
+                    BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
+                    try {
+                        while (in.readNextHeader()) {
+                            final String key = in.getKey();
+                            if (key != null && key.charAt(0) >= 0xff00) {
+                                // Not okay: crash them and bail.
+                                failAgent(mAgentBinder, "Illegal backup key: " + key);
+                                addBackupTrace("illegal key " + key + " from " + pkgName);
+                                EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
+                                        "bad key");
+                                mBackupHandler.removeMessages(MSG_TIMEOUT);
+                                agentErrorCleanup();
+                                // agentErrorCleanup() implicitly executes next state properly
+                                return;
+                            }
+                            in.skipEntityData();
+                        }
+                    } finally {
+                        if (readFd != null) {
+                            readFd.close();
+                        }
+                    }
+                }
+
+                // Piggyback the widget state payload, if any
                 BackupDataOutput out = new BackupDataOutput(fd);
                 byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName,
                         UserHandle.USER_OWNER);
@@ -2434,8 +2477,7 @@
                 }
             }
 
-            // Spin the data off to the
-            // transport and proceed with the next stage.
+            // Spin the data off to the transport and proceed with the next stage.
             if (MORE_DEBUG) Slog.v(TAG, "operationComplete(): sending data to transport for "
                     + pkgName);
             mBackupHandler.removeMessages(MSG_TIMEOUT);
@@ -4648,7 +4690,11 @@
 
     // ----- Restore handling -----
 
-    private boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
+    static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
+        if (target == null) {
+            return false;
+        }
+
         // If the target resides on the system partition, we allow it to restore
         // data from the like-named package in a restore set even if the signatures
         // do not match.  (Unlike general applications, those flashed to the system
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 495da88..132579d 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -19,15 +19,19 @@
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
+import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.util.Slog;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
@@ -42,6 +46,8 @@
 import java.util.List;
 import java.util.Set;
 
+import java.util.Objects;
+
 /**
  * We back up the signatures of each package so that during a system restore,
  * we can verify that the app whose data we think we have matches the app
@@ -58,6 +64,9 @@
     // is stored using the package name as a key)
     private static final String GLOBAL_METADATA_KEY = "@meta@";
 
+    // key under which we store the identity of the user's chosen default home app
+    private static final String DEFAULT_HOME_KEY = "@home@";
+
     private List<PackageInfo> mAllPackages;
     private PackageManager mPackageManager;
     // version & signature info of each app in a restore set
@@ -68,7 +77,15 @@
     private final HashSet<String> mExisting = new HashSet<String>();
     private int mStoredSdkVersion;
     private String mStoredIncrementalVersion;
+    private ComponentName mStoredHomeComponent;
+    private long mStoredHomeVersion;
+    private Signature[] mStoredHomeSigs;
+
     private boolean mHasMetadata;
+    private ComponentName mRestoredHome;
+    private long mRestoredHomeVersion;
+    private String mRestoredHomeInstaller;
+    private Signature[] mRestoredHomeSignatures;
 
     public class Metadata {
         public int versionCode;
@@ -136,7 +153,50 @@
             mExisting.clear();
         }
 
+        long homeVersion = 0;
+        Signature[] homeSigs = null;
+        PackageInfo homeInfo = null;
+        String homeInstaller = null;
+        ComponentName home = getPreferredHomeComponent();
+        if (home != null) {
+            try {
+                homeInfo = mPackageManager.getPackageInfo(home.getPackageName(),
+                        PackageManager.GET_SIGNATURES);
+                homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
+                homeVersion = homeInfo.versionCode;
+                homeSigs = homeInfo.signatures;
+            } catch (NameNotFoundException e) {
+                Slog.w(TAG, "Can't access preferred home info");
+                // proceed as though there were no preferred home set
+                home = null;
+            }
+        }
+
         try {
+            // We need to push a new preferred-home-app record if:
+            //    1. the version of the home app has changed since our last backup;
+            //    2. the home app [or absence] we now use differs from the prior state,
+            // OR 3. it looks like we use the same home app + version as before, but
+            //       the signatures don't match so we treat them as different apps.
+            final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
+                    || Objects.equals(home, mStoredHomeComponent)
+                    || (home != null
+                        && !BackupManagerService.signaturesMatch(mStoredHomeSigs, homeInfo));
+            if (needHomeBackup) {
+                if (DEBUG) {
+                    Slog.i(TAG, "Home preference changed; backing up new state " + home);
+                }
+                if (home != null) {
+                    outputBufferStream.writeUTF(home.flattenToString());
+                    outputBufferStream.writeLong(homeVersion);
+                    outputBufferStream.writeUTF(homeInstaller != null ? homeInstaller : "" );
+                    writeSignatureArray(outputBufferStream, homeSigs);
+                    writeEntity(data, DEFAULT_HOME_KEY, outputBuffer.toByteArray());
+                } else {
+                    data.writeEntityHeader(DEFAULT_HOME_KEY, -1);
+                }
+            }
+
             /*
              * Global metadata:
              *
@@ -146,6 +206,7 @@
              * String incremental -- the incremental release name of the OS stored in
              *                       the backup set.
              */
+            outputBuffer.reset();
             if (!mExisting.contains(GLOBAL_METADATA_KEY)) {
                 if (DEBUG) Slog.v(TAG, "Storing global metadata key");
                 outputBufferStream.writeInt(Build.VERSION.SDK_INT);
@@ -238,7 +299,7 @@
         }
 
         // Finally, write the new state blob -- just the list of all apps we handled
-        writeStateFile(mAllPackages, newState);
+        writeStateFile(mAllPackages, home, homeVersion, homeSigs, newState);
     }
     
     private static void writeEntity(BackupDataOutput data, String key, byte[] bytes)
@@ -286,6 +347,19 @@
                             + " (" + mStoredIncrementalVersion + " vs "
                             + Build.VERSION.INCREMENTAL + ")");
                 }
+            } else if (key.equals(DEFAULT_HOME_KEY)) {
+                String cn = inputBufferStream.readUTF();
+                mRestoredHome = ComponentName.unflattenFromString(cn);
+                mRestoredHomeVersion = inputBufferStream.readLong();
+                mRestoredHomeInstaller = inputBufferStream.readUTF();
+                mRestoredHomeSignatures = readSignatureArray(inputBufferStream);
+                if (DEBUG) {
+                    Slog.i(TAG, "   read preferred home app " + mRestoredHome
+                            + " version=" + mRestoredHomeVersion
+                            + " installer=" + mRestoredHomeVersion
+                            + " sig=" + mRestoredHomeVersion);
+                }
+
             } else {
                 // it's a file metadata record
                 int versionCode = inputBufferStream.readInt();
@@ -365,18 +439,34 @@
         mStateVersions.clear();
         mStoredSdkVersion = 0;
         mStoredIncrementalVersion = null;
+        mStoredHomeComponent = null;
+        mStoredHomeVersion = 0;
+        mStoredHomeSigs = null;
 
         // The state file is just the list of app names we have stored signatures for
         // with the exception of the metadata block, to which is also appended the
         // version numbers corresponding with the last time we wrote this PM block.
         // If they mismatch the current system, we'll re-store the metadata key.
         FileInputStream instream = new FileInputStream(stateFile.getFileDescriptor());
-        DataInputStream in = new DataInputStream(instream);
+        BufferedInputStream inbuffer = new BufferedInputStream(instream);
+        DataInputStream in = new DataInputStream(inbuffer);
 
-        int bufSize = 256;
-        byte[] buf = new byte[bufSize];
         try {
             String pkg = in.readUTF();
+
+            // First comes the preferred home app data, if any, headed by the DEFAULT_HOME_KEY tag
+            if (pkg.equals(DEFAULT_HOME_KEY)) {
+                // flattened component name, version, signature of the home app
+                mStoredHomeComponent = ComponentName.unflattenFromString(in.readUTF());
+                mStoredHomeVersion = in.readLong();
+                mStoredHomeSigs = readSignatureArray(in);
+
+                pkg = in.readUTF(); // set up for the next block of state
+            } else {
+                // else no preferred home app on the ancestral device - fall through to the rest
+            }
+
+            // After (possible) home app data comes the global metadata block
             if (pkg.equals(GLOBAL_METADATA_KEY)) {
                 mStoredSdkVersion = in.readInt();
                 mStoredIncrementalVersion = in.readUTF();
@@ -386,7 +476,7 @@
                 return;
             }
 
-            // The global metadata was first; now read all the apps
+            // The global metadata was last; now read all the apps
             while (true) {
                 pkg = in.readUTF();
                 int versionCode = in.readInt();
@@ -401,13 +491,28 @@
         }
     }
 
-    // Util: write out our new backup state file
-    private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
-        FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
-        DataOutputStream out = new DataOutputStream(outstream);
+    private ComponentName getPreferredHomeComponent() {
+        return mPackageManager.getHomeActivities(new ArrayList<ResolveInfo>());
+    }
 
+    // Util: write out our new backup state file
+    private void writeStateFile(List<PackageInfo> pkgs, ComponentName preferredHome,
+            long homeVersion, Signature[] homeSignatures, ParcelFileDescriptor stateFile) {
+        FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
+        BufferedOutputStream outbuf = new BufferedOutputStream(outstream);
+        DataOutputStream out = new DataOutputStream(outbuf);
+
+        // by the time we get here we know we've done all our backing up
         try {
-            // by the time we get here we know we've stored the global metadata record
+            // If we remembered a preferred home app, record that
+            if (preferredHome != null) {
+                out.writeUTF(DEFAULT_HOME_KEY);
+                out.writeUTF(preferredHome.flattenToString());
+                out.writeLong(homeVersion);
+                writeSignatureArray(out, homeSignatures);
+            }
+
+            // Conclude with the metadata block
             out.writeUTF(GLOBAL_METADATA_KEY);
             out.writeInt(Build.VERSION.SDK_INT);
             out.writeUTF(Build.VERSION.INCREMENTAL);
@@ -417,9 +522,10 @@
                 out.writeUTF(pkg.packageName);
                 out.writeInt(pkg.versionCode);
             }
+
+            out.flush();
         } catch (IOException e) {
             Slog.e(TAG, "Unable to write package manager state file!");
-            return;
         }
     }
 }
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 0f78c9b..9768934 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -58,7 +58,11 @@
 2751 notification_cancel (uid|1|5),(pid|1|5),(pkg|3),(id|1|5),(tag|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
 # when someone tries to cancel all of the notifications for a particular package
 2752 notification_cancel_all (uid|1|5),(pid|1|5),(pkg|3),(userid|1|5),(required_flags|1),(forbidden_flags|1),(reason|1|5),(listener|3)
-
+# when the notification panel is shown
+# Note: New tag range starts here since 2753+ have been used below.
+27500 notification_panel_revealed
+# when the notification panel is hidden
+27501 notification_panel_hidden
 
 # ---------------------------
 # Watchdog.java
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5fb6405..6fc3e77 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -148,6 +148,7 @@
     static final int MSG_UNBIND_METHOD = 3000;
     static final int MSG_BIND_METHOD = 3010;
     static final int MSG_SET_ACTIVE = 3020;
+    static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 3030;
 
     static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
 
@@ -445,7 +446,7 @@
                 return;
             } else if (Intent.ACTION_USER_ADDED.equals(action)
                     || Intent.ACTION_USER_REMOVED.equals(action)) {
-                updateRelatedUserIds();
+                updateCurrentProfileIds();
                 return;
             } else {
                 Slog.w(TAG, "Unexpected intent " + intent);
@@ -689,7 +690,7 @@
         // mSettings should be created before buildInputMethodListLocked
         mSettings = new InputMethodSettings(
                 mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
-        updateRelatedUserIds();
+        updateCurrentProfileIds();
         mFileManager = new InputMethodFileManager(mMethodMap, userId);
         mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings);
         mSwitchingController.resetCircularListLocked(context);
@@ -805,7 +806,7 @@
 
     private void switchUserLocked(int newUserId) {
         mSettings.setCurrentUserId(newUserId);
-        updateRelatedUserIds();
+        updateCurrentProfileIds();
         // InputMethodFileManager should be reset when the user is changed
         mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
         final String defaultImiId = mSettings.getSelectedInputMethod();
@@ -826,14 +827,14 @@
         }
     }
 
-    void updateRelatedUserIds() {
-        List<UserInfo> relatedUsers =
-                UserManager.get(mContext).getRelatedUsers(mSettings.getCurrentUserId());
-        int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
-        for (int i = 0; i < relatedUserIds.length; i++) {
-            relatedUserIds[i] = relatedUsers.get(i).id;
+    void updateCurrentProfileIds() {
+        List<UserInfo> profiles =
+                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
+        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+        for (int i = 0; i < currentProfileIds.length; i++) {
+            currentProfileIds[i] = profiles.get(i).id;
         }
-        mSettings.setRelatedUserIds(relatedUserIds);
+        mSettings.setCurrentProfileIds(currentProfileIds);
     }
 
     @Override
@@ -931,7 +932,7 @@
                     + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
                     + InputMethodUtils.getApiCallStack());
         }
-        if (uid == Process.SYSTEM_UID || mSettings.isRelatedToOrCurrentUser(userId)) {
+        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
             return true;
         }
 
@@ -2275,6 +2276,27 @@
         }
     }
 
+    @Override
+    public void setCursorAnchorMonitorMode(IBinder token, int monitorMode) {
+        if (DEBUG) {
+            Slog.d(TAG, "setCursorAnchorMonitorMode: monitorMode=" + monitorMode);
+        }
+        if (!calledFromValidUser()) {
+            return;
+        }
+        synchronized (mMethodMap) {
+            if (token == null || mCurToken != token) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Ignoring setCursorAnchorMonitorMode from uid "
+                            + Binder.getCallingUid() + " token: " + token);
+                }
+                return;
+            }
+            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
+                    MSG_SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, mCurClient));
+        }
+    }
+
     private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
         synchronized (mMethodMap) {
             if (token == null) {
@@ -2506,6 +2528,15 @@
                             + ((ClientState)msg.obj).uid);
                 }
                 return true;
+            case MSG_SET_CURSOR_ANCHOR_MONITOR_MODE:
+                try {
+                    ((ClientState)msg.obj).client.setCursorAnchorMonitorMode(msg.arg1);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Got RemoteException sending setCursorAnchorMonitorMode "
+                            + "notification to pid " + ((ClientState)msg.obj).pid
+                            + " uid " + ((ClientState)msg.obj).uid);
+                }
+                return true;
 
             // --------------------------------------------------------------
             case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index fe814fc..0d2cee8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -30,7 +30,11 @@
 import android.database.sqlite.SQLiteStatement;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.storage.IMountService;
+import android.os.ServiceManager;
+import android.os.storage.StorageManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -79,6 +83,7 @@
 
     private final Context mContext;
     private LockPatternUtils mLockPatternUtils;
+    private boolean mFirstCallToVold;
 
     public LockSettingsService(Context context) {
         mContext = context;
@@ -86,6 +91,7 @@
         mOpenHelper = new DatabaseHelper(mContext);
 
         mLockPatternUtils = new LockPatternUtils(context);
+        mFirstCallToVold = true;
     }
 
     public void systemReady() {
@@ -347,6 +353,51 @@
     }
 
     @Override
+        public boolean checkVoldPassword(int userId) throws RemoteException {
+        if (!mFirstCallToVold) {
+            return false;
+        }
+        mFirstCallToVold = false;
+
+        checkPasswordReadPermission(userId);
+
+        // There's no guarantee that this will safely connect, but if it fails
+        // we will simply show the lock screen when we shouldn't, so relatively
+        // benign. There is an outside chance something nasty would happen if
+        // this service restarted before vold stales out the password in this
+        // case. The nastiness is limited to not showing the lock screen when
+        // we should, within the first minute of decrypting the phone if this
+        // service can't connect to vold, it restarts, and then the new instance
+        // does successfully connect.
+        final IMountService service = getMountService();
+        String password = service.getPassword();
+        service.clearPassword();
+        if (password == null) {
+            return false;
+        }
+
+        try {
+            if (mLockPatternUtils.isLockPatternEnabled()) {
+                if (checkPattern(password, userId)) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        try {
+            if (mLockPatternUtils.isLockPasswordEnabled()) {
+                if (checkPassword(password, userId)) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        return false;
+    }
+
+    @Override
     public void removeUser(int userId) {
         checkWritePermission(userId);
 
@@ -524,4 +575,12 @@
         Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
         Secure.LOCK_SCREEN_OWNER_INFO
     };
+
+    private IMountService getMountService() {
+        final IBinder service = ServiceManager.getService("mount");
+        if (service != null) {
+            return IMountService.Stub.asInterface(service);
+        }
+        return null;
+    }
 }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index cd74fed..b6e761c 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -74,6 +74,7 @@
 import com.google.android.collect.Maps;
 
 import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.DecoderException;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -157,6 +158,7 @@
         public static final int VolumeListResult               = 110;
         public static final int AsecListResult                 = 111;
         public static final int StorageUsersListResult         = 112;
+        public static final int CryptfsGetfieldResult          = 113;
 
         /*
          * 200 series - Requestion action has been successfully completed.
@@ -573,6 +575,14 @@
         }
     }
 
+    private boolean isReady() {
+        try {
+            return mConnectedSignal.await(0, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+
     private void handleSystemReady() {
         // Snapshot current volume states since it's not safe to call into vold
         // while holding locks.
@@ -2075,12 +2085,25 @@
 
     private String toHex(String password) {
         if (password == null) {
-            return null;
+            return new String();
         }
         byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
         return new String(Hex.encodeHex(bytes));
     }
 
+    private String fromHex(String hexPassword) {
+        if (hexPassword == null) {
+            return null;
+        }
+
+        try {
+            byte[] bytes = Hex.decodeHex(hexPassword.toCharArray());
+            return new String(bytes, StandardCharsets.UTF_8);
+        } catch (DecoderException e) {
+            return null;
+        }
+    }
+
     @Override
     public int decryptStorage(String password) {
         if (TextUtils.isEmpty(password)) {
@@ -2229,6 +2252,78 @@
         }
     }
 
+    /**
+     * Set a field in the crypto header.
+     * @param field field to set
+     * @param contents contents to set in field
+     */
+    @Override
+    public void setField(String field, String contents) throws RemoteException {
+
+        waitForReady();
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "setfield", field, contents);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    /**
+     * Gets a field from the crypto header.
+     * @param field field to get
+     * @return contents of field
+     */
+    @Override
+    public String getField(String field) throws RemoteException {
+
+        waitForReady();
+
+        final NativeDaemonEvent event;
+        try {
+            final String[] contents = NativeDaemonEvent.filterMessageList(
+                    mConnector.executeForList("cryptfs", "getfield", field),
+                    VoldResponseCode.CryptfsGetfieldResult);
+            String result = new String();
+            for (String content : contents) {
+                result += content;
+            }
+            return result;
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public String getPassword() throws RemoteException {
+        if (!isReady()) {
+            return new String();
+        }
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "getpw");
+            return fromHex(event.getMessage());
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void clearPassword() throws RemoteException {
+        if (!isReady()) {
+            return;
+        }
+
+        final NativeDaemonEvent event;
+        try {
+            event = mConnector.execute("cryptfs", "clearpw");
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
     @Override
     public int mkdirs(String callingPkg, String appPath) {
         final int userId = UserHandle.getUserId(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 94f699f..f59edc7 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -71,6 +71,7 @@
     private boolean mCarModeKeepsScreenOn;
     private boolean mDeskModeKeepsScreenOn;
     private boolean mTelevision;
+    private boolean mWatch;
     private boolean mComputedNightMode;
 
     int mCurUiMode = 0;
@@ -176,6 +177,7 @@
                 PackageManager.FEATURE_TELEVISION) ||
             context.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_LEANBACK);
+        mWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
 
         mNightMode = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
@@ -339,8 +341,12 @@
     }
 
     private void updateConfigurationLocked() {
-        int uiMode = mTelevision ? Configuration.UI_MODE_TYPE_TELEVISION : mDefaultUiModeType;
-        if (mCarModeEnabled) {
+        int uiMode = mDefaultUiModeType;
+        if (mTelevision) {
+            uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
+        } else if (mWatch) {
+            uiMode = Configuration.UI_MODE_TYPE_WATCH;
+        } else if (mCarModeEnabled) {
             uiMode = Configuration.UI_MODE_TYPE_CAR;
         } else if (isDeskDockState(mDockState)) {
             uiMode = Configuration.UI_MODE_TYPE_DESK;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5fa9084..e9be1d7d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -43,6 +43,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
@@ -61,8 +62,6 @@
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
-import dalvik.system.Zygote;
-
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -945,6 +944,11 @@
      */
     boolean mDidDexOpt;
 
+    /**
+     * Set if the systemServer made a call to enterSafeMode.
+     */
+    boolean mSafeMode;
+
     String mDebugApp = null;
     boolean mWaitForDebugger = false;
     boolean mDebugTransient = false;
@@ -1015,7 +1019,7 @@
     final ActivityThread mSystemThread;
 
     int mCurrentUserId = 0;
-    int[] mRelatedUserIds = new int[0]; // Accessed by ActivityStack
+    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack
     private UserManagerService mUserManager;
 
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1074,7 +1078,7 @@
     static final int IMMERSIVE_MODE_LOCK_MSG = 37;
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
-    static final int START_RELATED_USERS_MSG = 40;
+    static final int START_PROFILES_MSG = 40;
     static final int UPDATE_TIME = 41;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1689,9 +1693,9 @@
                 requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                 break;
             }
-            case START_RELATED_USERS_MSG: {
+            case START_PROFILES_MSG: {
                 synchronized (ActivityManagerService.this) {
-                    startRelatedUsersLocked();
+                    startProfilesLocked();
                 }
                 break;
             }
@@ -2737,7 +2741,7 @@
             // Run the app in safe mode if its manifest requests so or the
             // system is booted in safe mode.
             if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
-                Zygote.systemInSafeMode == true) {
+                mSafeMode == true) {
                 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
             }
             if ("1".equals(SystemProperties.get("debug.checkjni"))) {
@@ -5204,7 +5208,7 @@
                                 userId);
                     }
                 }
-                scheduleStartRelatedUsersLocked();
+                scheduleStartProfilesLocked();
             }
         }
     }
@@ -6859,8 +6863,8 @@
                             maxNum < N ? maxNum : N);
 
             final Set<Integer> includedUsers;
-            if ((flags & ActivityManager.RECENT_INCLUDE_RELATED) != 0) {
-                includedUsers = getRelatedUsersLocked(userId);
+            if ((flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0) {
+                includedUsers = getProfileIdsLocked(userId);
             } else {
                 includedUsers = new HashSet<Integer>();
             }
@@ -6895,18 +6899,27 @@
                     rti.stackId = tr.stack.mStackId;
                     rti.userId = tr.userId;
 
+                    // Traverse upwards looking for any break between main task activities and
+                    // utility activities.
                     final ArrayList<ActivityRecord> activities = tr.mActivities;
-                    int numSet = 0;
-                    for (int activityNdx = activities.size() - 1; activityNdx >= 0 && numSet < 2;
-                            --activityNdx) {
+                    int activityNdx;
+                    final int numActivities = activities.size();
+                    for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
+                            ++activityNdx) {
                         final ActivityRecord r = activities.get(activityNdx);
-                        if (rti.activityLabel == null && r.recentsLabel != null) {
-                            rti.activityLabel = r.recentsLabel;
-                            ++numSet;
+                        if (r.intent != null &&
+                                (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
+                                        != 0) {
+                            break;
                         }
-                        if (rti.activityIcon == null && r.recentsIcon != null) {
-                            rti.activityIcon = r.recentsIcon;
-                            ++numSet;
+                    }
+                    // Traverse downwards starting below break looking for set label and icon.
+                    for (--activityNdx; activityNdx >= 0; --activityNdx) {
+                        final ActivityRecord r = activities.get(activityNdx);
+                        if (r.activityLabel != null || r.activityIcon != null) {
+                            rti.activityLabel = r.activityLabel;
+                            rti.activityIcon = r.activityIcon;
+                            break;
                         }
                     }
 
@@ -6975,21 +6988,13 @@
     }
 
     @Override
-    public void setRecentsLabel(IBinder token, CharSequence recentsLabel) {
+    public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
+            Bitmap activityIcon) {
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.recentsLabel = recentsLabel.toString();
-            }
-        }
-    }
-
-    @Override
-    public void setRecentsIcon(IBinder token, Bitmap recentsIcon) {
-        synchronized (this) {
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r != null) {
-                r.recentsIcon = recentsIcon;
+                r.activityLabel = activityLabel.toString();
+                r.activityIcon = activityIcon;
             }
         }
     }
@@ -8963,6 +8968,8 @@
                 } catch (RemoteException e) {
                 }
             }
+
+            mSafeMode = true;
         }
     }
 
@@ -16311,19 +16318,19 @@
      * user switch happens or when a new related user is started in the
      * background.
      */
-    private void updateRelatedUserIdsLocked() {
-        final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
-        int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
-        for (int i = 0; i < relatedUserIds.length; i++) {
-            relatedUserIds[i] = relatedUsers.get(i).id;
+    private void updateCurrentProfileIdsLocked() {
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+        for (int i = 0; i < currentProfileIds.length; i++) {
+            currentProfileIds[i] = profiles.get(i).id;
         }
-        mRelatedUserIds = relatedUserIds;
+        mCurrentProfileIds = currentProfileIds;
     }
 
-    private Set getRelatedUsersLocked(int userId) {
+    private Set getProfileIdsLocked(int userId) {
         Set userIds = new HashSet<Integer>();
-        final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(userId);
-        for (UserInfo user : relatedUsers) {
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(userId);
+        for (UserInfo user : profiles) {
             userIds.add(Integer.valueOf(user.id));
         }
         return userIds;
@@ -16384,15 +16391,15 @@
 
                 if (foreground) {
                     mCurrentUserId = userId;
-                    updateRelatedUserIdsLocked();
-                    mWindowManager.setCurrentUser(userId, mRelatedUserIds);
+                    updateCurrentProfileIdsLocked();
+                    mWindowManager.setCurrentUser(userId, mCurrentProfileIds);
                     // Once the internal notion of the active user has switched, we lock the device
                     // with the option to show the user switcher on the keyguard.
                     mWindowManager.lockNow(null);
                 } else {
                     final Integer currentUserIdInt = Integer.valueOf(mCurrentUserId);
-                    updateRelatedUserIdsLocked();
-                    mWindowManager.updateRelatedUserIds(mRelatedUserIds);
+                    updateCurrentProfileIdsLocked();
+                    mWindowManager.setCurrentProfileIds(mCurrentProfileIds);
                     mUserLru.remove(currentUserIdInt);
                     mUserLru.add(currentUserIdInt);
                 }
@@ -16612,20 +16619,21 @@
         }
     }
 
-    void scheduleStartRelatedUsersLocked() {
-        if (!mHandler.hasMessages(START_RELATED_USERS_MSG)) {
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(START_RELATED_USERS_MSG),
+    void scheduleStartProfilesLocked() {
+        if (!mHandler.hasMessages(START_PROFILES_MSG)) {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
                     DateUtils.SECOND_IN_MILLIS);
         }
     }
 
-    void startRelatedUsersLocked() {
-        if (DEBUG_MU) Slog.i(TAG_MU, "startRelatedUsersLocked");
-        List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
-        List<UserInfo> toStart = new ArrayList<UserInfo>(relatedUsers.size());
-        for (UserInfo relatedUser : relatedUsers) {
-            if ((relatedUser.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED) {
-                toStart.add(relatedUser);
+    void startProfilesLocked() {
+        if (DEBUG_MU) Slog.i(TAG_MU, "startProfilesLocked");
+        List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        List<UserInfo> toStart = new ArrayList<UserInfo>(profiles.size());
+        for (UserInfo user : profiles) {
+            if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED
+                    && user.id != mCurrentUserId) {
+                toStart.add(user);
             }
         }
         final int n = toStart.size();
@@ -16634,7 +16642,7 @@
             startUserInBackground(toStart.get(i).id);
         }
         if (i < n) {
-            Slog.w(TAG_MU, "More related users than MAX_RUNNING_USERS");
+            Slog.w(TAG_MU, "More profiles than MAX_RUNNING_USERS");
         }
     }
 
@@ -16653,7 +16661,7 @@
                         true, false, MY_PID, Process.SYSTEM_UID, userId);
             }
 
-            startRelatedUsersLocked();
+            startProfilesLocked();
 
             int num = mUserLru.size();
             int i = 0;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
old mode 100644
new mode 100755
index 77f5c59..d596472
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -148,8 +148,8 @@
     boolean mStartingWindowShown = false;
     ActivityContainer mInitialActivityContainer;
 
-    String recentsLabel;
-    Bitmap recentsIcon;
+    String activityLabel;
+    Bitmap activityIcon;
 
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
@@ -522,13 +522,6 @@
         if (fullscreen == toOpaque) {
             return false;
         }
-        AttributeCache.Entry ent =
-                AttributeCache.instance().get(packageName, realTheme, styleable.Window, userId);
-        if (ent == null
-                || !ent.array.getBoolean(styleable.Window_windowIsTranslucent, false)
-                || ent.array.getBoolean(styleable.Window_windowIsFloating, false)) {
-            return false;
-        }
 
         // Keep track of the number of fullscreen activities in this task.
         task.numFullscreen += toOpaque ? +1 : -1;
@@ -956,8 +949,8 @@
         // for another app to start, then we have paused dispatching
         // for this activity.
         ActivityRecord r = this;
-        final ActivityStack stack = task.stack;
         if (r.waitingVisible) {
+            final ActivityStack stack = mStackSupervisor.getFocusedStack();
             // Hmmm, who might we be waiting for?
             r = stack.mResumedActivity;
             if (r == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3db3a26..b894724 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -341,18 +341,18 @@
     }
 
     /**
-     * Checks whether the userid is either the current user or a related user.
+     * Checks whether the userid is a profile of the current user.
      */
-    private boolean isRelatedToOrCurrentUserLocked(int userId) {
-        if (mCurrentUser == userId) return true;
-        for (int i = 0; i < mService.mRelatedUserIds.length; i++) {
-            if (mService.mRelatedUserIds[i] == userId) return true;
+    private boolean isCurrentProfileLocked(int userId) {
+        if (userId == mCurrentUser) return true;
+        for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
+            if (mService.mCurrentProfileIds[i] == userId) return true;
         }
         return false;
     }
 
     boolean okToShowLocked(ActivityRecord r) {
-        return isRelatedToOrCurrentUserLocked(r.userId)
+        return isCurrentProfileLocked(r.userId)
                 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
     }
 
@@ -571,7 +571,7 @@
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             TaskRecord task = mTaskHistory.get(taskNdx);
-            if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+            if (!isCurrentProfileLocked(task.userId)) {
                 return null;
             }
             final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -602,7 +602,7 @@
         int index = mTaskHistory.size();
         for (int i = 0; i < index; ) {
             TaskRecord task = mTaskHistory.get(i);
-            if (isRelatedToOrCurrentUserLocked(task.userId)) {
+            if (isCurrentProfileLocked(task.userId)) {
                 if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
                         " moving " + task + " to top");
                 mTaskHistory.remove(i);
@@ -1189,6 +1189,7 @@
                         // At this point, nothing else needs to be shown
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
                         behindFullscreen = true;
+                        showHomeBehindStack = false;
                     } else if (isActivityOverHome(r)) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
                         showHomeBehindStack = true;
@@ -1765,10 +1766,10 @@
         mTaskHistory.remove(task);
         // Now put task at top.
         int stackNdx = mTaskHistory.size();
-        if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+        if (!isCurrentProfileLocked(task.userId)) {
             // Put non-current user tasks below current user tasks.
             while (--stackNdx >= 0) {
-                if (!isRelatedToOrCurrentUserLocked(mTaskHistory.get(stackNdx).userId)) {
+                if (!isCurrentProfileLocked(mTaskHistory.get(stackNdx).userId)) {
                     break;
                 }
             }
@@ -2707,6 +2708,9 @@
         if (mResumedActivity == r) {
             mResumedActivity = null;
         }
+        if (mPausingActivity == r) {
+            mPausingActivity = null;
+        }
         if (mService.mFocusedActivity == r) {
             mService.mFocusedActivity = null;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
index 9916435..64b51c9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
@@ -27,8 +27,12 @@
 import java.util.List;
 
 /**
- * CecDevice class represents a CEC logical device characterized
- * by its device type. A physical device can contain the functions of
+ * HdmiCecDevice class represents a CEC logical device characterized
+ * by its device type. It is a superclass of those serving concrete device type.
+ * Currently we're interested in playback(one of sources), display(sink) device type
+ * only. The support for the other types like recorder, audio system will come later.
+ *
+ * <p>A physical device can contain the functions of
  * more than one logical device, in which case it should create
  * as many logical devices as necessary.
  *
@@ -41,7 +45,7 @@
  *
  * <p>Declared as package-private, accessed by HdmiCecService only.
  */
-final class HdmiCecDevice {
+abstract class HdmiCecDevice {
     private static final String TAG = "HdmiCecDevice";
 
     private final int mType;
@@ -49,19 +53,38 @@
     // List of listeners to the message/event coming to the device.
     private final List<IHdmiCecListener> mListeners = new ArrayList<IHdmiCecListener>();
     private final Binder mBinder = new Binder();
+    private final HdmiCecService mService;
 
-    private String mName;
     private boolean mIsActiveSource;
 
     /**
+     * Factory method that creates HdmiCecDevice instance to the device type.
+     */
+    public static HdmiCecDevice create(HdmiCecService service, int type) {
+        if (type == HdmiCec.DEVICE_PLAYBACK) {
+            return new HdmiCecDevicePlayback(service, type);
+        } else if (type == HdmiCec.DEVICE_TV) {
+            return new HdmiCecDeviceTv(service, type);
+        }
+        return null;
+    }
+
+    /**
      * Constructor.
      */
-    public HdmiCecDevice(int type) {
+    public HdmiCecDevice(HdmiCecService service, int type) {
+        mService = service;
         mType = type;
         mIsActiveSource = false;
     }
 
     /**
+     * Called right after the class is instantiated. This method can be used to
+     * implement any initialization tasks for the instance.
+     */
+    abstract public void initialize();
+
+    /**
      * Return the binder token that identifies this instance.
      */
     public Binder getToken() {
@@ -69,6 +92,13 @@
     }
 
     /**
+     * Return the service instance.
+     */
+    public HdmiCecService getService() {
+        return mService;
+    }
+
+    /**
      * Return the type of this device.
      */
     public int getType() {
@@ -76,24 +106,6 @@
     }
 
     /**
-     * Set the name of the device. The name will be transferred via the message
-     * &lt;Set OSD Name&gt; to other HDMI-CEC devices connected through HDMI
-     * cables and shown on TV screen to identify the devicie.
-     *
-     * @param name name of the device
-     */
-    public void setName(String name) {
-        mName = name;
-    }
-
-    /**
-     * Return the name of this device.
-     */
-    public String getName() {
-        return mName;
-    }
-
-    /**
      * Register a listener to be invoked when events occur.
      *
      * @param listener the listern that will run
@@ -128,6 +140,7 @@
         if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE) {
             mIsActiveSource = false;
         }
+
         if (mListeners.size() == 0) {
             return;
         }
@@ -167,4 +180,13 @@
     public void setIsActiveSource(boolean state) {
         mIsActiveSource = state;
     }
+
+    /**
+     * Check if the connected sink device is in powered-on state. The default implementation
+     * simply returns false. Should be overriden by subclass to report the correct state.
+     */
+    public boolean isSinkDeviceOn() {
+        Log.w(TAG, "Not valid for the device type: " + mType);
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
new file mode 100644
index 0000000..0310264
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+/**
+ * Class for the logical device of playback type. Devices such as DVD/Blueray player
+ * that support 'playback' feature are classified as playback device. It is common
+ * that they don't have built-in display, therefore need to talk, stream their contents
+ * to TV/display device which is connected through HDMI cable.
+ *
+ * <p>It closely monitors the status of display device (other devices can be of interest
+ * too, but with much less priority), declares itself as 'active source' to have
+ * display show its output, switch the source state as ordered by display that may be
+ * talking to many other devices connected to it. It also receives commands from display
+ * such as remote control signal, standby, status report, playback mode.
+ *
+ * <p>Declared as package-private, accessed by HdmiCecService only.
+ */
+final class HdmiCecDevicePlayback extends HdmiCecDevice {
+    private static final String TAG = "HdmiCecDevicePlayback";
+
+    private int mSinkDevicePowerStatus;
+
+    /**
+     * Constructor.
+     */
+    public HdmiCecDevicePlayback(HdmiCecService service, int type) {
+        super(service, type);
+        mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN;
+    }
+
+    @Override
+    public void initialize() {
+        // Playback device tries to obtain the power status of TV/display when created,
+        // and maintains it all through its lifecycle. CEC spec says there is
+        // a maximum 1 second response time. Therefore it should be kept in mind
+        // that there can be as much amount of period of time the power status
+        // of the display remains unknown after the query is sent out.
+        queryTvPowerStatus();
+    }
+
+    private void queryTvPowerStatus() {
+        getService().sendMessage(getType(), HdmiCec.ADDR_TV,
+                HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, HdmiCecService.EMPTY_PARAM);
+    }
+
+    @Override
+    public void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) {
+        // Updates power status of display. The cases are:
+        // 1) Response for the queried power status request arrives. Update the status.
+        // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going
+        //    into standby mode too.
+        // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up.
+        if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) {
+            mSinkDevicePowerStatus = params[0];
+        } else if (srcAddress == HdmiCec.ADDR_TV) {
+            if (opcode == HdmiCec.MESSAGE_STANDBY) {
+                mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY;
+            } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) {
+                mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON;
+            }
+        }
+        super.handleMessage(srcAddress, dstAddress, opcode, params);
+    }
+
+    @Override
+    public void handleHotplug(boolean connected) {
+        // If cable get disconnected sink device becomes unreachable. Switch the status
+        // to unknown, and query the status once the cable gets connected back.
+        if (!connected) {
+            mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN;
+        } else {
+            queryTvPowerStatus();
+        }
+        super.handleHotplug(connected);
+    }
+
+    @Override
+    public boolean isSinkDeviceOn() {
+        return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java
new file mode 100644
index 0000000..09ff3ca
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+/**
+ * Class for logical device of TV type.
+ */
+final class HdmiCecDeviceTv extends HdmiCecDevice {
+    private static final String TAG = "HdmiCecDeviceTv";
+
+    /**
+     * Constructor.
+     */
+    public HdmiCecDeviceTv(HdmiCecService service, int type) {
+        super(service, type);
+    }
+
+    public void initialize() {
+        // TODO: Do the initialization task for TV device here.
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java
index 36a6e84..aa496c5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java
@@ -23,6 +23,7 @@
 import android.hardware.hdmi.IHdmiCecListener;
 import android.hardware.hdmi.IHdmiCecService;
 import android.os.Binder;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.text.TextUtils;
@@ -30,6 +31,7 @@
 import android.util.SparseArray;
 
 import com.android.server.SystemService;
+import libcore.util.EmptyArray;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -63,6 +65,8 @@
 
     private static final String PERMISSION = "android.permission.HDMI_CEC";
 
+    static final byte[] EMPTY_PARAM = EmptyArray.BYTE;
+
     public HdmiCecService(Context context) {
         super(context);
     }
@@ -72,7 +76,12 @@
     @Override
     public void onStart() {
         mNativePtr = nativeInit(this);
-        publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService());
+        if (mNativePtr != 0) {
+            // TODO: Consider using a dedicated, configurable identifier for OSD name, maybe from
+            //       Settings. It should be ASCII only, not a very long one (limited to 15 chars).
+            setOsdNameLocked(Build.MODEL);
+            publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService());
+        }
     }
 
     /**
@@ -84,7 +93,6 @@
         //       but better be handled in service by turning off the screen
         //       or putting the device into suspend mode. List up such messages
         //       and handle them here.
-        int type = HdmiCec.getTypeFromAddress(dstAddress);
         synchronized (mLock) {
             if (dstAddress == HdmiCec.ADDR_BROADCAST) {
                 for (int i = 0; i < mLogicalDevices.size(); ++i) {
@@ -92,6 +100,7 @@
                             params);
                 }
             } else {
+                int type = HdmiCec.getTypeFromAddress(dstAddress);
                 HdmiCecDevice device = mLogicalDevices.get(type);
                 if (device == null) {
                     Log.w(TAG, "logical device not found. type: " + type);
@@ -134,22 +143,6 @@
     }
 
     /**
-     * Called by native when a request for the device OSD name was received.
-     * The native part uses the return value to generate the message
-     * &lt;Set Osd Name&gt; in response.
-     */
-    private byte[] getOsdName(int type) {
-        // TODO: Consider getting the OSD name from device name instead.
-        synchronized (mLock) {
-            HdmiCecDevice device = mLogicalDevices.get(type);
-            if (device != null) {
-                return device.getName().getBytes(Charset.forName("US-ASCII"));
-            }
-        }
-        return null;
-    }
-
-    /**
      * Called by native when a request for the menu language of the device was
      * received. The native part uses the return value to generate the message
      * &lt;Set Menu Language&gt; in response. The language should be of
@@ -170,8 +163,7 @@
         synchronized (mLock) {
             for (int i = 0; i < mLogicalDevices.size(); ++i) {
                 HdmiCecDevice device = mLogicalDevices.valueAt(i);
-                pw.println("Device: name=" + device.getName() +
-                           ", type=" + device.getType() +
+                pw.println("Device: type=" + device.getType() +
                            ", active=" + device.isActiveSource());
             }
         }
@@ -201,6 +193,15 @@
         throw new IllegalArgumentException("Device not found");
     }
 
+    // package-private. Used by HdmiCecDevice and its subclasses only.
+    void sendMessage(int type, int address, int opcode, byte[] params) {
+        nativeSendMessage(mNativePtr, type, address, opcode, params);
+    }
+
+    private void setOsdNameLocked(String name) {
+        nativeSetOsdName(mNativePtr, name.getBytes(Charset.forName("US-ASCII")));
+    }
+
     private final class ListenerRecord implements IBinder.DeathRecipient {
         private final IHdmiCecListener mListener;
         private final int mType;
@@ -244,8 +245,12 @@
                         Log.e(TAG, "Logical address was not allocated");
                         return null;
                     } else {
-                        device = new HdmiCecDevice(type);
-                        device.setName(HdmiCec.getDefaultDeviceName(address));
+                        device = HdmiCecDevice.create(HdmiCecService.this, type);
+                        if (device == null) {
+                            Log.e(TAG, "Device type not supported yet.");
+                            return null;
+                        }
+                        device.initialize();
                         mLogicalDevices.put(type, device);
                     }
                 }
@@ -268,24 +273,18 @@
         }
 
         @Override
-        public void setOsdName(IBinder b, String name) {
-            enforceAccessPermission();
-            if (TextUtils.isEmpty(name)) {
-                throw new IllegalArgumentException("name must not be null");
-            }
-            synchronized (mLock) {
-                HdmiCecDevice device = getLogicalDeviceLocked(b);
-                device.setName(name);
-            }
-        }
-
-        @Override
         public void sendActiveSource(IBinder b) {
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
                 device.setIsActiveSource(true);
-                nativeSendActiveSource(mNativePtr, device.getType());
+                int physicalAddress = nativeGetPhysicalAddress(mNativePtr);
+                byte[] param = new byte[] {
+                    (byte) ((physicalAddress >> 8) & 0xff),
+                    (byte) (physicalAddress & 0xff)
+                };
+                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
+                        HdmiCec.MESSAGE_ACTIVE_SOURCE, param);
             }
         }
 
@@ -295,7 +294,8 @@
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
                 device.setIsActiveSource(false);
-                nativeSendInactiveSource(mNativePtr, device.getType());
+                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
+                        HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM);
             }
         }
 
@@ -304,7 +304,8 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                nativeSendImageViewOn(mNativePtr, device.getType());
+                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
+                        HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM);
             }
         }
 
@@ -313,16 +314,17 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                nativeSendTextViewOn(mNativePtr, device.getType());
+                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
+                        HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM);
             }
         }
 
         @Override
-        public void sendGiveDevicePowerStatus(IBinder b, int address) {
+        public boolean isTvOn(IBinder b) {
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                nativeSendGiveDevicePowerStatus(mNativePtr, device.getType(), address);
+                return device.isSinkDeviceOn();
             }
         }
 
@@ -366,7 +368,8 @@
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
                 pw.println("Permission denial: can't dump HdmiCecService from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                        + " without permission " + android.Manifest.permission.DUMP);
                 return;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -382,10 +385,6 @@
     private static native void nativeRemoveLogicalAddress(long handler, int deviceType);
     private static native void nativeSendMessage(long handler, int deviceType, int destination,
             int opcode, byte[] params);
-    private static native void nativeSendActiveSource(long handler, int deviceType);
-    private static native void nativeSendInactiveSource(long handler, int deviceType);
-    private static native void nativeSendImageViewOn(long handler, int deviceType);
-    private static native void nativeSendTextViewOn(long handler, int deviceType);
-    private static native void nativeSendGiveDevicePowerStatus(long handler, int deviceType,
-            int address);
+    private static native int nativeGetPhysicalAddress(long handler);
+    private static native void nativeSetOsdName(long handler, byte[] name);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 4c8dcc3..e0591a2 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -29,5 +29,6 @@
             String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId);
     void onPanelRevealed();
+    void onPanelHidden();
     boolean allowDisable(int what, IBinder token, String pkg);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e25e42c..6534783 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -51,6 +51,7 @@
 import android.media.IRingtonePlayer;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -65,8 +66,8 @@
 import android.service.notification.StatusBarNotification;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.AtomicFile;
-import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -76,9 +77,9 @@
 import android.widget.Toast;
 
 import com.android.internal.R;
-
 import com.android.internal.notification.NotificationScorer;
 import com.android.server.EventLogTags;
+import com.android.server.notification.NotificationUsageStats.SingleNotificationStats;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.SystemService;
 import com.android.server.lights.Light;
@@ -169,7 +170,8 @@
     // used as a mutex for access to all active notifications & listeners
     final ArrayList<NotificationRecord> mNotificationList =
             new ArrayList<NotificationRecord>();
-
+    final ArrayMap<String, NotificationRecord> mNotificationsByKey =
+            new ArrayMap<String, NotificationRecord>();
     final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
 
     ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
@@ -184,10 +186,10 @@
     // things that will be put into mListeners as soon as they're ready
     private ArrayList<String> mServicesBinding = new ArrayList<String>();
     // lists the component names of all enabled (and therefore connected) listener
-    // app services for the current user only
-    private HashSet<ComponentName> mEnabledListenersForCurrentUser
+    // app services for current profiles.
+    private HashSet<ComponentName> mEnabledListenersForCurrentProfiles
             = new HashSet<ComponentName>();
-    // Just the packages from mEnabledListenersForCurrentUser
+    // Just the packages from mEnabledListenersForCurrentProfiles
     private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();
 
     // Notification control database. For now just contains disabled packages.
@@ -205,6 +207,8 @@
 
     final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
 
+    private final NotificationUsageStats mUsageStats = new NotificationUsageStats();
+
     private int mZenMode;
     // temporary, until we update apps to provide metadata
     private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
@@ -216,8 +220,8 @@
             ));
     private static final String EXTRA_INTERCEPT = "android.intercept";
 
-    // Users related to the current user.
-    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+    // Profiles of the current user.
+    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
@@ -239,32 +243,40 @@
         int userid;
         boolean isSystem;
         ServiceConnection connection;
+        int targetSdkVersion;
 
         public NotificationListenerInfo(INotificationListener listener, ComponentName component,
-                int userid, boolean isSystem) {
+                int userid, boolean isSystem, int targetSdkVersion) {
             this.listener = listener;
             this.component = component;
             this.userid = userid;
             this.isSystem = isSystem;
             this.connection = null;
+            this.targetSdkVersion = targetSdkVersion;
         }
 
         public NotificationListenerInfo(INotificationListener listener, ComponentName component,
-                int userid, ServiceConnection connection) {
+                int userid, ServiceConnection connection, int targetSdkVersion) {
             this.listener = listener;
             this.component = component;
             this.userid = userid;
             this.isSystem = false;
             this.connection = connection;
+            this.targetSdkVersion = targetSdkVersion;
         }
 
         boolean enabledAndUserMatches(StatusBarNotification sbn) {
             final int nid = sbn.getUserId();
-            if (!isEnabledForCurrentUser()) {
+            if (!isEnabledForCurrentProfiles()) {
                 return false;
             }
             if (this.userid == UserHandle.USER_ALL) return true;
-            return (nid == UserHandle.USER_ALL || nid == this.userid);
+            if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
+            return supportsProfiles() && isCurrentProfile(nid);
+        }
+
+        boolean supportsProfiles() {
+            return targetSdkVersion >= Build.VERSION_CODES.L;
         }
 
         public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
@@ -296,11 +308,11 @@
             removeListenerImpl(this.listener, this.userid);
         }
 
-        /** convenience method for looking in mEnabledListenersForCurrentUser */
-        public boolean isEnabledForCurrentUser() {
+        /** convenience method for looking in mEnabledListenersForCurrentProfiles */
+        public boolean isEnabledForCurrentProfiles() {
             if (this.isSystem) return true;
             if (this.connection == null) return false;
-            return mEnabledListenersForCurrentUser.contains(this.component);
+            return mEnabledListenersForCurrentProfiles.contains(this.component);
         }
     }
 
@@ -503,18 +515,25 @@
      * Remove notification access for any services that no longer exist.
      */
     void disableNonexistentListeners() {
-        int currentUser = ActivityManager.getCurrentUser();
+        int[] userIds = getCurrentProfileIds();
+        final int N = userIds.length;
+        for (int i = 0 ; i < N; ++i) {
+            disableNonexistentListeners(userIds[i]);
+        }
+    }
+
+    void disableNonexistentListeners(int userId) {
         String flatIn = Settings.Secure.getStringForUser(
                 getContext().getContentResolver(),
                 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                currentUser);
+                userId);
         if (!TextUtils.isEmpty(flatIn)) {
             if (DBG) Slog.v(TAG, "flat before: " + flatIn);
             PackageManager pm = getContext().getPackageManager();
             List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
                     new Intent(NotificationListenerService.SERVICE_INTERFACE),
                     PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
-                    currentUser);
+                    userId);
 
             Set<ComponentName> installed = new HashSet<ComponentName>();
             for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -548,7 +567,7 @@
             if (!flatIn.equals(flatOut)) {
                 Settings.Secure.putStringForUser(getContext().getContentResolver(),
                         Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                        flatOut, currentUser);
+                        flatOut, userId);
             }
         }
     }
@@ -558,54 +577,70 @@
      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
      */
     void rebindListenerServices() {
-        final int currentUser = ActivityManager.getCurrentUser();
-        String flat = Settings.Secure.getStringForUser(
-                getContext().getContentResolver(),
-                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                currentUser);
+        final int[] userIds = getCurrentProfileIds();
+        final int nUserIds = userIds.length;
+
+        final SparseArray<String> flat = new SparseArray<String>();
+
+        for (int i = 0; i < nUserIds; ++i) {
+            flat.put(userIds[i], Settings.Secure.getStringForUser(
+                    getContext().getContentResolver(),
+                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+                    userIds[i]));
+        }
 
         NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
-        final ArrayList<ComponentName> toAdd;
+        final SparseArray<ArrayList<ComponentName>> toAdd
+                = new SparseArray<ArrayList<ComponentName>>();
 
         synchronized (mNotificationList) {
             // unbind and remove all existing listeners
             toRemove = mListeners.toArray(toRemove);
 
-            toAdd = new ArrayList<ComponentName>();
             final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
             final HashSet<String> newPackages = new HashSet<String>();
 
-            // decode the list of components
-            if (flat != null) {
-                String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
-                for (int i=0; i<components.length; i++) {
-                    final ComponentName component
-                            = ComponentName.unflattenFromString(components[i]);
-                    if (component != null) {
-                        newEnabled.add(component);
-                        toAdd.add(component);
-                        newPackages.add(component.getPackageName());
-                    }
-                }
+            for (int i = 0; i < nUserIds; ++i) {
+                final ArrayList<ComponentName> add = new ArrayList<ComponentName>();
+                toAdd.put(userIds[i], add);
 
-                mEnabledListenersForCurrentUser = newEnabled;
-                mEnabledListenerPackageNames = newPackages;
+                // decode the list of components
+                String toDecode = flat.get(userIds[i]);
+                if (toDecode != null) {
+                    String[] components = toDecode.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
+                    for (int j = 0; j < components.length; j++) {
+                        final ComponentName component
+                                = ComponentName.unflattenFromString(components[j]);
+                        if (component != null) {
+                            newEnabled.add(component);
+                            add.add(component);
+                            newPackages.add(component.getPackageName());
+                        }
+                    }
+
+                }
             }
+            mEnabledListenersForCurrentProfiles = newEnabled;
+            mEnabledListenerPackageNames = newPackages;
         }
 
         for (NotificationListenerInfo info : toRemove) {
             final ComponentName component = info.component;
             final int oldUser = info.userid;
-            Slog.v(TAG, "disabling notification listener for user " + oldUser + ": " + component);
+            Slog.v(TAG, "disabling notification listener for user "
+                    + oldUser + ": " + component);
             unregisterListenerService(component, info.userid);
         }
 
-        final int N = toAdd.size();
-        for (int i=0; i<N; i++) {
-            final ComponentName component = toAdd.get(i);
-            Slog.v(TAG, "enabling notification listener for user " + currentUser + ": "
-                    + component);
-            registerListenerService(component, currentUser);
+        for (int i = 0; i < nUserIds; ++i) {
+            final ArrayList<ComponentName> add = toAdd.get(userIds[i]);
+            final int N = add.size();
+            for (int j = 0; j < N; j++) {
+                final ComponentName component = add.get(j);
+                Slog.v(TAG, "enabling notification listener for user " + userIds[i] + ": "
+                        + component);
+                registerListenerService(component, userIds[i]);
+            }
         }
     }
 
@@ -653,6 +688,16 @@
                     getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0);
             intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
 
+            ApplicationInfo appInfo = null;
+            try {
+                appInfo = getContext().getPackageManager().getApplicationInfo(
+                        name.getPackageName(), 0);
+            } catch (NameNotFoundException e) {
+                // Ignore if the package doesn't exist we won't be able to bind to the service.
+            }
+            final int targetSdkVersion =
+                    appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
+
             try {
                 if (DBG) Slog.v(TAG, "binding: " + intent);
                 if (!getContext().bindServiceAsUser(intent,
@@ -661,19 +706,30 @@
 
                             @Override
                             public void onServiceConnected(ComponentName name, IBinder service) {
+                                boolean added = false;
                                 synchronized (mNotificationList) {
                                     mServicesBinding.remove(servicesBindingTag);
                                     try {
                                         mListener = INotificationListener.Stub.asInterface(service);
                                         NotificationListenerInfo info
                                                 = new NotificationListenerInfo(
-                                                mListener, name, userid, this);
+                                                        mListener, name, userid, this,
+                                                        targetSdkVersion);
                                         service.linkToDeath(info, 0);
-                                        mListeners.add(info);
+                                        added = mListeners.add(info);
                                     } catch (RemoteException e) {
                                         // already dead
                                     }
                                 }
+                                if (added) {
+                                    final String[] keys =
+                                            getActiveNotificationKeysFromListener(mListener);
+                                    try {
+                                        mListener.onListenerConnected(keys);
+                                    } catch (RemoteException e) {
+                                        // we tried
+                                    }
+                                }
                             }
 
                             @Override
@@ -781,6 +837,7 @@
     public static final class NotificationRecord
     {
         final StatusBarNotification sbn;
+        final SingleNotificationStats stats = new SingleNotificationStats();
         IBinder statusBarKey;
 
         NotificationRecord(StatusBarNotification sbn)
@@ -799,6 +856,7 @@
             pw.println(prefix + "  icon=0x" + Integer.toHexString(notification.icon)
                     + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon));
             pw.println(prefix + "  pri=" + notification.priority + " score=" + sbn.getScore());
+            pw.println(prefix + "  key=" + sbn.getKey());
             pw.println(prefix + "  contentIntent=" + notification.contentIntent);
             pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
             pw.println(prefix + "  tickerText=" + notification.tickerText);
@@ -850,15 +908,17 @@
                 }
                 pw.println(prefix + "  }");
             }
+            pw.println(prefix + "  stats=" + stats.toString());
         }
 
         @Override
         public final String toString() {
             return String.format(
-                    "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+                    "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
                     System.identityHashCode(this),
                     this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
-                    this.sbn.getTag(), this.sbn.getScore(), this.sbn.getNotification());
+                    this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(),
+                    this.sbn.getNotification());
         }
     }
 
@@ -928,7 +988,8 @@
         @Override
         public void onClearAll(int callingUid, int callingPid, int userId) {
             synchronized (mNotificationList) {
-                cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
+                cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null,
+                        /*includeCurrentProfiles*/ true);
             }
         }
 
@@ -949,6 +1010,7 @@
 
         @Override
         public void onPanelRevealed() {
+            EventLogTags.writeNotificationPanelRevealed();
             synchronized (mNotificationList) {
                 // sound
                 mSoundNotification = null;
@@ -981,6 +1043,11 @@
         }
 
         @Override
+        public void onPanelHidden() {
+            EventLogTags.writeNotificationPanelHidden();
+        }
+
+        @Override
         public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
                 int uid, int initialPid, String message, int userId) {
             Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
@@ -1103,9 +1170,9 @@
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
                 // reload per-user settings
                 mSettingsObserver.update(null);
-                updateRelatedUserCache(context);
+                updateCurrentProfilesCache(context);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
-                updateRelatedUserCache(context);
+                updateCurrentProfilesCache(context);
             }
         }
     };
@@ -1222,6 +1289,8 @@
         }
         updateZenMode();
 
+        updateCurrentProfilesCache(getContext());
+
         // register for various Intents
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -1554,21 +1623,47 @@
          * @param token The binder for the listener, to check that the caller is allowed
          */
         @Override
-        public void cancelAllNotificationsFromListener(INotificationListener token) {
+        public void cancelNotificationsFromListener(INotificationListener token, String[] keys) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    NotificationListenerInfo info = checkListenerTokenLocked(token);
-                    cancelAllLocked(callingUid, callingPid, info.userid,
-                            REASON_LISTENER_CANCEL_ALL, info);
+                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                    if (keys != null) {
+                        final int N = keys.length;
+                        for (int i = 0; i < N; i++) {
+                            NotificationRecord r = mNotificationsByKey.get(keys[i]);
+                            final int userId = r.sbn.getUserId();
+                            if (userId != info.userid && userId != UserHandle.USER_ALL &&
+                                    !isCurrentProfile(userId)) {
+                                throw new SecurityException("Disallowed call from listener: "
+                                        + info.listener);
+                            }
+                            if (r != null) {
+                                cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+                                        r.sbn.getPackageName(), r.sbn.getTag(), r.sbn.getId(),
+                                        userId);
+                            }
+                        }
+                    } else {
+                        cancelAllLocked(callingUid, callingPid, info.userid,
+                                REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles());
+                    }
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
         }
 
+        private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
+                int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
+            cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
+                    Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
+                    true,
+                    userId, REASON_LISTENER_CANCEL, info);
+        }
+
         /**
          * Allow an INotificationListener to simulate clearing (dismissing) a single notification.
          *
@@ -1584,11 +1679,15 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    NotificationListenerInfo info = checkListenerTokenLocked(token);
-                    cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
-                            Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
-                            true,
-                            info.userid, REASON_LISTENER_CANCEL, info);
+                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                    if (info.supportsProfiles()) {
+                        Log.e(TAG, "Ignoring deprecated cancelNotification(pkg, tag, id) "
+                                + "from " + info.component
+                                + " use cancelNotification(key) instead.");
+                    } else {
+                        cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+                                pkg, tag, id, info.userid);
+                    }
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -1604,15 +1703,26 @@
          */
         @Override
         public StatusBarNotification[] getActiveNotificationsFromListener(
-                INotificationListener token) {
+                INotificationListener token, String[] keys) {
             synchronized (mNotificationList) {
-                NotificationListenerInfo info = checkListenerTokenLocked(token);
-                ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
-                final int N = mNotificationList.size();
-                for (int i=0; i<N; i++) {
-                    StatusBarNotification sbn = mNotificationList.get(i).sbn;
-                    if (info.enabledAndUserMatches(sbn)) {
-                        list.add(sbn);
+                final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                final ArrayList<StatusBarNotification> list
+                        = new ArrayList<StatusBarNotification>();
+                if (keys == null) {
+                    final int N = mNotificationList.size();
+                    for (int i=0; i<N; i++) {
+                        StatusBarNotification sbn = mNotificationList.get(i).sbn;
+                        if (info.enabledAndUserMatches(sbn)) {
+                            list.add(sbn);
+                        }
+                    }
+                } else {
+                    final int N = keys.length;
+                    for (int i=0; i<N; i++) {
+                        NotificationRecord r = mNotificationsByKey.get(keys[i]);
+                        if (r != null && info.enabledAndUserMatches(r.sbn)) {
+                            list.add(r.sbn);
+                        }
                     }
                 }
                 return list.toArray(new StatusBarNotification[list.size()]);
@@ -1620,6 +1730,11 @@
         }
 
         @Override
+        public String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+            return NotificationManagerService.this.getActiveNotificationKeysFromListener(token);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -1633,12 +1748,27 @@
         }
     };
 
+    private String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+        synchronized (mNotificationList) {
+            final NotificationListenerInfo info = checkListenerTokenLocked(token);
+            final ArrayList<String> keys = new ArrayList<String>();
+            final int N = mNotificationList.size();
+            for (int i=0; i<N; i++) {
+                final StatusBarNotification sbn = mNotificationList.get(i).sbn;
+                if (info.enabledAndUserMatches(sbn)) {
+                    keys.add(sbn.getKey());
+                }
+            }
+            return keys.toArray(new String[keys.size()]);
+        }
+    }
+
     void dumpImpl(PrintWriter pw) {
         pw.println("Current Notification Manager state:");
 
-        pw.println("  Listeners (" + mEnabledListenersForCurrentUser.size()
-                + ") enabled for current user:");
-        for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
+        pw.println("  Listeners (" + mEnabledListenersForCurrentProfiles.size()
+                + ") enabled for current profiles:");
+        for (ComponentName cmpt : mEnabledListenersForCurrentProfiles) {
             pw.println("    " + cmpt);
         }
 
@@ -1698,6 +1828,9 @@
                 }
             }
 
+            pw.println("\n  Usage Stats:");
+            mUsageStats.dump(pw, "    ");
+
         }
     }
 
@@ -1845,15 +1978,21 @@
                     int index = indexOfNotificationLocked(pkg, tag, id, userId);
                     if (index < 0) {
                         mNotificationList.add(r);
+                        mUsageStats.registerPostedByApp(r);
                     } else {
-                        old = mNotificationList.remove(index);
-                        mNotificationList.add(index, r);
+                        old = mNotificationList.get(index);
+                        mNotificationList.set(index, r);
+                        mUsageStats.registerUpdatedByApp(r);
                         // Make sure we don't lose the foreground service state.
                         if (old != null) {
                             notification.flags |=
                                 old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
                         }
                     }
+                    if (old != null) {
+                        mNotificationsByKey.remove(old.sbn.getKey());
+                    }
+                    mNotificationsByKey.put(n.getKey(), r);
 
                     // Ensure if this is a foreground service that the proper additional
                     // flags are set.
@@ -1921,7 +2060,8 @@
                             && (!(old != null
                                 && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                             && (r.getUserId() == UserHandle.USER_ALL ||
-                                (r.getUserId() == userId && r.getUserId() == currentUser))
+                                (r.getUserId() == userId && r.getUserId() == currentUser) ||
+                                isCurrentProfile(r.getUserId()))
                             && canInterrupt
                             && mSystemReady
                             && mAudioManager != null) {
@@ -2057,7 +2197,8 @@
         synchronized (mNotificationList) {
             try {
                 NotificationListenerInfo info
-                        = new NotificationListenerInfo(listener, component, userid, true);
+                        = new NotificationListenerInfo(listener, component, userid,
+                        /*isSystem*/ true, Build.VERSION_CODES.L);
                 listener.asBinder().linkToDeath(info, 0);
                 mListeners.add(info);
             } catch (RemoteException e) {
@@ -2236,7 +2377,7 @@
         manager.sendAccessibilityEvent(event);
     }
 
-    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete) {
+    private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason) {
         // tell the app
         if (sendDelete) {
             if (r.getNotification().deleteIntent != null) {
@@ -2295,6 +2436,26 @@
             mLedNotification = null;
         }
 
+        // Record usage stats
+        switch (reason) {
+            case REASON_DELEGATE_CANCEL:
+            case REASON_DELEGATE_CANCEL_ALL:
+            case REASON_LISTENER_CANCEL:
+            case REASON_LISTENER_CANCEL_ALL:
+                mUsageStats.registerDismissedByUser(r);
+                break;
+            case REASON_NOMAN_CANCEL:
+            case REASON_NOMAN_CANCEL_ALL:
+                mUsageStats.registerRemovedByApp(r);
+                break;
+            case REASON_DELEGATE_CLICK:
+                mUsageStats.registerCancelDueToClick(r);
+                break;
+            default:
+                mUsageStats.registerCancelUnknown(r);
+                break;
+        }
+
         // Save it for users of getHistoricalNotifications()
         mArchive.record(r.sbn);
     }
@@ -2323,6 +2484,12 @@
                     if (index >= 0) {
                         NotificationRecord r = mNotificationList.get(index);
 
+                        // Ideally we'd do this in the caller of this method. However, that would
+                        // require the caller to also find the notification.
+                        if (reason == REASON_DELEGATE_CLICK) {
+                            mUsageStats.registerClickedByUser(r);
+                        }
+
                         if ((r.getNotification().flags & mustHaveFlags) != mustHaveFlags) {
                             return;
                         }
@@ -2331,8 +2498,9 @@
                         }
 
                         mNotificationList.remove(index);
+                        mNotificationsByKey.remove(r.sbn.getKey());
 
-                        cancelNotificationLocked(r, sendDelete);
+                        cancelNotificationLocked(r, sendDelete, reason);
                         updateLightsLocked();
                     }
                 }
@@ -2357,13 +2525,11 @@
     /**
      * Determine whether the userId applies to the notification in question, either because
      * they match exactly, or one of them is USER_ALL (which is treated as a wildcard) or
-     * because it matches a related user.
+     * because it matches one of the users profiles.
      */
-    private boolean notificationMatchesUserIdOrRelated(NotificationRecord r, int userId) {
-        synchronized (mRelatedUsers) {
-            return notificationMatchesUserId(r, userId)
-                    || mRelatedUsers.get(r.getUserId()) != null;
-        }
+    private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
+        return notificationMatchesUserId(r, userId)
+                || isCurrentProfile(r.getUserId());
     }
 
     /**
@@ -2403,7 +2569,8 @@
                     return true;
                 }
                 mNotificationList.remove(i);
-                cancelNotificationLocked(r, false);
+                mNotificationsByKey.remove(r.sbn.getKey());
+                cancelNotificationLocked(r, false, reason);
             }
             if (canceledSomething) {
                 updateLightsLocked();
@@ -2451,22 +2618,29 @@
     }
 
     void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
-            NotificationListenerInfo listener) {
+            NotificationListenerInfo listener, boolean includeCurrentProfiles) {
         EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
                 null, userId, 0, 0, reason,
                 listener == null ? null : listener.component.toShortString());
+
         final int N = mNotificationList.size();
         for (int i=N-1; i>=0; i--) {
             NotificationRecord r = mNotificationList.get(i);
-
-            if (!notificationMatchesUserIdOrRelated(r, userId)) {
-                continue;
+            if (includeCurrentProfiles) {
+                if (!notificationMatchesCurrentProfiles(r, userId)) {
+                    continue;
+                }
+            } else {
+                if (!notificationMatchesUserId(r, userId)) {
+                    continue;
+                }
             }
 
             if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
                             | Notification.FLAG_NO_CLEAR)) == 0) {
                 mNotificationList.remove(i);
-                cancelNotificationLocked(r, true);
+                mNotificationsByKey.remove(r.sbn.getKey());
+                cancelNotificationLocked(r, true, reason);
             }
         }
         updateLightsLocked();
@@ -2573,20 +2747,37 @@
                 exceptionPackages);
     }
 
-    private void updateRelatedUserCache(Context context) {
+    private void updateCurrentProfilesCache(Context context) {
         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-        int currentUserId = ActivityManager.getCurrentUser();
         if (userManager != null) {
-            List<UserInfo> relatedUsers = userManager.getRelatedUsers(currentUserId);
-            synchronized (mRelatedUsers) {
-                mRelatedUsers.clear();
-                for (UserInfo related : relatedUsers) {
-                    mRelatedUsers.put(related.id, related);
+            int currentUserId = ActivityManager.getCurrentUser();
+            List<UserInfo> profiles = userManager.getProfiles(currentUserId);
+            synchronized (mCurrentProfiles) {
+                mCurrentProfiles.clear();
+                for (UserInfo user : profiles) {
+                    mCurrentProfiles.put(user.id, user);
                 }
             }
         }
     }
 
+    private int[] getCurrentProfileIds() {
+        synchronized (mCurrentProfiles) {
+            int[] users = new int[mCurrentProfiles.size()];
+            final int N = mCurrentProfiles.size();
+            for (int i = 0; i < N; ++i) {
+                users[i] = mCurrentProfiles.keyAt(i);
+            }
+            return users;
+        }
+    }
+
+    private boolean isCurrentProfile(int userId) {
+        synchronized (mCurrentProfiles) {
+            return mCurrentProfiles.get(userId) != null;
+        }
+    }
+
     private boolean isCall(String pkg, Notification n) {
         return CALL_PACKAGES.contains(pkg);
     }
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
new file mode 100644
index 0000000..d9e2b91
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -0,0 +1,277 @@
+/*
+ * 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.notification;
+
+import com.android.server.notification.NotificationManagerService.NotificationRecord;
+
+import android.os.SystemClock;
+import android.service.notification.StatusBarNotification;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Keeps track of notification activity, display, and user interaction.
+ *
+ * <p>This class receives signals from NoMan and keeps running stats of
+ * notification usage. Some metrics are updated as events occur. Others, namely
+ * those involving durations, are updated as the notification is canceled.</p>
+ *
+ * <p>This class is thread-safe.</p>
+ *
+ * {@hide}
+ */
+public class NotificationUsageStats {
+
+    // Guarded by synchronized(this).
+    private final Map<String, AggregatedStats> mStats = new HashMap<String, AggregatedStats>();
+
+    /**
+     * Called when a notification has been posted.
+     */
+    public synchronized void registerPostedByApp(NotificationRecord notification) {
+        notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.numPostedByApp++;
+        }
+    }
+
+    /**
+     * Called when a notification has been updated.
+     */
+    public void registerUpdatedByApp(NotificationRecord notification) {
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.numUpdatedByApp++;
+        }
+    }
+
+    /**
+     * Called when the originating app removed the notification programmatically.
+     */
+    public synchronized void registerRemovedByApp(NotificationRecord notification) {
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.numRemovedByApp++;
+            stats.collect(notification.stats);
+        }
+    }
+
+    /**
+     * Called when the user dismissed the notification via the UI.
+     */
+    public synchronized void registerDismissedByUser(NotificationRecord notification) {
+        notification.stats.onDismiss();
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.numDismissedByUser++;
+            stats.collect(notification.stats);
+        }
+    }
+
+    /**
+     * Called when the user clicked the notification in the UI.
+     */
+    public synchronized void registerClickedByUser(NotificationRecord notification) {
+        notification.stats.onClick();
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.numClickedByUser++;
+        }
+    }
+
+    /**
+     * Called when the notification is canceled because the user clicked it.
+     *
+     * <p>Called after {@link #registerClickedByUser(NotificationRecord)}.</p>
+     */
+    public synchronized void registerCancelDueToClick(NotificationRecord notification) {
+        // No explicit stats for this (the click has already been registered in
+        // registerClickedByUser), just make sure the single notification stats
+        // are folded up into aggregated stats.
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.collect(notification.stats);
+        }
+    }
+
+    /**
+     * Called when the notification is canceled due to unknown reasons.
+     *
+     * <p>Called for notifications of apps being uninstalled, for example.</p>
+     */
+    public synchronized void registerCancelUnknown(NotificationRecord notification) {
+        // Fold up individual stats.
+        for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+            stats.collect(notification.stats);
+        }
+    }
+
+    // Locked by this.
+    private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
+        StatusBarNotification n = record.sbn;
+
+        String user = String.valueOf(n.getUserId());
+        String userPackage = user + ":" + n.getPackageName();
+
+        // TODO: Use pool of arrays.
+        return new AggregatedStats[] {
+                getOrCreateAggregatedStatsLocked(user),
+                getOrCreateAggregatedStatsLocked(userPackage),
+                getOrCreateAggregatedStatsLocked(n.getKey()),
+        };
+    }
+
+    // Locked by this.
+    private AggregatedStats getOrCreateAggregatedStatsLocked(String key) {
+        AggregatedStats result = mStats.get(key);
+        if (result == null) {
+            result = new AggregatedStats(key);
+            mStats.put(key, result);
+        }
+        return result;
+    }
+
+    public synchronized void dump(PrintWriter pw, String indent) {
+        for (AggregatedStats as : mStats.values()) {
+            as.dump(pw, indent);
+        }
+    }
+
+    /**
+     * Aggregated notification stats.
+     */
+    private static class AggregatedStats {
+        public final String key;
+
+        // ---- Updated as the respective events occur.
+        public int numPostedByApp;
+        public int numUpdatedByApp;
+        public int numRemovedByApp;
+        public int numClickedByUser;
+        public int numDismissedByUser;
+
+        // ----  Updated when a notification is canceled.
+        public final Aggregate posttimeMs = new Aggregate();
+        public final Aggregate posttimeToDismissMs = new Aggregate();
+        public final Aggregate posttimeToFirstClickMs = new Aggregate();
+
+        public AggregatedStats(String key) {
+            this.key = key;
+        }
+
+        public void collect(SingleNotificationStats singleNotificationStats) {
+            posttimeMs.addSample(
+	            SystemClock.elapsedRealtime() - singleNotificationStats.posttimeElapsedMs);
+            if (singleNotificationStats.posttimeToDismissMs >= 0) {
+                posttimeToDismissMs.addSample(singleNotificationStats.posttimeToDismissMs);
+            }
+            if (singleNotificationStats.posttimeToFirstClickMs >= 0) {
+                posttimeToFirstClickMs.addSample(singleNotificationStats.posttimeToFirstClickMs);
+            }
+        }
+
+        public void dump(PrintWriter pw, String indent) {
+            pw.println(toStringWithIndent(indent));
+        }
+
+        @Override
+        public String toString() {
+            return toStringWithIndent("");
+        }
+
+        private String toStringWithIndent(String indent) {
+            return indent + "AggregatedStats{\n" +
+                    indent + "  key='" + key + "',\n" +
+                    indent + "  numPostedByApp=" + numPostedByApp + ",\n" +
+                    indent + "  numUpdatedByApp=" + numUpdatedByApp + ",\n" +
+                    indent + "  numRemovedByApp=" + numRemovedByApp + ",\n" +
+                    indent + "  numClickedByUser=" + numClickedByUser + ",\n" +
+                    indent + "  numDismissedByUser=" + numDismissedByUser + ",\n" +
+                    indent + "  posttimeMs=" + posttimeMs + ",\n" +
+                    indent + "  posttimeToDismissMs=" + posttimeToDismissMs + ",\n" +
+                    indent + "  posttimeToFirstClickMs=" + posttimeToFirstClickMs + ",\n" +
+                    indent + "}";
+        }
+    }
+
+    /**
+     * Tracks usage of an individual notification that is currently active.
+     */
+    public static class SingleNotificationStats {
+        /** SystemClock.elapsedRealtime() when the notification was posted. */
+        public long posttimeElapsedMs = -1;
+        /** Elapsed time since the notification was posted until it was first clicked, or -1. */
+        public long posttimeToFirstClickMs = -1;
+        /** Elpased time since the notification was posted until it was dismissed by the user. */
+        public long posttimeToDismissMs = -1;
+
+        /**
+         * Called when the user clicked the notification.
+         */
+        public void onClick() {
+            if (posttimeToFirstClickMs < 0) {
+                posttimeToFirstClickMs = SystemClock.elapsedRealtime() - posttimeElapsedMs;
+            }
+        }
+
+        /**
+         * Called when the user removed the notification.
+         */
+        public void onDismiss() {
+            if (posttimeToDismissMs < 0) {
+                posttimeToDismissMs = SystemClock.elapsedRealtime() - posttimeElapsedMs;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "SingleNotificationStats{" +
+                    "posttimeElapsedMs=" + posttimeElapsedMs +
+                    ", posttimeToFirstClickMs=" + posttimeToFirstClickMs +
+                    ", posttimeToDismissMs=" + posttimeToDismissMs +
+                    '}';
+        }
+    }
+
+    /**
+     * Aggregates long samples to sum and averages.
+     */
+    public static class Aggregate {
+        long numSamples;
+        double avg;
+        double sum2;
+        double var;
+
+        public void addSample(long sample) {
+            // Welford's "Method for Calculating Corrected Sums of Squares"
+            // http://www.jstor.org/stable/1266577?seq=2
+            numSamples++;
+            final double n = numSamples;
+            final double delta = sample - avg;
+            avg += (1.0 / n) * delta;
+            sum2 += ((n - 1) / n) * delta * delta;
+            final double divisor = numSamples == 1 ? 1.0 : n - 1.0;
+            var = sum2 / divisor;
+        }
+
+        @Override
+        public String toString() {
+            return "Aggregate{" +
+                    "numSamples=" + numSamples +
+                    ", avg=" + avg +
+                    ", var=" + var +
+                    '}';
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ae1cfab..ff816ea 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -407,7 +407,14 @@
         return execute(builder.toString());
     }
 
-    public boolean restoreconData() {
-        return (execute("restorecondata") == 0);
+    public boolean restoreconData(String pkgName, String seinfo, int uid) {
+        StringBuilder builder = new StringBuilder("restorecondata");
+        builder.append(' ');
+        builder.append(pkgName);
+        builder.append(' ');
+        builder.append(seinfo != null ? seinfo : "!");
+        builder.append(' ');
+        builder.append(uid);
+        return (execute(builder.toString()) == 0);
     }
 }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
new file mode 100644
index 0000000..27c7b39
--- /dev/null
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -0,0 +1,292 @@
+/*
+ * 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.pm;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ILauncherApps;
+import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IInterface;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
+
+import com.android.internal.content.PackageMonitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service that manages requests and callbacks for launchers that support
+ * managed profiles. 
+ */
+public class LauncherAppsService extends ILauncherApps.Stub {
+
+    private static final String TAG = "LauncherAppsService";
+    private final Context mContext;
+    private final PackageManager mPm;
+    private final UserManager mUm;
+    private final PackageCallbackList<IOnAppsChangedListener> mListeners
+            = new PackageCallbackList<IOnAppsChangedListener>();
+
+    private MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
+
+    public LauncherAppsService(Context context) {
+        mContext = context;
+        mPm = mContext.getPackageManager();
+        mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+    }
+
+    /*
+     * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
+     *          android.content.pm.IOnAppsChangedListener)
+     */
+    @Override
+    public void addOnAppsChangedListener(IOnAppsChangedListener listener) throws RemoteException {
+        synchronized (mListeners) {
+            if (mListeners.getRegisteredCallbackCount() == 0) {
+                startWatchingPackageBroadcasts();
+            }
+            mListeners.unregister(listener);
+            mListeners.register(listener);
+        }
+    }
+
+    /*
+     * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
+     *          android.content.pm.IOnAppsChangedListener)
+     */
+    @Override
+    public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
+            throws RemoteException {
+        synchronized (mListeners) {
+            mListeners.unregister(listener);
+            if (mListeners.getRegisteredCallbackCount() == 0) {
+                stopWatchingPackageBroadcasts();
+            }
+        }
+    }
+
+    /**
+     * Register a receiver to watch for package broadcasts
+     */
+    private void startWatchingPackageBroadcasts() {
+        mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
+    }
+
+    /**
+     * Unregister package broadcast receiver
+     */
+    private void stopWatchingPackageBroadcasts() {
+        mPackageMonitor.unregister();
+    }
+
+    void checkCallbackCount() {
+        synchronized (LauncherAppsService.this) {
+            if (mListeners.getRegisteredCallbackCount() == 0) {
+                stopWatchingPackageBroadcasts();
+            }
+        }
+    }
+
+    /**
+     * Checks if the caller is in the same group as the userToCheck.
+     */
+    private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+        final int callingUserId = UserHandle.getCallingUserId();
+        final int targetUserId = userToCheck.getIdentifier();
+
+        if (targetUserId == callingUserId) return;
+
+        long ident = Binder.clearCallingIdentity();
+        try {
+            UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
+            UserInfo targetUserInfo = mUm.getUserInfo(targetUserId);
+            if (targetUserInfo == null
+                    || targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
+                    || targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
+                throw new SecurityException(message);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> getLauncherActivities(String packageName, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot retrieve activities for unrelated profile " + user);
+
+        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0,
+                    user.getIdentifier());
+            return apps;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public ResolveInfo resolveActivity(Intent intent, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot resolve activity for unrelated profile " + user);
+
+        long ident = Binder.clearCallingIdentity();
+        try {
+            ResolveInfo app = mPm.resolveActivityAsUser(intent, 0, user.getIdentifier());
+            return app;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public void startActivityAsUser(ComponentName component, Rect sourceBounds,
+            Bundle opts, UserHandle user) throws RemoteException {
+        ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+
+        Intent launchIntent = new Intent(Intent.ACTION_MAIN);
+        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        launchIntent.setComponent(component);
+        launchIntent.setSourceBounds(sourceBounds);
+        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        final int callingUserId = UserHandle.getCallingUserId();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mContext.startActivityAsUser(launchIntent, opts, user);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private class MyPackageMonitor extends PackageMonitor {
+
+        @Override
+        public void onPackageAdded(String packageName, int uid) {
+            UserHandle user = new UserHandle(getChangingUserId());
+            // TODO: if (!isProfile(user)) return;
+            final int n = mListeners.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                try {
+                    listener.onPackageAdded(user, packageName);
+                } catch (RemoteException re) {
+                    Slog.d(TAG, "Callback failed ", re);
+                }
+            }
+            mListeners.finishBroadcast();
+
+            super.onPackageAdded(packageName, uid);
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            UserHandle user = new UserHandle(getChangingUserId());
+            // TODO: if (!isCurrentProfile(user)) return;
+            final int n = mListeners.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                try {
+                    listener.onPackageRemoved(user, packageName);
+                } catch (RemoteException re) {
+                    Slog.d(TAG, "Callback failed ", re);
+                }
+            }
+            mListeners.finishBroadcast();
+
+            super.onPackageRemoved(packageName, uid);
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
+            UserHandle user = new UserHandle(getChangingUserId());
+            // TODO: if (!isProfile(user)) return;
+            final int n = mListeners.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                try {
+                    listener.onPackageChanged(user, packageName);
+                } catch (RemoteException re) {
+                    Slog.d(TAG, "Callback failed ", re);
+                }
+            }
+            mListeners.finishBroadcast();
+
+            super.onPackageModified(packageName);
+        }
+
+        @Override
+        public void onPackagesAvailable(String[] packages) {
+            UserHandle user = new UserHandle(getChangingUserId());
+            // TODO: if (!isProfile(user)) return;
+            final int n = mListeners.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                try {
+                    listener.onPackagesAvailable(user, packages, isReplacing());
+                } catch (RemoteException re) {
+                    Slog.d(TAG, "Callback failed ", re);
+                }
+            }
+            mListeners.finishBroadcast();
+
+            super.onPackagesAvailable(packages);
+        }
+
+        @Override
+        public void onPackagesUnavailable(String[] packages) {
+            UserHandle user = new UserHandle(getChangingUserId());
+            // TODO: if (!isProfile(user)) return;
+            final int n = mListeners.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                try {
+                    listener.onPackagesUnavailable(user, packages, isReplacing());
+                } catch (RemoteException re) {
+                    Slog.d(TAG, "Callback failed ", re);
+                }
+            }
+            mListeners.finishBroadcast();
+
+            super.onPackagesUnavailable(packages);
+        }
+
+    }
+
+    class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
+
+        @Override
+        public void onCallbackDied(T callback, Object cookie) {
+            checkCallbackCount();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a07ad5a..ff90cae 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -402,6 +402,9 @@
     // If mac_permissions.xml was found for seinfo labeling.
     boolean mFoundPolicyFile;
 
+    // If a recursive restorecon of /data/data/<pkg> is needed.
+    private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon();
+
     // All available activities, for your resolving pleasure.
     final ActivityIntentResolver mActivities =
             new ActivityIntentResolver();
@@ -697,7 +700,7 @@
                                     // Just post MCS_BOUND message to trigger processing
                                     // of next pending install.
                                     if (DEBUG_SD_INSTALL) Log.i(TAG,
-                                            "Posting MCS_BOUND for next woek");
+                                            "Posting MCS_BOUND for next work");
                                     mHandler.sendEmptyMessage(MCS_BOUND);
                                 }
                             }
@@ -1536,13 +1539,6 @@
             // can downgrade to reader
             mSettings.writeLPr();
 
-            if (SELinuxMMAC.shouldRestorecon()) {
-                Slog.i(TAG, "Relabeling of /data/data and /data/user issued.");
-                if (mInstaller.restoreconData()) {
-                    SELinuxMMAC.setRestoreconDone();
-                }
-            }
-
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                     SystemClock.uptimeMillis());
 
@@ -4787,6 +4783,11 @@
                     }
                 }
                 pkg.applicationInfo.dataDir = dataPath.getPath();
+                if (mShouldRestoreconData) {
+                    Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
+                    mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
+                                pkg.applicationInfo.uid);
+                }
             } else {
                 if (DEBUG_PACKAGE_SCANNING) {
                     if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
@@ -7532,32 +7533,34 @@
                 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
             }
 
-            final boolean mounted;
-            if (Environment.isExternalStorageEmulated()) {
-                mounted = true;
-            } else {
-                final String status = Environment.getExternalStorageState();
-                mounted = (Environment.MEDIA_MOUNTED.equals(status)
-                        || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
-            }
+            if (mSuccess) {
+                final boolean mounted;
+                if (Environment.isExternalStorageEmulated()) {
+                    mounted = true;
+                } else {
+                    final String status = Environment.getExternalStorageState();
+                    mounted = (Environment.MEDIA_MOUNTED.equals(status)
+                            || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
+                }
 
-            if (mounted) {
-                final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
+                if (mounted) {
+                    final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
 
-                mStats.externalCacheSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
+                    mStats.externalCacheSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
 
-                mStats.externalDataSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
+                    mStats.externalDataSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
 
-                // Always subtract cache size, since it's a subdirectory
-                mStats.externalDataSize -= mStats.externalCacheSize;
+                    // Always subtract cache size, since it's a subdirectory
+                    mStats.externalDataSize -= mStats.externalCacheSize;
 
-                mStats.externalMediaSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
+                    mStats.externalMediaSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
 
-                mStats.externalObbSize = calculateDirectorySize(mContainerService,
-                        userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+                    mStats.externalObbSize = calculateDirectorySize(mContainerService,
+                            userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+                }
             }
         }
 
@@ -9198,7 +9201,7 @@
         }
         
         // Successfully disabled the old package. Now proceed with re-installation
-        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
+        res.returnCode = mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
         if (newPackage == null) {
@@ -9211,9 +9214,20 @@
                 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
                 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
                 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
+
+                // is the update attempting to change shared user? that isn't going to work...
+                if (oldPkgSetting.sharedUser != newPkgSetting.sharedUser) {
+                    Slog.w(TAG, "Forbidding shared user change from " + oldPkgSetting.sharedUser
+                            + " to " + newPkgSetting.sharedUser);
+                    res.returnCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
+                    updatedSettings = true;
+                }
             }
-            updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
-            updatedSettings = true;
+
+            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
+                updatedSettings = true;
+            }
         }
 
         if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -10270,6 +10284,9 @@
             final IPackageStatsObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GET_PACKAGE_SIZE, null);
+        if (packageName == null) {
+            throw new IllegalArgumentException("Attempt to get size of null packageName");
+        }
 
         PackageStats stats = new PackageStats(packageName, userHandle);
 
@@ -11432,6 +11449,10 @@
      */
     public void scanAvailableAsecs() {
         updateExternalMediaStatusInner(true, false, false);
+        if (mShouldRestoreconData) {
+            SELinuxMMAC.setRestoreconDone();
+            mShouldRestoreconData = false;
+        }
     }
 
     /*
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7f55464..32515b5 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -92,7 +92,7 @@
     private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
     private static final String ATTR_PARTIAL = "partial";
     private static final String ATTR_USER_VERSION = "version";
-    private static final String ATTR_RELATED_GROUP_ID = "relatedGroupId";
+    private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
     private static final String TAG_USERS = "users";
     private static final String TAG_USER = "user";
     private static final String TAG_RESTRICTIONS = "restrictions";
@@ -257,26 +257,28 @@
     }
 
     @Override
-    public List<UserInfo> getRelatedUsers(int userId) {
-        checkManageUsersPermission("query users");
+    public List<UserInfo> getProfiles(int userId) {
+        if (userId != UserHandle.getCallingUserId()) {
+            checkManageUsersPermission("getting profiles related to user " + userId);
+        }
         synchronized (mPackagesLock) {
             UserInfo user = getUserInfoLocked(userId);
             ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
             for (int i = 0; i < mUsers.size(); i++) {
-                UserInfo ui = mUsers.valueAt(i);
-                if (!areRelatedUsers(user, ui)) {
+                UserInfo profile = mUsers.valueAt(i);
+                if (!isProfileOf(user, profile)) {
                     continue;
                 }
-                users.add(ui);
+                users.add(profile);
             }
             return users;
         }
     }
 
-    private boolean areRelatedUsers(UserInfo user1, UserInfo user2) {
-        return user1.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID &&
-                user1.relatedGroupId == user2.relatedGroupId &&
-                user1.id != user2.id;
+    private boolean isProfileOf(UserInfo user, UserInfo profile) {
+        return user.id == profile.id ||
+                (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                && user.profileGroupId == profile.profileGroupId);
     }
 
     @Override
@@ -684,9 +686,9 @@
             if (userInfo.partial) {
                 serializer.attribute(null, ATTR_PARTIAL, "true");
             }
-            if (userInfo.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID) {
-                serializer.attribute(null, ATTR_RELATED_GROUP_ID,
-                        Integer.toString(userInfo.relatedGroupId));
+            if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
+                serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
+                        Integer.toString(userInfo.profileGroupId));
             }
 
             serializer.startTag(null, TAG_NAME);
@@ -771,7 +773,7 @@
         long salt = 0L;
         String pinHash = null;
         int failedAttempts = 0;
-        int relatedGroupId = UserInfo.NO_RELATED_GROUP_ID;
+        int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
         long lastAttemptTime = 0L;
         boolean partial = false;
         Bundle restrictions = new Bundle();
@@ -809,8 +811,14 @@
                 pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
                 failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
                 lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
-                relatedGroupId = readIntAttribute(parser, ATTR_RELATED_GROUP_ID,
-                        UserInfo.NO_RELATED_GROUP_ID);
+                profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
+                        UserInfo.NO_PROFILE_GROUP_ID);
+                if (profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+                    // This attribute was added and renamed during development of L.
+                    // TODO Remove upgrade path by 1st May 2014
+                    profileGroupId = readIntAttribute(parser, "relatedGroupId",
+                            UserInfo.NO_PROFILE_GROUP_ID);
+                }
                 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
                 if ("true".equals(valueString)) {
                     partial = true;
@@ -849,7 +857,7 @@
             userInfo.creationTime = creationTime;
             userInfo.lastLoggedInTime = lastLoggedInTime;
             userInfo.partial = partial;
-            userInfo.relatedGroupId = relatedGroupId;
+            userInfo.profileGroupId = profileGroupId;
             mUserRestrictions.append(id, restrictions);
             if (salt != 0L) {
                 RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
@@ -964,25 +972,25 @@
         }
     }
 
-    private int getNextRelatedGroupIdLocked() {
-        int maxGroupId = UserInfo.NO_RELATED_GROUP_ID;
+    private int getNextProfileGroupIdLocked() {
+        int maxGroupId = UserInfo.NO_PROFILE_GROUP_ID;
         for (int i = 0; i < mUsers.size(); i++) {
             UserInfo ui = mUsers.valueAt(i);
-            if (maxGroupId < ui.relatedGroupId) {
-                maxGroupId = ui.relatedGroupId;
+            if (maxGroupId < ui.profileGroupId) {
+                maxGroupId = ui.profileGroupId;
             }
         }
         return maxGroupId + 1;
     }
 
     @Override
-    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+    public UserInfo createProfileForUser(String name, int flags, int userId) {
         checkManageUsersPermission("Only the system can create users");
-        if (relatedUserId != UserHandle.USER_OWNER) {
-            Slog.w(LOG_TAG, "Only user owner can have related users");
+        if (userId != UserHandle.USER_OWNER) {
+            Slog.w(LOG_TAG, "Only user owner can have profiles");
             return null;
         }
-        return createUserInternal(name, flags, relatedUserId);
+        return createUserInternal(name, flags, userId);
     }
 
     @Override
@@ -991,16 +999,16 @@
         return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
-    private UserInfo createUserInternal(String name, int flags, int relatedUserId) {
+    private UserInfo createUserInternal(String name, int flags, int profileId) {
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo = null;
         try {
             synchronized (mInstallLock) {
                 synchronized (mPackagesLock) {
-                    UserInfo relatedUser = null;
-                    if (relatedUserId != UserHandle.USER_NULL) {
-                        relatedUser = getUserInfoLocked(relatedUserId);
-                        if (relatedUser == null) return null;
+                    UserInfo profile = null;
+                    if (profileId != UserHandle.USER_NULL) {
+                        profile = getUserInfoLocked(profileId);
+                        if (profile == null) return null;
                     }
                     if (isUserLimitReachedLocked()) return null;
                     int userId = getNextAvailableIdLocked();
@@ -1013,12 +1021,12 @@
                     Environment.getUserSystemDirectory(userInfo.id).mkdirs();
                     mUsers.put(userId, userInfo);
                     writeUserListLocked();
-                    if (relatedUser != null) {
-                        if (relatedUser.relatedGroupId == UserInfo.NO_RELATED_GROUP_ID) {
-                            relatedUser.relatedGroupId = getNextRelatedGroupIdLocked();
+                    if (profile != null) {
+                        if (profile.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+                            profile.profileGroupId = getNextProfileGroupIdLocked();
+                            writeUserLocked(profile);
                         }
-                        userInfo.relatedGroupId = relatedUser.relatedGroupId;
-                        writeUserLocked(relatedUser);
+                        userInfo.profileGroupId = profile.profileGroupId;
                     }
                     writeUserLocked(userInfo);
                     mPm.createNewUserLILPw(userId, userPath);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a388318..b85a506 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -406,6 +406,7 @@
     private static native void nativeReleaseSuspendBlocker(String name);
     private static native void nativeSetInteractive(boolean enable);
     private static native void nativeSetAutoSuspend(boolean enable);
+    private static native void nativeSendPowerHint(int hintId, int data);
 
     public PowerManagerService(Context context) {
         super(context);
@@ -2541,10 +2542,19 @@
         @Override // Binder call
         public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
                 String packageName, int uid) {
+            if (uid < 0) {
+                uid = Binder.getCallingUid();
+            }
             acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
         }
 
         @Override // Binder call
+        public void powerHint(int hintId, int data) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+            nativeSendPowerHint(hintId, data);
+        }
+
+        @Override // Binder call
         public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
                 WorkSource ws, String historyTag) {
             if (lock == null) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 4ce02c1..e4b5f3a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -535,6 +535,17 @@
     }
 
     @Override
+    public void onPanelHidden() throws RemoteException {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onPanelHidden();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onNotificationClick(String pkg, String tag, int id, int userId) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
new file mode 100644
index 0000000..a83fa87
--- /dev/null
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.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 com.android.server.trust;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import android.service.trust.ITrustAgentService;
+import android.service.trust.ITrustAgentServiceCallback;
+
+/**
+ * A wrapper around a TrustAgentService interface. Coordinates communication between
+ * TrustManager and the actual TrustAgent.
+ */
+public class TrustAgentWrapper {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "TrustAgentWrapper";
+
+    private static final int MSG_ENABLE_TRUST = 1;
+    private static final int MSG_REVOKE_TRUST = 2;
+    private static final int MSG_TRUST_TIMEOUT = 3;
+
+    private final TrustManagerService mTrustManagerService;
+    private final int mUserId;
+    private final Context mContext;
+    private final ComponentName mName;
+
+    private ITrustAgentService mTrustAgentService;
+
+    // Trust state
+    private boolean mTrusted;
+    private String mMessage;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ENABLE_TRUST:
+                    mTrusted = true;
+                    mMessage = (String) msg.obj;
+                    boolean initiatedByUser = msg.arg1 != 0;
+                    // TODO: Handle handle user initiated trust changes.
+                    mTrustManagerService.updateTrust(mUserId);
+                    break;
+                case MSG_TRUST_TIMEOUT:
+                    if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
+                    // Fall through.
+                case MSG_REVOKE_TRUST:
+                    mTrusted = false;
+                    mMessage = null;
+                    mTrustManagerService.updateTrust(mUserId);
+                    break;
+            }
+        }
+    };
+
+    private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
+
+        public void enableTrust(String userMessage, long durationMs, boolean initiatedByUser) {
+            if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs
+                        + ", initiatedByUser = " + initiatedByUser + ")");
+
+            mHandler.obtainMessage(MSG_ENABLE_TRUST, initiatedByUser ? 1 : 0, 0, userMessage)
+                    .sendToTarget();
+            if (durationMs > 0) {
+                mHandler.removeMessages(MSG_TRUST_TIMEOUT);
+                mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs);
+            }
+        }
+
+        public void revokeTrust() {
+            if (DEBUG) Slog.v(TAG, "revokeTrust()");
+            mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+        }
+    };
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
+            mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
+            setCallback(mCallback);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString());
+            mTrustAgentService = null;
+            mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+        }
+    };
+
+
+    public TrustAgentWrapper(Context context, TrustManagerService trustManagerService,
+            Intent intent, UserHandle user) {
+        mContext = context;
+        mTrustManagerService = trustManagerService;
+        mUserId = user.getIdentifier();
+        mName = intent.getComponent();
+        if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
+            if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
+            // TODO: retry somehow?
+        }
+    }
+
+    private void onError(Exception e) {
+        Slog.w(TAG , "Remote Exception", e);
+    }
+
+    /**
+     * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
+     */
+    public void onUnlockAttempt(boolean successful) {
+        try {
+            if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    private void setCallback(ITrustAgentServiceCallback callback) {
+        try {
+            if (mTrustAgentService != null) {
+                mTrustAgentService.setCallback(callback);
+            }
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    public boolean isTrusted() {
+        return mTrusted;
+    }
+
+    public String getMessage() {
+        return mMessage;
+    }
+
+    public void unbind() {
+        if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
+        mContext.unbindService(mConnection);
+    }
+}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
new file mode 100644
index 0000000..a2a49c9
--- /dev/null
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -0,0 +1,387 @@
+/*
+ * 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.trust;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.server.SystemService;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.Manifest;
+import android.app.trust.ITrustListener;
+import android.app.trust.ITrustManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.trust.TrustAgentService;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.util.Xml;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages trust agents and trust listeners.
+ *
+ * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
+ * of each user and notifies them about events that are relevant to them.
+ * It start and stops them based on the value of
+ * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
+ *
+ * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
+ * trust state changes for any user.
+ *
+ * Trust state and the setting of enabled agents is kept per user and each user has its own
+ * instance of a {@link android.service.trust.TrustAgentService}.
+ */
+public class TrustManagerService extends SystemService {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "TrustManagerService";
+
+    private static final Intent TRUST_AGENT_INTENT =
+            new Intent(TrustAgentService.SERVICE_INTERFACE);
+
+    private static final int MSG_REGISTER_LISTENER = 1;
+    private static final int MSG_UNREGISTER_LISTENER = 2;
+    private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
+    private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
+
+    private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
+    private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
+    private final Context mContext;
+
+    private UserManager mUserManager;
+
+    /**
+     * Cache for {@link #refreshAgentList()}
+     */
+    private final ArraySet<AgentInfo> mObsoleteAgents = new ArraySet<AgentInfo>();
+
+
+    public TrustManagerService(Context context) {
+        super(context);
+        mContext = context;
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.TRUST_SERVICE, mService);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
+            // Listen for package changes
+            mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
+            refreshAgentList();
+        }
+    }
+
+    // Agent management
+
+    private static final class AgentInfo {
+        CharSequence label;
+        Drawable icon;
+        ComponentName component; // service that implements ITrustAgent
+        ComponentName settings; // setting to launch to modify agent.
+        TrustAgentWrapper agent;
+        int userId;
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof AgentInfo)) {
+                return false;
+            }
+            AgentInfo o = (AgentInfo) other;
+            return component.equals(o.component) && userId == o.userId;
+        }
+
+        @Override
+        public int hashCode() {
+            return component.hashCode() * 31 + userId;
+        }
+    }
+
+    private void updateTrustAll() {
+        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+        for (UserInfo userInfo : userInfos) {
+            updateTrust(userInfo.id);
+        }
+    }
+
+    public void updateTrust(int userId) {
+        dispatchOnTrustChanged(aggregateIsTrusted(userId), userId);
+    }
+
+    protected void refreshAgentList() {
+        if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+        PackageManager pm = mContext.getPackageManager();
+
+        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+        LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+
+        mObsoleteAgents.clear();
+        mObsoleteAgents.addAll(mActiveAgents);
+
+        for (UserInfo userInfo : userInfos) {
+            List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
+            if (enabledAgents == null) {
+                continue;
+            }
+            List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+                    PackageManager.GET_META_DATA, userInfo.id);
+            for (ResolveInfo resolveInfo : resolveInfos) {
+                if (resolveInfo.serviceInfo == null) continue;
+                ComponentName name = getComponentName(resolveInfo);
+                if (!enabledAgents.contains(name)) continue;
+
+                AgentInfo agentInfo = new AgentInfo();
+                agentInfo.component = name;
+                agentInfo.userId = userInfo.id;
+                if (!mActiveAgents.contains(agentInfo)) {
+                    agentInfo.label = resolveInfo.loadLabel(pm);
+                    agentInfo.icon = resolveInfo.loadIcon(pm);
+                    agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
+                    agentInfo.agent = new TrustAgentWrapper(mContext, this,
+                            new Intent().setComponent(name), userInfo.getUserHandle());
+                    mActiveAgents.add(agentInfo);
+                } else {
+                    mObsoleteAgents.remove(agentInfo);
+                }
+            }
+        }
+
+        boolean trustMayHaveChanged = false;
+        for (int i = 0; i < mObsoleteAgents.size(); i++) {
+            AgentInfo info = mActiveAgents.valueAt(i);
+            if (info.agent.isTrusted()) {
+                trustMayHaveChanged = true;
+            }
+            info.agent.unbind();
+            mActiveAgents.remove(info);
+        }
+
+        if (trustMayHaveChanged) {
+            updateTrustAll();
+        }
+    }
+
+    private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
+        if (resolveInfo == null || resolveInfo.serviceInfo == null
+                || resolveInfo.serviceInfo.metaData == null) return null;
+        String cn = null;
+        XmlResourceParser parser = null;
+        Exception caughtException = null;
+        try {
+            parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
+                    TrustAgentService.TRUST_AGENT_META_DATA);
+            if (parser == null) {
+                Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
+                return null;
+            }
+            Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+                // Drain preamble.
+            }
+            String nodeName = parser.getName();
+            if (!"trust_agent".equals(nodeName)) {
+                Slog.w(TAG, "Meta-data does not start with trust_agent tag");
+                return null;
+            }
+            TypedArray sa = res
+                    .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
+            cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+            sa.recycle();
+        } catch (PackageManager.NameNotFoundException e) {
+            caughtException = e;
+        } catch (IOException e) {
+            caughtException = e;
+        } catch (XmlPullParserException e) {
+            caughtException = e;
+        } finally {
+            if (parser != null) parser.close();
+        }
+        if (caughtException != null) {
+            Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
+            return null;
+        }
+        if (cn == null) {
+            return null;
+        }
+        if (cn.indexOf('/') < 0) {
+            cn = resolveInfo.serviceInfo.packageName + "/" + cn;
+        }
+        return ComponentName.unflattenFromString(cn);
+    }
+
+    private ComponentName getComponentName(ResolveInfo resolveInfo) {
+        if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
+        return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+    }
+
+    // Agent dispatch and aggregation
+
+    private boolean aggregateIsTrusted(int userId) {
+        for (int i = 0; i < mActiveAgents.size(); i++) {
+            AgentInfo info = mActiveAgents.valueAt(i);
+            if (info.userId == userId) {
+                if (info.agent.isTrusted()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private void dispatchUnlockAttempt(boolean successful, int userId) {
+        for (int i = 0; i < mActiveAgents.size(); i++) {
+            AgentInfo info = mActiveAgents.valueAt(i);
+            if (info.userId == userId) {
+                info.agent.onUnlockAttempt(successful);
+            }
+        }
+    }
+
+    // Listeners
+
+    private void addListener(ITrustListener listener) {
+        for (int i = 0; i < mTrustListeners.size(); i++) {
+            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
+                return;
+            }
+        }
+        mTrustListeners.add(listener);
+    }
+
+    private void removeListener(ITrustListener listener) {
+        for (int i = 0; i < mTrustListeners.size(); i++) {
+            if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
+                mTrustListeners.get(i);
+                return;
+            }
+        }
+    }
+
+    private void dispatchOnTrustChanged(boolean enabled, int userId) {
+        for (int i = 0; i < mTrustListeners.size(); i++) {
+            try {
+                mTrustListeners.get(i).onTrustChanged(enabled, userId);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Exception while notifying TrustListener. Removing listener.", e);
+                mTrustListeners.get(i);
+                i--;
+            }
+        }
+    }
+
+    // Plumbing
+
+    private final IBinder mService = new ITrustManager.Stub() {
+        @Override
+        public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
+            enforceReportPermission();
+            mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
+                    .sendToTarget();
+        }
+
+        @Override
+        public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
+            enforceReportPermission();
+            // coalesce refresh messages.
+            mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
+            mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
+        }
+
+        @Override
+        public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
+            enforceListenerPermission();
+            mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
+        }
+
+        @Override
+        public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
+            enforceListenerPermission();
+            mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
+        }
+
+        private void enforceReportPermission() {
+            mContext.enforceCallingPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
+                    "reporting trust events");
+        }
+
+        private void enforceListenerPermission() {
+            mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
+                    "register trust listener");
+        }
+    };
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_REGISTER_LISTENER:
+                    addListener((ITrustListener) msg.obj);
+                    break;
+                case MSG_UNREGISTER_LISTENER:
+                    removeListener((ITrustListener) msg.obj);
+                    break;
+                case MSG_DISPATCH_UNLOCK_ATTEMPT:
+                    dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
+                    break;
+                case MSG_ENABLED_AGENTS_CHANGED:
+                    refreshAgentList();
+                    break;
+            }
+        }
+    };
+
+    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+        @Override
+        public void onSomePackagesChanged() {
+            refreshAgentList();
+        }
+
+        @Override
+        public boolean onPackageChanged(String packageName, int uid, String[] components) {
+            // We're interested in all changes, even if just some components get enabled / disabled.
+            return true;
+        }
+    };
+}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
new file mode 100644
index 0000000..972b088
--- /dev/null
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -0,0 +1,667 @@
+/*
+ * 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.tv;
+
+import android.app.ActivityManager;
+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.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.tv.ITvInputClient;
+import android.tv.ITvInputManager;
+import android.tv.ITvInputService;
+import android.tv.ITvInputServiceCallback;
+import android.tv.ITvInputSession;
+import android.tv.ITvInputSessionCallback;
+import android.tv.TvInputInfo;
+import android.tv.TvInputService;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.server.SystemService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** This class provides a system service that manages television inputs. */
+public final class TvInputManagerService extends SystemService {
+    // STOPSHIP: Turn debugging off.
+    private static final boolean DEBUG = true;
+    private static final String TAG = "TvInputManagerService";
+
+    private final Context mContext;
+
+    // A global lock.
+    private final Object mLock = new Object();
+
+    // ID of the current user.
+    private int mCurrentUserId = UserHandle.USER_OWNER;
+
+    // A map from user id to UserState.
+    private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
+
+    public TvInputManagerService(Context context) {
+        super(context);
+        mContext = context;
+        registerBroadcastReceivers();
+        synchronized (mLock) {
+            mUserStates.put(mCurrentUserId, new UserState());
+            buildTvInputListLocked(mCurrentUserId);
+        }
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.TV_INPUT_SERVICE, new BinderService());
+    }
+
+    private void registerBroadcastReceivers() {
+        PackageMonitor monitor = new PackageMonitor() {
+            @Override
+            public void onSomePackagesChanged() {
+                synchronized (mLock) {
+                    buildTvInputListLocked(mCurrentUserId);
+                }
+            }
+        };
+        monitor.register(mContext, null, UserHandle.ALL, true);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+    }
+
+    private void buildTvInputListLocked(int userId) {
+        UserState userState = getUserStateLocked(userId);
+        userState.inputList.clear();
+
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> services = pm.queryIntentServices(
+                new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
+        for (ResolveInfo ri : services) {
+            ServiceInfo si = ri.serviceInfo;
+            if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
+                Log.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
+                        + android.Manifest.permission.BIND_TV_INPUT);
+                continue;
+            }
+            TvInputInfo info = new TvInputInfo(ri);
+            userState.inputList.add(info);
+        }
+    }
+
+    private void switchUser(int userId) {
+        synchronized (mLock) {
+            if (mCurrentUserId == userId) {
+                return;
+            }
+            // final int oldUserId = mCurrentUserId;
+            // TODO: Release services and sessions in the old user state, if needed.
+            mCurrentUserId = userId;
+
+            UserState userState = mUserStates.get(userId);
+            if (userState == null) {
+                userState = new UserState();
+            }
+            mUserStates.put(userId, userState);
+            buildTvInputListLocked(userId);
+        }
+    }
+
+    private void removeUser(int userId) {
+        synchronized (mLock) {
+            // Release created sessions.
+            UserState userState = getUserStateLocked(userId);
+            for (SessionState state : userState.sessionStateMap.values()) {
+                if (state.session != null) {
+                    try {
+                        state.session.release();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in release", e);
+                    }
+                }
+            }
+            userState.sessionStateMap.clear();
+
+            // Unregister all callbacks and unbind all services.
+            for (ServiceState serviceState : userState.serviceStateMap.values()) {
+                if (serviceState.callback != null) {
+                    try {
+                        serviceState.service.unregisterCallback(serviceState.callback);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in unregisterCallback", e);
+                    }
+                }
+                serviceState.clients.clear();
+                mContext.unbindService(serviceState.connection);
+            }
+            userState.serviceStateMap.clear();
+
+            mUserStates.remove(userId);
+        }
+    }
+
+    private UserState getUserStateLocked(int userId) {
+        UserState userState = mUserStates.get(userId);
+        if (userState == null) {
+            throw new IllegalStateException("User state not found for user ID " + userId);
+        }
+        return userState;
+    }
+
+    private ServiceState getServiceStateLocked(ComponentName name, int userId) {
+        UserState userState = getUserStateLocked(userId);
+        ServiceState serviceState = userState.serviceStateMap.get(name);
+        if (serviceState == null) {
+            throw new IllegalStateException("Service state not found for " + name + " (userId=" +
+                    userId + ")");
+        }
+        return serviceState;
+    }
+
+    private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) {
+        UserState userState = getUserStateLocked(userId);
+        SessionState sessionState = userState.sessionStateMap.get(sessionToken);
+        if (sessionState == null) {
+            throw new IllegalArgumentException("Session state not found for token " + sessionToken);
+        }
+        // Only the application that requested this session or the system can access it.
+        if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.callingUid) {
+            throw new SecurityException("Illegal access to the session with token " + sessionToken
+                    + " from uid " + callingUid);
+        }
+        ITvInputSession session = sessionState.session;
+        if (session == null) {
+            throw new IllegalStateException("Session not yet created for token " + sessionToken);
+        }
+        return session;
+    }
+
+    private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId,
+            String methodName) {
+        return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false,
+                false, methodName, null);
+    }
+
+    private void updateServiceConnectionLocked(ComponentName name, int userId) {
+        UserState userState = getUserStateLocked(userId);
+        ServiceState serviceState = userState.serviceStateMap.get(name);
+        if (serviceState == null) {
+            return;
+        }
+        boolean isStateEmpty = serviceState.clients.size() == 0
+                && serviceState.sessionStateMap.size() == 0;
+        if (serviceState.service == null && !isStateEmpty && userId == mCurrentUserId) {
+            // This means that the service is not yet connected but its state indicates that we
+            // have pending requests. Then, connect the service.
+            if (serviceState.bound) {
+                // We have already bound to the service so we don't try to bind again until after we
+                // unbind later on.
+                return;
+            }
+            if (DEBUG) {
+                Log.i(TAG, "bindServiceAsUser(name=" + name.getClassName() + ", userId=" + userId
+                        + ")");
+            }
+            Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(name);
+            mContext.bindServiceAsUser(i, serviceState.connection, Context.BIND_AUTO_CREATE,
+                    new UserHandle(userId));
+            serviceState.bound = true;
+        } else if (serviceState.service != null && isStateEmpty) {
+            // This means that the service is already connected but its state indicates that we have
+            // nothing to do with it. Then, disconnect the service.
+            if (DEBUG) {
+                Log.i(TAG, "unbindService(name=" + name.getClassName() + ")");
+            }
+            mContext.unbindService(serviceState.connection);
+            userState.serviceStateMap.remove(name);
+        }
+    }
+
+    private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken,
+            final SessionState sessionState, final int userId) {
+        if (DEBUG) {
+            Log.d(TAG, "createSessionInternalLocked(name=" + sessionState.name.getClassName()
+                    + ")");
+        }
+        // Set up a callback to send the session token.
+        ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() {
+            @Override
+            public void onSessionCreated(ITvInputSession session) {
+                if (DEBUG) {
+                    Log.d(TAG, "onSessionCreated(name=" + sessionState.name.getClassName() + ")");
+                }
+                synchronized (mLock) {
+                    sessionState.session = session;
+                    sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
+                            sessionToken, sessionState.seq, userId);
+                }
+            }
+        };
+
+        // Create a session. When failed, send a null token immediately.
+        try {
+            service.createSession(callback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "error in createSession", e);
+            sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
+                    sessionState.seq, userId);
+        }
+    }
+
+    private void sendSessionTokenToClientLocked(ITvInputClient client, ComponentName name,
+            IBinder sessionToken, int seq, int userId) {
+        try {
+            client.onSessionCreated(name, sessionToken, seq);
+        } catch (RemoteException exception) {
+            Log.e(TAG, "error in onSessionCreated", exception);
+        }
+
+        if (sessionToken == null) {
+            // This means that the session creation failed. We might want to disconnect the service.
+            updateServiceConnectionLocked(name, userId);
+        }
+    }
+
+    private final class BinderService extends ITvInputManager.Stub {
+        @Override
+        public List<TvInputInfo> getTvInputList(int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "getTvInputList");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    return new ArrayList<TvInputInfo>(userState.inputList);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public boolean getAvailability(final ITvInputClient client, final ComponentName name,
+                int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "getAvailability");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    ServiceState serviceState = userState.serviceStateMap.get(name);
+                    if (serviceState != null) {
+                        // We already know the status of this input service. Return the cached
+                        // status.
+                        return serviceState.available;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return false;
+        }
+
+        @Override
+        public void registerCallback(final ITvInputClient client, final ComponentName name,
+                int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "registerCallback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    // Create a new service callback and add it to the callback map of the current
+                    // service.
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    ServiceState serviceState = userState.serviceStateMap.get(name);
+                    if (serviceState == null) {
+                        serviceState = new ServiceState(name, resolvedUserId);
+                        userState.serviceStateMap.put(name, serviceState);
+                    }
+                    IBinder iBinder = client.asBinder();
+                    if (!serviceState.clients.contains(iBinder)) {
+                        serviceState.clients.add(iBinder);
+                    }
+                    if (serviceState.service != null) {
+                        if (serviceState.callback != null) {
+                            // We already handled.
+                            return;
+                        }
+                        serviceState.callback = new ServiceCallback(resolvedUserId);
+                        try {
+                            serviceState.service.registerCallback(serviceState.callback);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "error in registerCallback", e);
+                        }
+                    } else {
+                        updateServiceConnectionLocked(name, resolvedUserId);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void unregisterCallback(ITvInputClient client, ComponentName name, int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "unregisterCallback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    ServiceState serviceState = userState.serviceStateMap.get(name);
+                    if (serviceState == null) {
+                        return;
+                    }
+
+                    // Remove this client from the client list and unregister the callback.
+                    serviceState.clients.remove(client.asBinder());
+                    if (!serviceState.clients.isEmpty()) {
+                        // We have other clients who want to keep the callback. Do this later.
+                        return;
+                    }
+                    if (serviceState.service == null || serviceState.callback == null) {
+                        return;
+                    }
+                    try {
+                        serviceState.service.unregisterCallback(serviceState.callback);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in unregisterCallback", e);
+                    } finally {
+                        serviceState.callback = null;
+                        updateServiceConnectionLocked(name, resolvedUserId);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void createSession(final ITvInputClient client, final ComponentName name,
+                int seq, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "createSession");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    // Create a new session token and a session state.
+                    IBinder sessionToken = new Binder();
+                    SessionState sessionState = new SessionState(name, client, seq, callingUid);
+                    sessionState.session = null;
+
+                    // Add them to the global session state map of the current user.
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    userState.sessionStateMap.put(sessionToken, sessionState);
+
+                    // Also, add them to the session state map of the current service.
+                    ServiceState serviceState = userState.serviceStateMap.get(name);
+                    if (serviceState == null) {
+                        serviceState = new ServiceState(name, resolvedUserId);
+                        userState.serviceStateMap.put(name, serviceState);
+                    }
+                    serviceState.sessionStateMap.put(sessionToken, sessionState);
+
+                    if (serviceState.service != null) {
+                        createSessionInternalLocked(serviceState.service, sessionToken,
+                                sessionState, resolvedUserId);
+                    } else {
+                        updateServiceConnectionLocked(name, resolvedUserId);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void releaseSession(IBinder sessionToken, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "releaseSession");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    // Release the session.
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).release();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in release", e);
+                    }
+
+                    // Remove its state from the global session state map of the current user.
+                    UserState userState = getUserStateLocked(resolvedUserId);
+                    SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
+
+                    // Also remove it from the session state map of the current service.
+                    ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
+                    if (serviceState != null) {
+                        serviceState.sessionStateMap.remove(sessionToken);
+                    }
+
+                    updateServiceConnectionLocked(sessionState.name, resolvedUserId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void setSurface(IBinder sessionToken, Surface surface, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "setSurface");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface(
+                                surface);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in setSurface", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void setVolume(IBinder sessionToken, float volume, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "setVolume");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume(
+                                volume);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in setVolume", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void tune(IBinder sessionToken, final Uri channelUri, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "tune");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    SessionState sessionState = getUserStateLocked(resolvedUserId)
+                            .sessionStateMap.get(sessionToken);
+                    final String serviceName = sessionState.name.getClassName();
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in tune", e);
+                        return;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+
+    private static final class UserState {
+        // A list of all known TV inputs on the system.
+        private final List<TvInputInfo> inputList = new ArrayList<TvInputInfo>();
+
+        // A mapping from the name of a TV input service to its state.
+        private final Map<ComponentName, ServiceState> serviceStateMap =
+                new HashMap<ComponentName, ServiceState>();
+
+        // A mapping from the token of a TV input session to its state.
+        private final Map<IBinder, SessionState> sessionStateMap =
+                new HashMap<IBinder, SessionState>();
+    }
+
+    private final class ServiceState {
+        private final List<IBinder> clients = new ArrayList<IBinder>();
+        private final ArrayMap<IBinder, SessionState> sessionStateMap = new ArrayMap<IBinder,
+                SessionState>();
+        private final ServiceConnection connection;
+
+        private ITvInputService service;
+        private ServiceCallback callback;
+        private boolean bound;
+        private boolean available;
+
+        private ServiceState(ComponentName name, int userId) {
+            this.connection = new InputServiceConnection(userId);
+        }
+    }
+
+    private static final class SessionState {
+        private final ComponentName name;
+        private final ITvInputClient client;
+        private final int seq;
+        private final int callingUid;
+
+        private ITvInputSession session;
+
+        private SessionState(ComponentName name, ITvInputClient client, int seq, int callingUid) {
+            this.name = name;
+            this.client = client;
+            this.seq = seq;
+            this.callingUid = callingUid;
+        }
+    }
+
+    private final class InputServiceConnection implements ServiceConnection {
+        private final int mUserId;
+
+        private InputServiceConnection(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) {
+                Log.d(TAG, "onServiceConnected(name=" + name.getClassName() + ")");
+            }
+            synchronized (mLock) {
+                ServiceState serviceState = getServiceStateLocked(name, mUserId);
+                serviceState.service = ITvInputService.Stub.asInterface(service);
+
+                // Register a callback, if we need to.
+                if (!serviceState.clients.isEmpty() && serviceState.callback == null) {
+                    serviceState.callback = new ServiceCallback(mUserId);
+                    try {
+                        serviceState.service.registerCallback(serviceState.callback);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error in registerCallback", e);
+                    }
+                }
+
+                // And create sessions, if any.
+                for (Map.Entry<IBinder, SessionState> entry : serviceState.sessionStateMap
+                        .entrySet()) {
+                    createSessionInternalLocked(serviceState.service, entry.getKey(),
+                            entry.getValue(), mUserId);
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) {
+                Log.d(TAG, "onServiceDisconnected(name=" + name.getClassName() + ")");
+            }
+        }
+    }
+
+    private final class ServiceCallback extends ITvInputServiceCallback.Stub {
+        private final int mUserId;
+
+        ServiceCallback(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onAvailabilityChanged(ComponentName name, boolean isAvailable)
+                throws RemoteException {
+            if (DEBUG) {
+                Log.d(TAG, "onAvailabilityChanged(name=" + name.getClassName() + ", isAvailable="
+                        + isAvailable + ")");
+            }
+            synchronized (mLock) {
+                ServiceState serviceState = getServiceStateLocked(name, mUserId);
+                serviceState.available = isAvailable;
+                for (IBinder iBinder : serviceState.clients) {
+                    ITvInputClient client = ITvInputClient.Stub.asInterface(iBinder);
+                    client.onAvailabilityChanged(name, isAvailable);
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
new file mode 100644
index 0000000..fbfca93
--- /dev/null
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class CircularDisplayMask {
+    private static final String TAG = "CircularDisplayMask";
+
+    private static final int STROKE_WIDTH = 2;
+
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
+    private Paint mPaint;
+
+    public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
+        SurfaceControl ctrl = null;
+        try {
+            ctrl = new SurfaceControl(session, "CircularDisplayMask",
+                320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(display.getLayerStack());
+            ctrl.setLayer(zOrder);
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (OutOfResourcesException e) {
+        }
+        mSurfaceControl = ctrl;
+        mDrawNeeded = true;
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStrokeWidth(STROKE_WIDTH);
+    }
+
+    private void drawIfNeeded() {
+        if (!mDrawNeeded) {
+            return;
+        }
+        mDrawNeeded = false;
+
+        Rect dirty = new Rect(0, 0, mLastDW, mLastDH);
+        Canvas c = null;
+        try {
+            c = mSurface.lockCanvas(dirty);
+        } catch (IllegalArgumentException e) {
+        } catch (Surface.OutOfResourcesException e) {
+        }
+        if (c == null) {
+            return;
+        }
+        c.drawCircle(160, 160, 160, mPaint);
+
+        mSurface.unlockCanvasAndPost(c);
+    }
+
+    // Note: caller responsible for being inside
+    // Surface.openTransaction() / closeTransaction()
+    public void setVisibility(boolean on) {
+        if (mSurfaceControl == null) {
+            return;
+        }
+        drawIfNeeded();
+        if (on) {
+            mSurfaceControl.show();
+        } else {
+            mSurfaceControl.hide();
+        }
+    }
+
+    void positionSurface(int dw, int dh) {
+        if (mLastDW == dw && mLastDH == dh) {
+            return;
+        }
+        mLastDW = dw;
+        mLastDH = dh;
+        mSurfaceControl.setSize(dw, dh);
+        mDrawNeeded = true;
+    }
+
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0558b5a..b12ae4f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -86,6 +86,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
@@ -285,6 +286,8 @@
     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
     private static final String SIZE_OVERRIDE = "ro.config.size_override";
 
+    private static final String SCREEN_CIRCULAR = "ro.display.circular";
+
     private static final int MAX_SCREENSHOT_RETRIES = 3;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -302,14 +305,14 @@
 
     /**
      * Current user when multi-user is enabled. Don't show windows of
-     * non-current user. Also see mRelatedUserIds.
+     * non-current user. Also see mCurrentProfileIds.
      */
     int mCurrentUserId;
     /**
-     * Users related to the current user. These are also allowed to show windows
+     * Users that are profiles of the current user. These are also allowed to show windows
      * on the current user.
      */
-    int[] mRelatedUserIds = new int[0];
+    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
 
     final Context mContext;
 
@@ -422,6 +425,7 @@
     final SurfaceSession mFxSession;
     Watermark mWatermark;
     StrictModeFlash mStrictModeFlash;
+    CircularDisplayMask mCircularDisplayMask;
     FocusedStackFrame mFocusedStackFrame;
 
     int mFocusedStackLayer;
@@ -819,6 +823,7 @@
         }
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
+        showCircularDisplayMaskIfNeeded();
     }
 
     public InputMonitor getInputMonitor() {
@@ -920,6 +925,10 @@
         final IWindow client = win.mClient;
         final WindowToken token = win.mToken;
         final DisplayContent displayContent = win.getDisplayContent();
+        if (displayContent == null) {
+            // It doesn't matter this display is going away.
+            return 0;
+        }
 
         final WindowList windows = win.getWindowList();
         final int N = windows.size();
@@ -1097,6 +1106,9 @@
     private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
         final WindowToken token = win.mToken;
         final DisplayContent displayContent = win.getDisplayContent();
+        if (displayContent == null) {
+            return;
+        }
         final WindowState attached = win.mAttachedWindow;
 
         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
@@ -2254,6 +2266,11 @@
                 return WindowManagerGlobal.ADD_APP_EXITING;
             }
 
+            if (win.getDisplayContent() == null) {
+                Slog.w(TAG, "Adding window to Display that has been removed.");
+                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+            }
+
             mPolicy.adjustWindowParamsLw(win.mAttrs);
             win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
 
@@ -2743,7 +2760,7 @@
             return;
         }
 
-        final DisplayInfo displayInfo = window.getDisplayContent().getDisplayInfo();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         final RectF dispRect = new RectF(0, 0,
                 displayInfo.logicalWidth, displayInfo.logicalHeight);
         matrix.mapRect(dispRect);
@@ -5213,16 +5230,16 @@
         ShutdownThread.rebootSafeMode(mContext, confirm);
     }
 
-    public void updateRelatedUserIds(final int[] relatedUserIds) {
+    public void setCurrentProfileIds(final int[] currentProfileIds) {
         synchronized (mWindowMap) {
-            mRelatedUserIds = relatedUserIds;
+            mCurrentProfileIds = currentProfileIds;
         }
     }
 
-    public void setCurrentUser(final int newUserId, final int[] relatedUserIds) {
+    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
         synchronized (mWindowMap) {
             mCurrentUserId = newUserId;
-            mRelatedUserIds = relatedUserIds;
+            mCurrentProfileIds = currentProfileIds;
             mAppTransition.setCurrentUser(newUserId);
             mPolicy.setCurrentUserLw(newUserId);
 
@@ -5238,10 +5255,10 @@
     }
 
     /* Called by WindowState */
-    boolean isRelatedToOrCurrentUserLocked(int userId) {
+    boolean isCurrentProfileLocked(int userId) {
         if (userId == mCurrentUserId) return true;
-        for (int i = 0; i < mRelatedUserIds.length; i++) {
-            if (mRelatedUserIds[i] == userId) return true;
+        for (int i = 0; i < mCurrentProfileIds.length; i++) {
+            if (mCurrentProfileIds[i] == userId) return true;
         }
         return false;
     }
@@ -5471,6 +5488,37 @@
         }
     }
 
+    public void showCircularDisplayMaskIfNeeded() {
+        if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) {
+            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
+        }
+    }
+
+    public void showCircularMask() {
+        synchronized(mWindowMap) {
+
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                    ">>> OPEN TRANSACTION showDisplayMask");
+            SurfaceControl.openTransaction();
+            try {
+                // TODO(multi-display): support multiple displays
+                if (mCircularDisplayMask == null) {
+                    mCircularDisplayMask = new CircularDisplayMask(
+                            getDefaultDisplayContentLocked().getDisplay(),
+                            mFxSession,
+                            mPolicy.windowTypeToLayerLw(
+                                    WindowManager.LayoutParams.TYPE_POINTER)
+                                    * TYPE_LAYER_MULTIPLIER + 10);
+                }
+                mCircularDisplayMask.setVisibility(true);
+            } finally {
+                SurfaceControl.closeTransaction();
+                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+                        "<<< CLOSE TRANSACTION showDisplayMask");
+            }
+        }
+    }
+
     // TODO: more accounting of which pid(s) turned it on, keep count,
     // only allow disables from pids which have count on, etc.
     @Override
@@ -7095,6 +7143,8 @@
 
         public static final int REMOVE_STARTING_TIMEOUT = 33;
 
+        public static final int SHOW_DISPLAY_MASK = 34;
+
         @Override
         public void handleMessage(Message msg) {
             if (DEBUG_WINDOW_TRACE) {
@@ -7490,6 +7540,11 @@
                     break;
                 }
 
+                case SHOW_DISPLAY_MASK: {
+                    showCircularMask();
+                    break;
+                }
+
                 case DO_ANIMATION_CALLBACK: {
                     try {
                         ((IRemoteCallback)msg.obj).sendResult(null);
@@ -8963,6 +9018,9 @@
             if (mStrictModeFlash != null) {
                 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
             }
+            if (mCircularDisplayMask != null) {
+                mCircularDisplayMask.positionSurface(defaultDw, defaultDh);
+            }
 
             boolean focusDisplayed = false;
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2c0e99e..dff75ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1249,7 +1249,7 @@
         }
 
         return win.mShowToOwnerOnly
-                && !mService.isRelatedToOrCurrentUserLocked(UserHandle.getUserId(win.mOwnerUid));
+                && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
     }
 
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6b3c368..3c9d53e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -176,9 +176,15 @@
         mAnimator = service.mAnimator;
         mPolicy = service.mPolicy;
         mContext = service.mContext;
-        final DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
-        mAnimDw = displayInfo.appWidth;
-        mAnimDh = displayInfo.appHeight;
+        final DisplayContent displayContent = win.getDisplayContent();
+        if (displayContent != null) {
+            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+            mAnimDw = displayInfo.appWidth;
+            mAnimDh = displayInfo.appHeight;
+        } else {
+            Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
+            // This is checked on return and dealt with.
+        }
 
         mWin = win;
         mAttachedWinAnimator = win.mAttachedWindow == null
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
index 6170c09..a00aaa8 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
@@ -20,7 +20,7 @@
 
 #include "ScopedPrimitiveArray.h"
 
-#include <cstring>
+#include <string>
 #include <deque>
 #include <map>
 
@@ -34,7 +34,6 @@
     jmethodID handleMessage;
     jmethodID handleHotplug;
     jmethodID getActiveSource;
-    jmethodID getOsdName;
     jmethodID getLanguage;
 } gHdmiCecServiceClassInfo;
 
@@ -63,30 +62,28 @@
     void initialize();
 
     // initialize individual logical device.
-    int initLogicalDevice(int type);
-    void releaseLogicalDevice(int type);
+    cec_logical_address_t initLogicalDevice(cec_device_type_t type);
+    void releaseLogicalDevice(cec_device_type_t type);
 
-    cec_logical_address_t getLogicalAddress(int deviceType);
+    cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType);
+    uint16_t getPhysicalAddress();
     int getDeviceType(cec_logical_address_t addr);
     void queueMessage(const MessageEntry& message);
     void queueOutgoingMessage(const cec_message_t& message);
     void sendReportPhysicalAddress();
     void sendActiveSource(cec_logical_address_t srcAddr);
-    void sendInactiveSource(cec_logical_address_t srcAddr);
-    void sendImageViewOn(cec_logical_address_t srcAddr);
-    void sendTextViewOn(cec_logical_address_t srcAddr);
-    void sendGiveDevicePowerStatus(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
     void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
             int opcode, int reason);
     void sendCecVersion(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
             int version);
-    void sendDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
+    void sendDeviceVendorId(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
     void sendGiveDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
     void sendSetOsdName(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
             const char* name, size_t len);
     void sendSetMenuLanguage(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
 
     void sendCecMessage(const cec_message_t& message);
+    void setOsdName(const char* name, size_t len);
 
 private:
     enum {
@@ -104,6 +101,7 @@
     static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     void updatePhysicalAddress();
+    void updateLogicalAddress();
     void dispatchMessage(const MessageEntry& message);
     void processIncomingMessage(const cec_message_t& msg);
 
@@ -147,7 +145,7 @@
     };
 
     // device type -> logical address mapping
-    std::map<int, cec_logical_address_t> mLogicalDevices;
+    std::map<cec_device_type_t, cec_logical_address_t> mLogicalDevices;
 
     hdmi_cec_device_t* mDevice;
     jobject mCallbacksObj;
@@ -158,6 +156,7 @@
 
     std::deque<MessageEntry> mMessageQueue;
     uint16_t mPhysicalAddress;
+    std::string mOsdName;
 };
 
 
@@ -173,6 +172,10 @@
     updatePhysicalAddress();
 }
 
+uint16_t HdmiCecHandler::getPhysicalAddress() {
+    return mPhysicalAddress;
+}
+
 void HdmiCecHandler::updatePhysicalAddress() {
     uint16_t addr;
     if (!mDevice->get_physical_address(mDevice, &addr)) {
@@ -182,7 +185,17 @@
     }
 }
 
-int HdmiCecHandler::initLogicalDevice(int type) {
+void HdmiCecHandler::updateLogicalAddress() {
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+    for (; it != mLogicalDevices.end(); ++it) {
+        cec_logical_address_t addr;
+        if (!mDevice->get_logical_address(mDevice, it->first, &addr)) {
+            it->second = addr;
+        }
+    }
+}
+
+cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) {
     cec_logical_address_t addr;
     int res = mDevice->allocate_logical_address(mDevice, type, &addr);
 
@@ -190,21 +203,21 @@
         ALOGE("Logical Address Allocation failed: %d", res);
     } else {
         ALOGV("Logical Address Allocation success: %d", addr);
-        mLogicalDevices.insert(std::pair<int, cec_logical_address_t>(type, addr));
+        mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));
     }
     return addr;
 }
 
-void HdmiCecHandler::releaseLogicalDevice(int type) {
-    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
+void HdmiCecHandler::releaseLogicalDevice(cec_device_type_t type) {
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
     if (it != mLogicalDevices.end()) {
         mLogicalDevices.erase(it);
     }
     // TODO: remove the address monitored in HAL as well.
 }
 
-cec_logical_address_t HdmiCecHandler::getLogicalAddress(int mDevicetype) {
-    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(mDevicetype);
+cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type) {
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
     if (it != mLogicalDevices.end()) {
         return it->second;
     }
@@ -212,7 +225,7 @@
 }
 
 int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
-    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
     for (; it != mLogicalDevices.end(); ++it) {
         if (it->second == addr) {
             return it->first;
@@ -245,14 +258,15 @@
     }
 
     // Report physical address for each logical one hosted in it.
-    std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
     while (it != mLogicalDevices.end()) {
         cec_message_t msg;
         msg.initiator = it->second;  // logical address
         msg.destination = CEC_ADDR_BROADCAST;
         msg.length = 4;
         msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
-        std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
+        msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
+        msg.body[2] = mPhysicalAddress & 0xff;
         msg.body[3] = it->first;  // device type
         queueOutgoingMessage(msg);
         ++it;
@@ -269,47 +283,8 @@
     msg.destination = CEC_ADDR_BROADCAST;
     msg.length = 3;
     msg.body[0] = CEC_MESSAGE_ACTIVE_SOURCE;
-    std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
-    queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendInactiveSource(cec_logical_address_t srcAddr) {
-    cec_message_t msg;
-    msg.initiator = srcAddr;
-    msg.destination = CEC_ADDR_TV;
-    msg.length = 3;
-    msg.body[0] = CEC_MESSAGE_INACTIVE_SOURCE;
-    if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
-        std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
-        queueOutgoingMessage(msg);
-    }
-}
-
-void HdmiCecHandler::sendImageViewOn(cec_logical_address_t srcAddr) {
-    cec_message_t msg;
-    msg.initiator = srcAddr;
-    msg.destination = CEC_ADDR_TV;
-    msg.length = 1;
-    msg.body[0] = CEC_MESSAGE_IMAGE_VIEW_ON;
-    queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendTextViewOn(cec_logical_address_t srcAddr) {
-    cec_message_t msg;
-    msg.initiator = srcAddr;
-    msg.destination = CEC_ADDR_TV;
-    msg.length = 1;
-    msg.body[0] = CEC_MESSAGE_TEXT_VIEW_ON;
-    queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendGiveDevicePowerStatus(cec_logical_address_t srcAddr,
-        cec_logical_address_t dstAddr) {
-    cec_message_t msg;
-    msg.initiator = srcAddr;
-    msg.destination = dstAddr;
-    msg.length = 1;
-    msg.body[0] = CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS;
+    msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
+    msg.body[2] = mPhysicalAddress & 0xff;
     queueOutgoingMessage(msg);
 }
 
@@ -346,7 +321,7 @@
     queueOutgoingMessage(msg);
 }
 
-void HdmiCecHandler::sendDeviceVendorID(cec_logical_address_t srcAddr,
+void HdmiCecHandler::sendDeviceVendorId(cec_logical_address_t srcAddr,
         cec_logical_address_t dstAddr) {
     cec_message_t msg;
     msg.initiator = srcAddr;
@@ -355,7 +330,9 @@
     msg.body[0] = CEC_MESSAGE_DEVICE_VENDOR_ID;
     uint32_t vendor_id;
     mDevice->get_vendor_id(mDevice, &vendor_id);
-    std::memcpy(msg.body + 1, &vendor_id, 3);
+    msg.body[1] = (vendor_id >> 16) & 0xff;
+    msg.body[2] = (vendor_id >> 8) & 0xff;
+    msg.body[3] = vendor_id & 0xff;
     queueOutgoingMessage(msg);
 }
 
@@ -397,6 +374,10 @@
     mDevice->send_message(mDevice, &message);
 }
 
+void HdmiCecHandler::setOsdName(const char* name, size_t len) {
+    mOsdName.assign(name, min(len, CEC_MESSAGE_BODY_MAX_LENGTH - 1));
+}
+
 // static
 void HdmiCecHandler::onReceived(const hdmi_event_t* event, void* arg) {
     HdmiCecHandler* handler = static_cast<HdmiCecHandler*>(arg);
@@ -437,9 +418,8 @@
         mMessageQueue.pop_front();
         bool connected = entry.second.hotplug.connected;
         if (connected) {
-            // TODO: Update logical addresses as well, since they also could have
-            // changed while the cable was disconnected.
             updatePhysicalAddress();
+            updateLogicalAddress();
         }
         propagateHotplug(connected);
     }
@@ -460,6 +440,9 @@
         handleGetCECVersion(msg);
     } else if (opcode == CEC_MESSAGE_GET_MENU_LANGUAGE) {
         handleGetMenuLanguage(msg);
+    } else if (opcode == CEC_MESSAGE_ABORT) {
+        // Compliance testing requires that abort message be responded with feature abort.
+        sendFeatureAbort(msg.destination, msg.initiator, msg.body[0], ABORT_REFUSED);
     } else {
         if (precheckMessage(msg)) {
             propagateMessage(msg);
@@ -480,8 +463,7 @@
             (opcode == CEC_MESSAGE_ACTIVE_SOURCE ||
              opcode == CEC_MESSAGE_SET_STREAM_PATH ||
              opcode == CEC_MESSAGE_INACTIVE_SOURCE)) {
-        uint16_t senderAddr;
-        std::memcpy(&senderAddr, &msg.body[1], 2);
+        uint16_t senderAddr = (msg.body[1] << 8) + msg.body[2];
         if (senderAddr == mPhysicalAddress) {
             return false;
         }
@@ -521,28 +503,19 @@
     jint activeDeviceType = env->CallIntMethod(mCallbacksObj,
             gHdmiCecServiceClassInfo.getActiveSource);
     if (activeDeviceType != INACTIVE_DEVICE_TYPE) {
-        sendActiveSource(getLogicalAddress(activeDeviceType));
+        sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType)));
     }
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
 void HdmiCecHandler::handleGetOsdName(const cec_message_t& msg) {
-    cec_logical_address_t addr = msg.destination;
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jbyteArray res = (jbyteArray) env->CallObjectMethod(mCallbacksObj,
-            gHdmiCecServiceClassInfo.getOsdName,
-            getDeviceType(addr));
-    jbyte *name = env->GetByteArrayElements(res, NULL);
-    if (name != NULL) {
-        sendSetOsdName(addr, msg.initiator, reinterpret_cast<const char *>(name),
-                env->GetArrayLength(res));
-        env->ReleaseByteArrayElements(res, name, JNI_ABORT);
+    if (!mOsdName.empty()) {
+        sendSetOsdName(msg.destination, msg.initiator, mOsdName.c_str(), mOsdName.length());
     }
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
 void HdmiCecHandler::handleGiveDeviceVendorID(const cec_message_t& msg) {
-    sendDeviceVendorID(msg.destination, msg.initiator);
+    sendDeviceVendorId(msg.destination, msg.initiator);
 }
 
 void HdmiCecHandler::handleGetCECVersion(const cec_message_t& msg) {
@@ -585,8 +558,6 @@
             "handleHotplug", "(Z)V");
     GET_METHOD_ID(gHdmiCecServiceClassInfo.getActiveSource, clazz,
             "getActiveSource", "()I");
-    GET_METHOD_ID(gHdmiCecServiceClassInfo.getOsdName, clazz,
-            "getOsdName", "(I)[B");
     GET_METHOD_ID(gHdmiCecServiceClassInfo.getLanguage, clazz,
             "getLanguage", "(I)Ljava/lang/String;");
 
@@ -596,64 +567,43 @@
 static void nativeSendMessage(JNIEnv* env, jclass clazz, jlong handlerPtr, jint deviceType,
         jint dstAddr, jint opcode, jbyteArray params) {
     HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
+    cec_logical_address_t srcAddr = handler->getLogicalAddress(
+            static_cast<cec_device_type_t>(deviceType));
     jsize len = env->GetArrayLength(params);
     ScopedByteArrayRO paramsPtr(env, params);
     cec_message_t message;
     message.initiator = srcAddr;
     message.destination = static_cast<cec_logical_address_t>(dstAddr);
-    message.length = len + 1;
+    message.length = min(len + 1, CEC_MESSAGE_BODY_MAX_LENGTH);
     message.body[0] = opcode;
-    std::memcpy(message.body + 1, paramsPtr.get(), len);
+    std::memcpy(message.body + 1, paramsPtr.get(), message.length - 1);
     handler->sendCecMessage(message);
 }
 
-static int nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
+static jint nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
         jint deviceType) {
     HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    return handler->initLogicalDevice(deviceType);
+    return handler->initLogicalDevice(static_cast<cec_device_type_t>(deviceType));
 }
 
 static void nativeRemoveLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
        jint deviceType) {
     HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    return handler->releaseLogicalDevice(deviceType);
+    return handler->releaseLogicalDevice(static_cast<cec_device_type_t>(deviceType));
 }
 
-static void nativeSendActiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
-        jint deviceType) {
+static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr) {
     HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
-    handler->sendActiveSource(srcAddr);
+    return handler->getPhysicalAddress();
 }
 
-static void nativeSendInactiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
-        jint deviceType) {
+static void nativeSetOsdName(JNIEnv* env, jclass clazz, jlong handlerPtr, jbyteArray name) {
     HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
-    handler->sendInactiveSource(srcAddr);
-}
-
-static void nativeSendImageViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
-        jint deviceType) {
-    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
-    handler->sendImageViewOn(srcAddr);
-}
-
-static void nativeSendTextViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
-        jint deviceType) {
-    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
-    handler->sendTextViewOn(srcAddr);
-}
-
-static void nativeSendGiveDevicePowerStatus(JNIEnv* env, jclass clazz, jlong handlerPtr,
-        jint deviceType, jint destination) {
-    HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
-    cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
-    cec_logical_address_t dstAddr = static_cast<cec_logical_address_t>(destination);
-    handler->sendGiveDevicePowerStatus(srcAddr, dstAddr);
+    jsize len = env->GetArrayLength(name);
+    if (len > 0) {
+        ScopedByteArrayRO namePtr(env, name);
+        handler->setOsdName(reinterpret_cast<const char *>(namePtr.get()), len);
+    }
 }
 
 static JNINativeMethod sMethods[] = {
@@ -666,16 +616,10 @@
             (void *)nativeAllocateLogicalAddress },
     { "nativeRemoveLogicalAddress", "(JI)V",
             (void *)nativeRemoveLogicalAddress },
-    { "nativeSendActiveSource", "(JI)V",
-            (void *)nativeSendActiveSource },
-    { "nativeSendInactiveSource", "(JI)V",
-            (void *)nativeSendInactiveSource },
-    { "nativeSendImageViewOn", "(JI)V",
-            (void *)nativeSendImageViewOn },
-    { "nativeSendTextViewOn", "(JI)V",
-            (void *)nativeSendTextViewOn },
-    { "nativeSendGiveDevicePowerStatus", "(JII)V",
-            (void *)nativeSendGiveDevicePowerStatus }
+    { "nativeGetPhysicalAddress", "(J)I",
+            (void *)nativeGetPhysicalAddress },
+    { "nativeSetOsdName", "(J[B)V",
+            (void *)nativeSetOsdName },
 };
 
 #define CLASS_PATH "com/android/server/hdmi/HdmiCecService"
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index e1069ae..b3247ff 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -150,7 +150,7 @@
     status_t status = android_view_PointerIcon_loadSystemIcon(env,
             contextObj, style, &pointerIcon);
     if (!status) {
-        pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, SkBitmap::kARGB_8888_Config);
+        pointerIcon.bitmap.copyTo(&outSpriteIcon->bitmap, kNative_8888_SkColorType);
         outSpriteIcon->hotSpotX = pointerIcon.hotSpotX;
         outSpriteIcon->hotSpotY = pointerIcon.hotSpotY;
     }
@@ -1297,7 +1297,7 @@
 
     size_t patternSize = env->GetArrayLength(patternObj);
     if (patternSize > MAX_VIBRATE_PATTERN_SIZE) {
-        ALOGI("Skipped requested vibration because the pattern size is %d "
+        ALOGI("Skipped requested vibration because the pattern size is %zu "
                 "which is more than the maximum supported size of %d.",
                 patternSize, MAX_VIBRATE_PATTERN_SIZE);
         return; // limit to reasonable size
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 151e134..dbf5439 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -189,6 +189,18 @@
     }
 }
 
+static void nativeSendPowerHint(JNIEnv *env, jclass clazz, jint hintId, jint data) {
+    int data_param = data;
+
+    if (gPowerModule && gPowerModule->powerHint) {
+        if(data)
+            gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, &data_param);
+        else {
+            gPowerModule->powerHint(gPowerModule, (power_hint_t)hintId, NULL);
+        }
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -205,6 +217,8 @@
             (void*) nativeSetInteractive },
     { "nativeSetAutoSuspend", "(Z)V",
             (void*) nativeSetAutoSuspend },
+    { "nativeSendPowerHint", "(II)V",
+            (void*) nativeSendPowerHint },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f186b2c..983ca2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -170,7 +170,7 @@
         int mActivePasswordNonLetter = 0;
         int mFailedPasswordAttempts = 0;
 
-        int mUserHandle;;
+        int mUserHandle;
         int mPasswordOwner = -1;
         long mLastMaximumTimeToLock = -1;
 
@@ -722,6 +722,10 @@
         final int callingUid = Binder.getCallingUid();
         final int userHandle = UserHandle.getUserId(callingUid);
         final DevicePolicyData policy = getUserData(userHandle);
+
+        List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
+
+        // Build a list of admins for this uid matching the given ComponentName
         if (who != null) {
             ActiveAdmin admin = policy.mAdminMap.get(who);
             if (admin == null) {
@@ -731,22 +735,43 @@
                 throw new SecurityException("Admin " + who + " is not owned by uid "
                         + Binder.getCallingUid());
             }
-            if (!admin.info.usesPolicy(reqPolicy)) {
-                throw new SecurityException("Admin " + admin.info.getComponent()
-                        + " did not specify uses-policy for: "
-                        + admin.info.getTagForPolicy(reqPolicy));
-            }
-            return admin;
+            candidates.add(admin);
         } else {
-            final int N = policy.mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
+            for (ActiveAdmin admin : policy.mAdminList) {
+                if (admin.getUid() == callingUid) {
+                    candidates.add(admin);
+                }
+            }
+        }
+
+        // Try to find an admin which can use reqPolicy
+        for (ActiveAdmin admin : candidates) {
+            boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
+            boolean ownsProfile = (getProfileOwner(userHandle) != null
+                    && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
+
+            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+                if (ownsDevice) {
+                    return admin;
+                }
+            } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+                if (ownsDevice || ownsProfile) {
+                    return admin;
+                }
+            } else {
+                if (admin.info.usesPolicy(reqPolicy)) {
                     return admin;
                 }
             }
+        }
+
+        if (who != null) {
+            throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
+                    + " did not specify uses-policy for: "
+                    + candidates.get(0).info.getTagForPolicy(reqPolicy));
+        } else {
             throw new SecurityException("No active admin owned by uid "
-                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
+                    + Binder.getCallingUid() + " for policy:" + reqPolicy);
         }
     }
 
@@ -2966,64 +2991,41 @@
         }
     }
 
-    private boolean isProfileOwner(String packageName, int userId) {
-        String profileOwnerPackage = getProfileOwner(userId);
-        // TODO: make public and connect with isProfileOwnerApp in DPM
-        return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
-    }
-
-    public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
+    public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
             ComponentName activity) {
-        int callingUserId = UserHandle.getCallingUserId();
-        Slog.d(LOG_TAG,"called by user " + callingUserId);
         synchronized (this) {
-            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
-            if (aa == null) {
-                throw new SecurityException("No active admin " + admin);
-            } else {
-                if (isProfileOwner(admin.getPackageName(), callingUserId)
-                        || isDeviceOwner(admin.getPackageName())) {
-                    IPackageManager pm = AppGlobals.getPackageManager();
-                    long id = Binder.clearCallingIdentity();
-                    try {
-                        pm.addPersistentPreferredActivity(filter, activity, callingUserId);
-                    } catch (RemoteException re) {
-                        // Shouldn't happen
-                    } finally {
-                        restoreCallingIdentity(id);
-                    }
-                } else {
-                    throw new SecurityException("Admin " + admin +
-                            "is not device owner or profile owner" );
-                }
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId());
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
             }
         }
     }
 
-    public void clearPackagePersistentPreferredActivities(ComponentName admin,
-            String packageName) {
-        int callingUserId = UserHandle.getCallingUserId();
-        Slog.d(LOG_TAG,"called by user " + callingUserId);
+    public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
         synchronized (this) {
-            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
-            if (aa == null) {
-                throw new SecurityException("No active admin " + admin);
-            } else {
-                if (isProfileOwner(admin.getPackageName(), callingUserId)
-                        || isDeviceOwner(admin.getPackageName())) {
-                    IPackageManager pm = AppGlobals.getPackageManager();
-                    long id = Binder.clearCallingIdentity();
-                    try{
-                        pm.clearPackagePersistentPreferredActivities(packageName, callingUserId);
-                    } catch (RemoteException re) {
-                        // Shouldn't happen
-                    } finally {
-                        restoreCallingIdentity(id);
-                    }
-                } else {
-                    throw new SecurityException("Admin " + admin +
-                            "is not device owner or profile owner" );
-                }
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId());
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
             }
         }
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c925669..912ac4d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -42,6 +42,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.service.dreams.DreamService;
+import android.tv.TvInputManager;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -50,6 +51,7 @@
 
 import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.os.Zygote;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
@@ -69,6 +71,7 @@
 import com.android.server.notification.NotificationManagerService;
 import com.android.server.os.SchedulingPolicyService;
 import com.android.server.pm.Installer;
+import com.android.server.pm.LauncherAppsService;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.UserManagerService;
 import com.android.server.power.PowerManagerService;
@@ -76,13 +79,14 @@
 import com.android.server.search.SearchManagerService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.storage.DeviceStorageMonitorService;
+import com.android.server.trust.TrustManagerService;
+import com.android.server.tv.TvInputManagerService;
 import com.android.server.twilight.TwilightService;
 import com.android.server.usb.UsbService;
 import com.android.server.wallpaper.WallpaperManagerService;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import java.io.File;
 import java.util.Timer;
@@ -116,6 +120,8 @@
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
+    private static final String WIFI_HOTSPOT_SERVICE_CLASS =
+            "com.android.server.wifi.hotspot.WifiHotspotService";
     private static final String WIFI_P2P_SERVICE_CLASS =
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String HDMI_CEC_SERVICE_CLASS =
@@ -266,7 +272,7 @@
     private void createSystemContext() {
         ActivityThread activityThread = ActivityThread.systemMain();
         mSystemContext = activityThread.getSystemContext();
-        mSystemContext.setTheme(android.R.style.Theme_Holo);
+        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
     }
 
     private void startBootstrapServices() {
@@ -614,6 +620,12 @@
                 }
 
                 try {
+                    mSystemServiceManager.startService(WIFI_HOTSPOT_SERVICE_CLASS);
+                } catch (Throwable e) {
+                    reportWtf("starting Wi-Fi HotspotService", e);
+                }
+
+                try {
                     mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
                 } catch (Throwable e) {
                     reportWtf("starting Wi-Fi Service", e);
@@ -897,6 +909,13 @@
                 reportWtf("starting HdmiCec Service", e);
             }
 
+            try {
+                Slog.i(TAG, "TvInputManagerService");
+                mSystemServiceManager.startService(TvInputManagerService.class);
+            } catch (Throwable e) {
+                reportWtf("starting TvInputManagerService", e);
+            }
+
             if (!disableNonCoreServices) {
                 try {
                     Slog.i(TAG, "Media Router Service");
@@ -905,6 +924,21 @@
                 } catch (Throwable e) {
                     reportWtf("starting MediaRouterService", e);
                 }
+
+                try {
+                    Slog.i(TAG, "Trust Manager");
+                    mSystemServiceManager.startService(TrustManagerService.class);
+                } catch (Throwable e) {
+                    Slog.e(TAG, "Failure starting TrustManagerService", e);
+                }
+            }
+
+            try {
+                Slog.i(TAG, "LauncherAppsService");
+                LauncherAppsService las = new LauncherAppsService(context);
+                ServiceManager.addService(Context.LAUNCHER_APPS_SERVICE, las);
+            } catch (Throwable t) {
+                reportWtf("starting LauncherAppsService", t);
             }
         }
 
@@ -913,8 +947,6 @@
         final boolean safeMode = wm.detectSafeMode();
         if (safeMode) {
             mActivityManagerService.enterSafeMode();
-            // Post the safe mode state in the Zygote class
-            Zygote.systemInSafeMode = true;
             // Disable the JIT for the system_server process
             VMRuntime.getRuntime().disableJitCompilation();
         } else {
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index ce953a4..f73d425 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -17,8 +17,10 @@
 package com.android.server.usb;
 
 import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.os.Handler;
@@ -244,15 +246,18 @@
     }
 
     private void showConfirmationDialog(String key, String fingerprints) {
-        Intent dialogIntent = new Intent();
+        Intent intent = new Intent();
 
-        dialogIntent.setClassName("com.android.systemui",
-                "com.android.systemui.usb.UsbDebuggingActivity");
-        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        dialogIntent.putExtra("key", key);
-        dialogIntent.putExtra("fingerprints", fingerprints);
+        ComponentName componentName = ComponentName.unflattenFromString(
+                Resources.getSystem().getString(
+                        com.android.internal.R.string.config_customAdbPublicKeyActivity));
+        intent.setClassName(componentName.getPackageName(),
+                componentName.getClassName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra("key", key);
+        intent.putExtra("fingerprints", fingerprints);
         try {
-            mContext.startActivity(dialogIntent);
+            mContext.startActivity(intent);
         } catch (ActivityNotFoundException e) {
             Slog.e(TAG, "unable to start UsbDebuggingActivity");
         }
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 323e0ac..1c75658 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -101,8 +101,93 @@
     /** Unknown error or not specified */
     public static final int ERROR_UNSPECIFIED              = 36;
 
+    /** Smallest valid value for call disconnect codes. */
+    public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
+    /** Largest valid value for call disconnect codes. */
+    public static final int MAXIMUM_VALID_VALUE = ERROR_UNSPECIFIED;
+
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
         // Do nothing.
     }
+
+    /** Returns descriptive string for the specified disconnect cause. */
+    public static String toString(int cause) {
+        switch (cause) {
+        case NOT_DISCONNECTED:
+            return "NOT_DISCONNECTED";
+        case INCOMING_MISSED:
+            return "INCOMING_MISSED";
+        case NORMAL:
+            return "NORMAL";
+        case LOCAL:
+            return "LOCAL";
+        case BUSY:
+            return "BUSY";
+        case CONGESTION:
+            return "CONGESTION";
+        case INVALID_NUMBER:
+            return "INVALID_NUMBER";
+        case NUMBER_UNREACHABLE:
+            return "NUMBER_UNREACHABLE";
+        case SERVER_UNREACHABLE:
+            return "SERVER_UNREACHABLE";
+        case INVALID_CREDENTIALS:
+            return "INVALID_CREDENTIALS";
+        case OUT_OF_NETWORK:
+            return "OUT_OF_NETWORK";
+        case SERVER_ERROR:
+            return "SERVER_ERROR";
+        case TIMED_OUT:
+            return "TIMED_OUT";
+        case LOST_SIGNAL:
+            return "LOST_SIGNAL";
+        case LIMIT_EXCEEDED:
+            return "LIMIT_EXCEEDED";
+        case INCOMING_REJECTED:
+            return "INCOMING_REJECTED";
+        case POWER_OFF:
+            return "POWER_OFF";
+        case OUT_OF_SERVICE:
+            return "OUT_OF_SERVICE";
+        case ICC_ERROR:
+            return "ICC_ERROR";
+        case CALL_BARRED:
+            return "CALL_BARRED";
+        case FDN_BLOCKED:
+            return "FDN_BLOCKED";
+        case CS_RESTRICTED:
+            return "CS_RESTRICTED";
+        case CS_RESTRICTED_NORMAL:
+            return "CS_RESTRICTED_NORMAL";
+        case CS_RESTRICTED_EMERGENCY:
+            return "CS_RESTRICTED_EMERGENCY";
+        case UNOBTAINABLE_NUMBER:
+            return "UNOBTAINABLE_NUMBER";
+        case CDMA_LOCKED_UNTIL_POWER_CYCLE:
+            return "CDMA_LOCKED_UNTIL_POWER_CYCLE";
+        case CDMA_DROP:
+            return "CDMA_DROP";
+        case CDMA_INTERCEPT:
+            return "CDMA_INTERCEPT";
+        case CDMA_REORDER:
+            return "CDMA_REORDER";
+        case CDMA_SO_REJECT:
+            return "CDMA_SO_REJECT";
+        case CDMA_RETRY_ORDER:
+            return "CDMA_RETRY_ORDER";
+        case CDMA_ACCESS_FAILURE:
+            return "CDMA_ACCESS_FAILURE";
+        case CDMA_PREEMPTED:
+            return "CDMA_PREEMPTED";
+        case CDMA_NOT_EMERGENCY:
+            return "CDMA_NOT_EMERGENCY";
+        case CDMA_ACCESS_BLOCKED:
+            return "CDMA_ACCESS_BLOCKED";
+        case ERROR_UNSPECIFIED:
+            return "ERROR_UNSPECIFIED";
+        default:
+            return "INVALID";
+        }
+    }
 }
diff --git a/tests/DynamicDrawableTest/lint.xml b/tests/DynamicDrawableTest/lint.xml
deleted file mode 100644
index ee0eead..0000000
--- a/tests/DynamicDrawableTest/lint.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lint>
-</lint>
\ No newline at end of file
diff --git a/tests/DynamicDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
similarity index 94%
rename from tests/DynamicDrawableTest/Android.mk
rename to tests/VectorDrawableTest/Android.mk
index 5c51301..dd8a4d4 100644
--- a/tests/DynamicDrawableTest/Android.mk
+++ b/tests/VectorDrawableTest/Android.mk
@@ -19,7 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_PACKAGE_NAME := DynamicDrawableTest
+LOCAL_PACKAGE_NAME := VectorDrawableTest
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/DynamicDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
similarity index 98%
rename from tests/DynamicDrawableTest/AndroidManifest.xml
rename to tests/VectorDrawableTest/AndroidManifest.xml
index 4ca3e3c..28c5f33 100644
--- a/tests/DynamicDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -17,7 +17,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.test.dynamic" >
-    <uses-sdk android:minSdkVersion="11" />
+    <uses-sdk android:minSdkVersion="20" />
 
     <application
         android:hardwareAccelerated="true"
@@ -73,7 +73,7 @@
             </intent-filter>
 
         </activity>
-        
+
         <activity
             android:name="VectorCheckbox"
             android:label="On a Checkbox" >
diff --git a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png b/tests/VectorDrawableTest/res/drawable-hdpi/icon.png
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable-hdpi/icon.png
rename to tests/VectorDrawableTest/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/VectorDrawableTest/res/drawable/icon.png
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/icon.png
rename to tests/VectorDrawableTest/res/drawable/icon.png
Binary files differ
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
similarity index 63%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 4f4b386..6ca1aa7 100644
--- a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -14,11 +14,11 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:trigger="state_checked" >
+    android:trigger="state_checked" android:versionCode="1" >
 
     <size
-        android:height="64dp"
-        android:width="64dp" />
+        android:height="48dp"
+        android:width="48dp" />
 
     <viewport
         android:viewportHeight="480"
@@ -28,42 +28,47 @@
         <path
             android:name="check"
             android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
-            android:fill="#ffff00ff"
-            android:stroke="#FF00FF00"
-            android:strokeWidth="5" />
+            android:fill="?android:attr/colorControlActivated" />
     </group>
     <group>
         <path
             android:name="box1"
             android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
-            android:fill="#ffffffff"
-            android:stroke="#FF00FF00"
-            android:strokeWidth="5" />
+            android:fill="?android:attr/colorControlActivated"
+            android:stroke="?android:attr/colorControlActivated"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
     </group>
     <group>
         <path
             android:name="box2"
             android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
-            android:fill="#ff000000"
             android:rotation="46.757"
             android:pivotX="162"
             android:pivotY="173.5"
-            android:stroke="#FF00FF00"
-            android:strokeWidth="5" />
+            android:fill="?attr/android:colorControlNormal"
+            android:stroke="?attr/android:colorControlNormal"
+            android:strokeWidth="3"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
     </group>
     <group>
         <path
             android:name="box3"
             android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
-            android:stroke="#FF000000"
-            android:strokeWidth="4" />
+            android:stroke="?attr/android:colorControlNormal"
+            android:strokeWidth="10"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
     </group>
     <group>
         <path
             android:name="box4"
             android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
-            android:stroke="#FF000000"
-            android:strokeWidth="30" />
+            android:stroke="?attr/android:colorControlNormal"
+            android:strokeWidth="30"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
     </group>
 
     <animation
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
similarity index 98%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
index a1a03be..8787b34 100644
--- a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
@@ -29,7 +29,7 @@
             android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
             android:fill="#3388ff"
             android:stroke="#ff8833"
-            android:strokeWidth="1" 
+            android:strokeWidth="1"
             android:rotation="0"/>
          <path
             android:name="spark"
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml
rename to tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_test01.xml
rename to tests/VectorDrawableTest/res/drawable/vector_test01.xml
diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/drawable/vector_test02.xml
rename to tests/VectorDrawableTest/res/drawable/vector_test02.xml
diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/VectorDrawableTest/res/values/strings.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/values/strings.xml
rename to tests/VectorDrawableTest/res/values/strings.xml
diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/VectorDrawableTest/res/values/styles.xml
similarity index 100%
rename from tests/DynamicDrawableTest/res/values/styles.xml
rename to tests/VectorDrawableTest/res/values/styles.xml
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
index 1060d19..0b3ea4d 100644
--- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
@@ -60,7 +60,6 @@
             CheckBox checkBox = new CheckBox(this);
             bArray[i] = checkBox;
             checkBox.setWidth(200);
-            checkBox.setWidth(200);
             checkBox.setButtonDrawable(icon[i]);
             container.addView(checkBox);
         }
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index 0ae4b6d..88ae398 100644
--- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -59,7 +59,6 @@
             Button button = new Button(this);
             bArray[i] = button;
             button.setWidth(200);
-            button.setWidth(200);
             button.setBackgroundResource(icon[i]);
             container.addView(button);
             button.setOnClickListener(this);
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
similarity index 98%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 9e8ea75..3929298 100644
--- a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -74,7 +74,6 @@
         for (int i = 0; i < icon.length; i++) {
             Button button = new Button(this);
             button.setWidth(200);
-            button.setWidth(200);
             button.setBackgroundResource(icon[i]);
             container.addView(button);
             button.setOnClickListener(this);
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
similarity index 100%
rename from tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
rename to tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 38bfa00..e0dab78 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1342,6 +1342,11 @@
               (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
               | ResTable_config::UI_MODE_TYPE_APPLIANCE;
         return true;
+    } else if (strcmp(name, "watch") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_WATCH;
+        return true;
     }
 
     return false;
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 1fa9615..cb68340 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -53,6 +53,7 @@
 $(LOCAL_BUILT_MODULE): $(built_core_dep) \
                        $(built_framework_dep) \
                        $(built_ext_dep) \
+                       $(built_ext_data) \
                        $(built_layoutlib_create_jar)
 	$(hide) echo "host layoutlib_create: $@"
 	$(hide) mkdir -p $(dir $@)
diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
new file mode 100644
index 0000000..914a359
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide implementation of a select few native methods of {@link AssetManager}
+ * <p/>
+ * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class AssetManager_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static long newTheme(AssetManager manager) {
+        return Resources_Theme_Delegate.getDelegateManager()
+                .addNewDelegate(new Resources_Theme_Delegate());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void deleteTheme(AssetManager manager, long theme) {
+        Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean force) {
+        Resources_Theme_Delegate.getDelegateManager().getDelegate(theme).force = force;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index cfe7525..cc621c4 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -52,9 +52,9 @@
     private final BridgeContext mContext;
     private final boolean mPlatformFile;
 
-    private ResourceValue[] mResourceData;
-    private String[] mNames;
-    private boolean[] mIsFramework;
+    private final ResourceValue[] mResourceData;
+    private final String[] mNames;
+    private final boolean[] mIsFramework;
 
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
@@ -81,8 +81,8 @@
     }
 
     /**
-     * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have
-     * been done.
+     * Seals the array after all calls to
+     * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
      * <p/>This allows to compute the list of non default values, permitting
      * {@link #getIndexCount()} to return the proper value.
      */
@@ -252,7 +252,7 @@
             for (String keyword : keywords) {
                 Integer i = map.get(keyword.trim());
                 if (i != null) {
-                    result |= i.intValue();
+                    result |= i;
                 } else {
                     Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                             String.format(
@@ -731,7 +731,7 @@
         }
 
         // not a direct id valid reference? resolve it
-        Integer idValue = null;
+        Integer idValue;
 
         if (resValue.isFramework()) {
             idValue = Bridge.getResourceId(resValue.getResourceType(),
@@ -742,7 +742,7 @@
         }
 
         if (idValue != null) {
-            return idValue.intValue();
+            return idValue;
         }
 
         Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
@@ -753,6 +753,12 @@
         return defValue;
     }
 
+    @Override
+    public int getThemeAttributeId(int index, int defValue) {
+        // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
+        return defValue;
+    }
+
     /**
      * Retrieve the Drawable for the attribute at <var>index</var>.  This
      * gets the resource ID of the selected attribute, and uses
@@ -854,6 +860,7 @@
      */
     @Override
     public boolean hasValue(int index) {
+        //noinspection SimplifiableIfStatement
         if (index < 0 || index >= mResourceData.length) {
             return false;
         }
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index c9d615c..31d1594 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -16,7 +16,13 @@
 
 package android.content.res;
 
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+import com.android.resources.ResourceType;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.content.res.Resources.NotFoundException;
@@ -25,7 +31,7 @@
 import android.util.TypedValue;
 
 /**
- * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme}
+ * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme}
  *
  * Through the layoutlib_create tool, the original  methods of Theme have been replaced
  * by calls to methods of the same name in this delegate class.
@@ -33,11 +39,28 @@
  */
 public class Resources_Theme_Delegate {
 
+    // Whether to use the Theme.mThemeResId as primary theme.
+    boolean force;
+
+    // ---- delegate manager ----
+
+    private static final DelegateManager<Resources_Theme_Delegate> sManager =
+            new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class);
+
+    public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() {
+        return sManager;
+    }
+
+    // ---- delegate methods. ----
+
     @LayoutlibDelegate
     /*package*/ static TypedArray obtainStyledAttributes(
             Resources thisResources, Theme thisTheme,
             int[] attrs) {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
@@ -45,15 +68,21 @@
             Resources thisResources, Theme thisTheme,
             int resid, int[] attrs)
             throws NotFoundException {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
     /*package*/ static TypedArray obtainStyledAttributes(
             Resources thisResources, Theme thisTheme,
             AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
-        return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(
-                set, attrs, defStyleAttr, defStyleRes);
+        boolean changed = setupResources(thisTheme);
+        TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, attrs,
+                defStyleAttr, defStyleRes);
+        restoreResources(changed);
+        return ta;
     }
 
     @LayoutlibDelegate
@@ -61,7 +90,45 @@
             Resources thisResources, Theme thisTheme,
             int resid, TypedValue outValue,
             boolean resolveRefs) {
-        return RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
+        boolean changed = setupResources(thisTheme);
+        boolean found =  RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
                 resid, outValue, resolveRefs);
+        restoreResources(changed);
+        return found;
+    }
+
+    // ---- private helper methods ----
+
+    private static boolean setupResources(Theme thisTheme) {
+        Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme());
+        StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId());
+        if (style != null) {
+            RenderSessionImpl.getCurrentContext().getRenderResources()
+                    .applyStyle(style, themeDelegate.force);
+            return true;
+        }
+        return false;
+    }
+
+    private static void restoreResources(boolean changed) {
+        if (changed) {
+            RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles();
+        }
+    }
+
+    @Nullable
+    private static StyleResourceValue resolveStyle(int nativeResid) {
+        if (nativeResid == 0) {
+            return null;
+        }
+        BridgeContext context = RenderSessionImpl.getCurrentContext();
+        ResourceReference theme = context.resolveId(nativeResid);
+        if (theme.isFramework()) {
+            return (StyleResourceValue) context.getRenderResources()
+                    .getFrameworkResource(ResourceType.STYLE, theme.getName());
+        } else {
+            return (StyleResourceValue) context.getRenderResources()
+                    .getProjectResource(ResourceType.STYLE, theme.getName());
+        }
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b9294ab..9ee2f60 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.annotations.Nullable;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.rendering.api.IProjectCallback;
 import com.android.ide.common.rendering.api.LayoutLog;
@@ -109,7 +110,7 @@
     // maps for dynamically generated id representing style objects (StyleResourceValue)
     private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
     private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
-    private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
+    private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
 
     // cache for TypedArray generated from IStyleResourceValue object
     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
@@ -315,6 +316,11 @@
             }
         }
 
+        // The base value for R.style is 0x01030000 and the custom style is 0x02030000.
+        // So, if the second byte is 03, it's probably a style.
+        if ((id >> 16 & 0xFF) == 0x03) {
+            return getStyleByDynamicId(id);
+        }
         return null;
     }
 
@@ -455,7 +461,10 @@
 
     @Override
     public final TypedArray obtainStyledAttributes(int[] attrs) {
-        return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs);
+        // No style is specified here, so create the typed array based on the default theme
+        // and the styles already applied to it. A null value of style indicates that the default
+        // theme should be used.
+        return createStyleBasedTypedArray(null, attrs);
     }
 
     @Override
@@ -723,11 +732,13 @@
 
     /**
      * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
-     * values found in the given style.
+     * values found in the given style. If no style is specified, the default theme, along with the
+     * styles applied to it are used.
+     *
      * @see #obtainStyledAttributes(int, int[])
      */
-    private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
-            throws Resources.NotFoundException {
+    private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
+            int[] attrs) throws Resources.NotFoundException {
 
         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
 
@@ -740,8 +751,14 @@
 
             if (attribute != null) {
                 // look for the value in the given style
-                ResourceValue resValue = mRenderResources.findItemInStyle(style,
-                        attribute.getFirst(), attribute.getSecond());
+                ResourceValue resValue;
+                if (style != null) {
+                    resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+                            attribute.getSecond());
+                } else {
+                    resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
+                            attribute.getSecond());
+                }
 
                 if (resValue != null) {
                     // resolve it to make sure there are no references left.
@@ -756,7 +773,6 @@
         return ta;
     }
 
-
     /**
      * The input int[] attrs is a list of attributes. The returns a list of information about
      * each attributes. The information is (name, isFramework)
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 66e67db5..0bb7fc2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -238,4 +238,9 @@
         // TODO Auto-generated method stub
         return null;
     }
+
+    @Override
+    public void setCursorAnchorMonitorMode(IBinder arg0, int arg1) {
+      // TODO Auto-generated method stub
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 3414b3e..b9f2ed9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -51,6 +51,11 @@
     }
 
     @Override
+    public void powerHint(int hintId, int data) {
+        // pass for now.
+    }
+
+    @Override
     public void crash(String arg0) throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/create/.classpath b/tools/layoutlib/create/.classpath
index cd8bb0d..25c3b3e 100644
--- a/tools/layoutlib/create/.classpath
+++ b/tools/layoutlib/create/.classpath
@@ -4,6 +4,6 @@
 	<classpathentry excluding="mock_data/" kind="src" path="tests"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
-	<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_PLAT/prebuilts/tools/common/asm-tools/src-4.0.zip"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/asm/asm-4.0.jar" sourcepath="/ANDROID_PLAT_SRC/prebuilts/misc/common/asm/src.zip"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index ef2b185..6e0a300 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -4,46 +4,45 @@
 - Description -
 ---------------
 
-Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor
-to perform layout.
+Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor to perform
+layout.
 
 
 - Usage -
 ---------
 
- ./layoutlib_create path/to/android.jar destination.jar
+ ./layoutlib_create destination.jar path/to/android1.jar path/to/android2.jar
 
 
 - Design Overview -
 -------------------
 
-Layoutlib_create uses the "android.jar" containing all the Java code used by Android
-as generated by the Android build, right before the classes are converted to a DEX format.
+Layoutlib_create uses a few jars from the framework containing the Java code used by Android as
+generated by the Android build, right before the classes are converted to a DEX format.
 
-The Android JAR can't be used directly in Eclipse:
-- it contains references to native code (which we want to avoid in Eclipse),
-- some classes need to be overridden, for example all the drawing code that is
-  replaced by Java 2D calls in Eclipse.
-- some of the classes that need to be changed are final and/or we need access
-  to their private internal state.
+These jars can't be used directly in Eclipse as:
+- they contains references to native code (which we want to avoid in Eclipse),
+- some classes need to be overridden, for example all the drawing code that is replaced by Java 2D
+  calls in Eclipse.
+- some of the classes that need to be changed are final and/or we need access to their private
+  internal state.
 
 Consequently this tool:
 - parses the input JAR,
 - modifies some of the classes directly using some bytecode manipulation,
 - filters some packages and removes those we don't want in the output JAR,
 - injects some new classes,
-- generates a modified JAR file that is suitable for the Android plugin
-  for Eclipse to perform rendering.
+- generates a modified JAR file that is suitable for the Android plugin for Eclipse to perform
+  rendering.
 
 The ASM library is used to do the bytecode modification using its visitor pattern API.
 
-The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the
-configuration is done in the main() method and the CreateInfo structure is expected to
-change with the Android platform as new classes are added, changed or removed.
+The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the configuration
+is done in the main() method and the CreateInfo structure is expected to change with the Android
+platform as new classes are added, changed or removed.
 
-The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the
-platform, that provides all the necessary missing implementation for rendering graphics
-in Eclipse.
+The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the platform, that
+provides all the necessary missing implementation for rendering graphics in Eclipse.
 
 
 
@@ -58,97 +57,96 @@
 - Analyzer
 ----------
 
-The goal of the analyzer is to create a graph of all the classes from the input JAR
-with their dependencies and then only keep the ones we want.
+The goal of the analyzer is to create a graph of all the classes from the input JAR with their
+dependencies and then only keep the ones we want.
 
-To do that, the analyzer is created with a list of base classes to keep -- everything
-that derives from these is kept. Currently the one such class is android.view.View:
-since we want to render layouts, anything that is sort of a view needs to be kept.
+To do that, the analyzer is created with a list of base classes to keep -- everything that derives
+from these is kept. Currently the one such class is android.view.View: since we want to render
+layouts, anything that is sort of a view needs to be kept.
 
-The analyzer is also given a list of class names to keep in the output.
-This is done using shell-like glob patterns that filter on the fully-qualified
-class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does,
-and "." and "$" are interpreted as-is).
-In practice we almost but not quite request the inclusion of full packages.
+The analyzer is also given a list of class names to keep in the output. This is done using
+shell-like glob patterns that filter on the fully-qualified class names, for example "android.*.R**"
+("*" does not matches dots whilst "**" does, and "." and "$" are interpreted as-is). In practice we
+almost but not quite request the inclusion of full packages.
 
-The analyzer is also given a list of classes to exclude. A fake implementation of these
-classes is injected by the Generator.
+The analyzer is also given a list of classes to exclude. A fake implementation of these classes is
+injected by the Generator.
 
-With this information, the analyzer parses the input zip to find all the classes.
-All classes deriving from the requested bases classes are kept.
-All classes which name matched the glob pattern are kept.
-The analysis then finds all the dependencies of the classes that are to be kept
-using an ASM visitor on the class, the field types, the method types and annotations types.
-Classes that belong to the current JRE are excluded.
+With this information, the analyzer parses the input zip to find all the classes. All classes
+deriving from the requested bases classes are kept. All classes whose name match the glob pattern
+are kept. The analysis then finds all the dependencies of the classes that are to be kept using an
+ASM visitor on the class, the field types, the method types and annotations types. Classes that
+belong to the current JRE are excluded.
 
-The output of the analyzer is a set of ASM ClassReader instances which are then
-fed to the generator.
+The output of the analyzer is a set of ASM ClassReader instances which are then fed to the
+generator.
 
 
 - Generator
 -----------
 
-The generator is constructed from a CreateInfo struct that acts as a config file
-and lists:
-- the classes to inject in the output JAR -- these classes are directly implemented
-  in layoutlib_create and will be used to interface with the renderer in Eclipse.
+The generator is constructed from a CreateInfo struct that acts as a config file and lists:
+- the classes to inject in the output JAR -- these classes are directly implemented in
+  layoutlib_create and will be used to interface with the renderer in Eclipse.
 - specific methods to override (see method stubs details below).
 - specific methods for which to delegate calls.
 - specific methods to remove based on their return type.
 - specific classes to rename.
 - specific classes to refactor.
 
-Each of these are specific strategies we use to be able to modify the Android code
-to fit within the Eclipse renderer. These strategies are explained beow.
+Each of these are specific strategies we use to be able to modify the Android code to fit within the
+Eclipse renderer. These strategies are explained beow.
 
-The core method of the generator is transform(): it takes an input ASM ClassReader
-and modifies it to produce a byte array suitable for the final JAR file.
+The core method of the generator is transform(): it takes an input ASM ClassReader and modifies it
+to produce a byte array suitable for the final JAR file.
 
 The first step of the transformation is to implement the method delegates.
 
-The TransformClassAdapter is then used to process the potentially renamed class.
-All protected or private classes are market as public.
-All classes are made non-final.
-Interfaces are left as-is.
+The TransformClassAdapter is then used to process the potentially renamed class.  All protected or
+private classes are market as public. All classes are made non-final. Interfaces are left as-is.
 
-If a method has a return type that must be erased, the whole method is skipped.
-Methods are also changed from protected/private to public.
-The code of the methods is then kept as-is, except for native methods which are
-replaced by a stub. Methods that are to be overridden are also replaced by a stub.
+If a method has a return type that must be erased, the whole method is skipped.  Methods are also
+changed from protected/private to public. The code of the methods is then kept as-is, except for
+native methods which are replaced by a stub. Methods that are to be overridden are also replaced by
+a stub.
 
 Finally fields are also visited and changed from protected/private to public.
 
-The next step of the transformation is changing the name of the class in case
-we requested the class to be renamed. This uses the RenameClassAdapter to also rename
-all inner classes and references in methods and types. Note that other classes are
-not transformed and keep referencing the original name.
+The next step of the transformation is changing the name of the class in case we requested the class
+to be renamed. This uses the RenameClassAdapter to also rename all inner classes and references in
+methods and types. Note that other classes are not transformed and keep referencing the original
+name.
 
-The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but
-updates the references in all classes. This is used to update the references of classes
-in the java package that were added in the Dalvik VM but are not a part of the standard
-JVM. The existing classes are modified to update all references to these non-standard
-classes. An alternate implementation of these (com.android.tools.layoutlib.java.*) is
-injected.
+The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but updates the
+references in all classes. This is used to update the references of classes in the java package that
+were added in the Dalvik VM but are not a part of the standard JVM. The existing classes are
+modified to update all references to these non-standard classes. An alternate implementation of
+these (com.android.tools.layoutlib.java.*) is injected.
 
-The ClassAdapters are chained together to achieve the desired output. (Look at section
-2.2.7 Transformation chains in the asm user guide, link in the References.) The order of
-execution of these is:
+RenameClassAdapter and RefactorClassAdapter both inherit from AbstractClassAdapter which changes the
+class version (version of the JDK used to compile the class) to 50 (corresponding to Java 6), if the
+class was originally compiled with Java 7 (version 51). This is because we don't currently generate
+the StackMapTable correctly and Java 7 VM enforces that classes with version greater than 51 have
+valid StackMapTable. As a side benefit of this, we can continue to support Java 6 because Java 7 on
+Mac has horrible font rendering support.
+
+The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7
+Transformation chains in the asm user guide, link in the References.) The order of execution of
+these is:
 ClassReader -> [DelegateClassAdapter] -> TransformClassAdapter -> [RenameClassAdapter] ->
 RefactorClassAdapter -> ClassWriter
 
 - Method stubs
 --------------
 
-As indicated above, all native and overridden methods are replaced by a stub.
-We don't have the code to replace with in layoutlib_create.
-Instead the StubMethodAdapter replaces the code of the method by a call to
-OverrideMethod.invokeX(). When using the final JAR, the bridge can register
+As indicated above, all native and overridden methods are replaced by a stub.  We don't have the
+code to replace with in layoutlib_create. Instead the StubMethodAdapter replaces the code of the
+method by a call to OverrideMethod.invokeX(). When using the final JAR, the bridge can register
 listeners from these overridden method calls based on the method signatures.
 
-The listeners are currently pretty basic: we only pass the signature of the
-method being called, its caller object and a flag indicating whether the
-method was native. We do not currently provide the parameters. The listener
-can however specify the return value of the overridden method.
+The listeners are currently pretty basic: we only pass the signature of the method being called, its
+caller object and a flag indicating whether the method was native. We do not currently provide the
+parameters. The listener can however specify the return value of the overridden method.
 
 This strategy is now obsolete and replaced by the method delegates.
 
@@ -156,97 +154,89 @@
 - Strategies
 ------------
 
-We currently have 6 strategies to deal with overriding the rendering code
-and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
-by the bridge (which runs in Eclipse) and the generator.
+We currently have 6 strategies to deal with overriding the rendering code and make it run in
+Eclipse. Most of these strategies are implemented hand-in-hand by the bridge (which runs in Eclipse)
+and the generator.
 
 
 1- Class Injection
 
 This is the easiest: we currently inject the following classes:
-- OverrideMethod and its associated MethodListener and MethodAdapter are used
-  to intercept calls to some specific methods that are stubbed out and change
-  their return value.
-- CreateInfo class, which configured the generator. Not used yet, but could
-  in theory help us track what the generator changed.
-- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new
-  classes are injected. The implementation for these classes has been taken from
-  Android's libcore (platform/libcore/luni/src/main/java/java/...).
-- Charsets, IntegralToString and UnsafeByteSequence are not part of the standard JAVA VM.
-  They are added to the Dalvik VM for performance reasons. An implementation that is very
-  close to the original (which is at platform/libcore/luni/src/main/java/...) is injected.
-  Since these classees were in part of the java package, where we can't inject classes,
-  all references to these have been updated (See strategy 4- Refactoring Classes).
+- OverrideMethod and its associated MethodListener and MethodAdapter are used to intercept calls to
+  some specific methods that are stubbed out and change their return value.
+- CreateInfo class, which configured the generator. Not used yet, but could in theory help us track
+  what the generator changed.
+- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new classes are
+  injected. The implementation for these classes has been taken from Android's libcore
+  (platform/libcore/luni/src/main/java/java/...).
+- Charsets, IntegralToString and UnsafeByteSequence are not part of the standard JAVA VM. They are
+  added to the Dalvik VM for performance reasons. An implementation that is very close to the
+  original (which is at platform/libcore/luni/src/main/java/...) is injected. Since these classees
+  were in part of the java package, where we can't inject classes, all references to these have been
+  updated (See strategy 4- Refactoring Classes).
 
 
 2- Overriding methods
 
-As explained earlier, the creator doesn't have any replacement code for
-methods to override. Instead it removes the original code and replaces it
-by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
-a listener on the method signature and can provide an implementation.
+As explained earlier, the creator doesn't have any replacement code for methods to override. Instead
+it removes the original code and replaces it by a call to a specific OveriddeMethod.invokeX(). The
+bridge then registers a listener on the method signature and can provide an implementation.
 
-This strategy is now obsolete and replaced by the method delegates.
-See strategy 5 below.
+This strategy is now obsolete and replaced by the method delegates (See strategy 6- Method
+Delegates).
 
 
 3- Renaming classes
 
-This simply changes the name of a class in its definition, as well as all its
-references in internal inner classes and methods.
-Calls from other classes are not modified -- they keep referencing the original
-class name. This allows the bridge to literally replace an implementation.
+This simply changes the name of a class in its definition, as well as all its references in internal
+inner classes and methods. Calls from other classes are not modified -- they keep referencing the
+original class name. This allows the bridge to literally replace an implementation.
 
-An example will make this easier: android.graphics.Paint is the main drawing
-class that we need to replace. To do so, the generator renames Paint to _original_Paint.
-Later the bridge provides its own replacement version of Paint which will be used
-by the rest of the Android stack. The replacement version of Paint can still use
-(either by inheritance or delegation) all the original non-native code of _original_Paint
-if it so desires.
+An example will make this easier: android.graphics.Paint is the main drawing class that we need to
+replace. To do so, the generator renames Paint to _original_Paint. Later the bridge provides its own
+replacement version of Paint which will be used by the rest of the Android stack. The replacement
+version of Paint can still use (either by inheritance or delegation) all the original non-native
+code of _original_Paint if it so desires.
 
-Some of the Android classes are basically wrappers over native objects and since
-we don't have the native code in Eclipse, we need to provide a full alternate
-implementation. Sub-classing doesn't work as some native methods are static and
-we don't control object creation.
+Some of the Android classes are basically wrappers over native objects and since we don't have the
+native code in Eclipse, we need to provide a full alternate implementation. Sub-classing doesn't
+work as some native methods are static and we don't control object creation.
 
 This won't rename/replace the inner static methods of a given class.
 
 
 4- Refactoring classes
 
-This is very similar to the Renaming classes except that it also updates the reference in
-all classes. This is done for classes which are added to the Dalvik VM for performance
-reasons but are not present in the Standard Java VM. An implementation for these classes
-is also injected.
+This is very similar to the Renaming classes except that it also updates the reference in all
+classes. This is done for classes which are added to the Dalvik VM for performance reasons but are
+not present in the Standard Java VM. An implementation for these classes is also injected.
 
 
 5- Method erasure based on return type
 
-This is mostly an implementation detail of the bridge: in the Paint class
-mentioned above, some inner static classes are used to pass around
-attributes (e.g. FontMetrics, or the Style enum) and all the original implementation
-is native.
+This is mostly an implementation detail of the bridge: in the Paint class mentioned above, some
+inner static classes are used to pass around attributes (e.g. FontMetrics, or the Style enum) and
+all the original implementation is native.
 
-In this case we have a strategy that tells the generator that anything returning, for
-example, the inner class Paint$Style in the Paint class should be discarded and the
-bridge will provide its own implementation.
+In this case we have a strategy that tells the generator that anything returning, for example, the
+inner class Paint$Style in the Paint class should be discarded and the bridge will provide its own
+implementation.
 
 
 6- Method Delegates
 
-This strategy is used to override method implementations.
-Given a method SomeClass.MethodName(), 1 or 2 methods are generated:
-a- A copy of the original method named SomeClass.MethodName_Original().
-   The content is the original method as-is from the reader.
-   This step is omitted if the method is native, since it has no Java implementation.
-b- A brand new implementation of SomeClass.MethodName() which calls to a
-   non-existing static method named SomeClass_Delegate.MethodName().
-   The implementation of this 'delegate' method is done in layoutlib_brigde.
+This strategy is used to override method implementations. Given a method SomeClass.MethodName(), 1
+or 2 methods are generated:
+a- A copy of the original method named SomeClass.MethodName_Original(). The content is the original
+method as-is from the reader. This step is omitted if the method is native, since it has no Java
+implementation.
+b- A brand new implementation of SomeClass.MethodName() which calls to a non-existing static method
+named SomeClass_Delegate.MethodName(). The implementation of this 'delegate' method is done in
+layoutlib_brigde.
 
-The delegate method is a static method.
-If the original method is non-static, the delegate method receives the original 'this'
-as its first argument. If the original method is an inner non-static method, it also
-receives the inner 'this' as the second argument.
+The delegate method is a static method. If the original method is non-static, the delegate method
+receives the original 'this' as its first argument. If the original method is an inner non-static
+method, it also receives the inner 'this' as the second argument.
 
 
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
index b2caa25..323a791 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
@@ -177,6 +177,17 @@
             }
         }
 
+        /* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0.
+         * However, the check is disabled if the class version number is 50.0 or less. Generation
+         * of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround,
+         * we rewrite the version number of the class to be 50.0
+         *
+         * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236
+         */
+        if (version > 50) {
+            version = 50;
+        }
+
         super.visit(version, access, name, signature, superName, interfaces);
     }
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index 9a31705..3e75c9e 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -632,8 +632,8 @@
             // field instruction
             @Override
             public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-                // name is the field's name.
-                considerName(name);
+                // owner is the class that declares the field.
+                considerName(owner);
                 // desc is the field's descriptor (see Type).
                 considerDesc(desc);
             }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4236038..e0c05de 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -126,6 +126,9 @@
         "android.content.res.Resources$Theme#obtainStyledAttributes",
         "android.content.res.Resources$Theme#resolveAttribute",
         "android.content.res.Resources#localeToLanguageTag",
+        "android.content.res.AssetManager#newTheme",
+        "android.content.res.AssetManager#deleteTheme",
+        "android.content.res.AssetManager#applyThemeStyle",
         "android.content.res.TypedArray#getValueAt",
         "android.graphics.BitmapFactory#finishDecode",
         "android.os.Handler#sendMessageAtTime",
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
index c988c70..2016c0e 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
@@ -527,7 +527,8 @@
             // field instruction
             @Override
             public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-                // name is the field's name.
+                // owner is the class that declares the field.
+                considerName(owner);
                 // desc is the field's descriptor (see Type).
                 considerDesc(desc);
             }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
index 7ec0d38..78e2c48 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
@@ -83,6 +83,7 @@
                 "mock_android.dummy.InnerTest$MyStaticInnerClass",
                 "mock_android.dummy.InnerTest$NotStaticInner1",
                 "mock_android.dummy.InnerTest$NotStaticInner2",
+                "mock_android.util.EmptyArray",
                 "mock_android.view.View",
                 "mock_android.view.ViewGroup",
                 "mock_android.view.ViewGroup$LayoutParams",
@@ -217,15 +218,16 @@
         TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>();
         TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>();
 
-        ClassReader cr = mAa.findClass("mock_android.widget.TableLayout", zipClasses, keep);
+        ClassReader cr = mAa.findClass("mock_android.widget.LinearLayout", zipClasses, keep);
         DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps);
 
         // get first level dependencies
         cr.accept(visitor, 0 /* flags */);
 
         assertArrayEquals(new String[] {
+                "mock_android.util.EmptyArray",
                 "mock_android.view.ViewGroup",
-                "mock_android.widget.TableLayout$LayoutParams",
+                "mock_android.widget.LinearLayout$LayoutParams",
             },
             out_deps.keySet().toArray());
 
@@ -255,7 +257,7 @@
 
         assertArrayEquals(new String[] { }, out_deps.keySet().toArray());
         assertArrayEquals(new String[] {
-                "mock_android.widget.TableLayout",
+                "mock_android.widget.LinearLayout",
         }, keep.keySet().toArray());
     }
 }
diff --git a/tools/layoutlib/create/tests/data/mock_android.jar b/tools/layoutlib/create/tests/data/mock_android.jar
index 8dd0481..c6ca3c4 100644
--- a/tools/layoutlib/create/tests/data/mock_android.jar
+++ b/tools/layoutlib/create/tests/data/mock_android.jar
Binary files differ
diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java
new file mode 100644
index 0000000..aaeebf6
--- /dev/null
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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 mock_android.util;
+
+import java.lang.JavaClass;
+
+public class EmptyArray {
+
+        public static final Object[] OBJECT = new Object[0];
+}
diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
index 3870a63..af56c4b 100644
--- a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
@@ -16,11 +16,13 @@
 
 package mock_android.widget;
 
+import mock_android.util.EmptyArray;
 import mock_android.view.ViewGroup;
 
 public class LinearLayout extends ViewGroup {
 
-    public class LayoutParams extends mock_android.view.ViewGroup.LayoutParams {
+    Object[] mObjects = EmptyArray.OBJECT;
+    public class LayoutParams extends MarginLayoutParams {
 
     }
 
diff --git a/wifi/java/android/net/wifi/BatchedScanSettings.java b/wifi/java/android/net/wifi/BatchedScanSettings.java
index f7ebc17..54801ad 100644
--- a/wifi/java/android/net/wifi/BatchedScanSettings.java
+++ b/wifi/java/android/net/wifi/BatchedScanSettings.java
@@ -34,17 +34,17 @@
     /** Used to indicate no preference for an int value */
     public final static int UNSPECIFIED = Integer.MAX_VALUE;
 
-    // TODO - make MIN/mAX dynamic and gservices adjustable.
+    // TODO - make MIN/mAX as standard for wifi batch capability requirement.
     public final static int MIN_SCANS_PER_BATCH = 2;
-    public final static int MAX_SCANS_PER_BATCH = 255;
+    public final static int MAX_SCANS_PER_BATCH = 20;
     public final static int DEFAULT_SCANS_PER_BATCH = MAX_SCANS_PER_BATCH;
 
     public final static int MIN_AP_PER_SCAN = 2;
-    public final static int MAX_AP_PER_SCAN = 255;
+    public final static int MAX_AP_PER_SCAN = 16;
     public final static int DEFAULT_AP_PER_SCAN = 16;
 
-    public final static int MIN_INTERVAL_SEC = 0;
-    public final static int MAX_INTERVAL_SEC = 3600;
+    public final static int MIN_INTERVAL_SEC = 10;
+    public final static int MAX_INTERVAL_SEC = 500;
     public final static int DEFAULT_INTERVAL_SEC = 30;
 
     public final static int MIN_AP_FOR_DISTANCE = 0;
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 84e933d..0535fe0 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -128,5 +128,7 @@
     boolean isBatchedScanSupported();
 
     void pollBatchedScan();
+
+    String getWpsNfcConfigurationToken(int netId);
 }
 
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 12729d2..d7ecaff 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -40,8 +40,7 @@
      */
     public String capabilities;
     /**
-     * The detected signal level in dBm. At least those are the units used by
-     * the TI driver.
+     * The detected signal level in dBm.
      */
     public int level;
     /**
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 4a6821c..f44cb0a 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -157,9 +157,8 @@
 
     /**
      * Returns the received signal strength indicator of the current 802.11
-     * network.
-     * <p><strong>This is not normalized, but should be!</strong></p>
-     * @return the RSSI, in the range ??? to ???
+     * network, in dBm.
+     * @return the RSSI, in the range -110 to 10
      */
     public int getRssi() {
         return mRssi;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0862b7e..5af1e4e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -930,6 +930,21 @@
     }
 
     /**
+     * Creates a configuration token describing the network referenced by {@code netId}
+     * of MIME type application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
+     *
+     * @return hex-string encoded configuration token
+     * @hide
+     */
+    public String getWpsNfcConfigurationToken(int netId) {
+        try {
+            return mService.getWpsNfcConfigurationToken(netId);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Return dynamic information about the current Wi-Fi connection, if any is active.
      * @return the Wi-Fi information, contained in {@link WifiInfo}.
      */
diff --git a/core/java/android/view/DisplayList.java b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
similarity index 64%
copy from core/java/android/view/DisplayList.java
copy to wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
index ed52803..2b1601b 100644
--- a/core/java/android/view/DisplayList.java
+++ b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
+/**
+ * Copyright (c) 2014, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.net.wifi.hotspot;
 
-/** TODO: Remove once frameworks/webview is updated
- *  @hide
+/**
+ * Interface that allows controlling and querying Hotspot connectivity.
+ *
+ * {@hide}
  */
-public class DisplayList {
-    /** @hide */
-    public static final int STATUS_DONE = 0x0;
+interface IWifiHotspotManager
+{
+    void test();
 }
+
diff --git a/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
new file mode 100644
index 0000000..ac15017
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
@@ -0,0 +1,48 @@
+/*
+ * 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.wifi.hotspot;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * TODO: doc
+ */
+public class WifiHotspotManager {
+
+    private static final String TAG = "WifiHotspotManager";
+
+    private Context mContext;
+    IWifiHotspotManager mService;
+
+    public WifiHotspotManager(Context context, IWifiHotspotManager service) {
+        mContext = context;
+        mService = service;
+    }
+
+    public void test() {
+        try{
+            Log.d(TAG, "test()");
+            mService.test();
+        }
+        catch (RemoteException e) {
+            Log.e(TAG, "test() exception");
+            e.printStackTrace();
+        }
+    }
+}