Merge "Remove lxml dependency." into lmp-preview-dev
diff --git a/Android.mk b/Android.mk
index 7c01ed9..52459ae 100644
--- a/Android.mk
+++ b/Android.mk
@@ -77,9 +77,9 @@
 	core/java/android/app/ISearchManagerCallback.aidl \
 	core/java/android/app/IServiceConnection.aidl \
 	core/java/android/app/IStopUserCallback.aidl \
-	core/java/android/app/task/ITaskCallback.aidl \
-	core/java/android/app/task/ITaskManager.aidl \
-	core/java/android/app/task/ITaskService.aidl \
+	core/java/android/app/job/IJobCallback.aidl \
+	core/java/android/app/job/IJobScheduler.aidl \
+	core/java/android/app/job/IJobService.aidl \
 	core/java/android/app/IThumbnailRetriever.aidl \
 	core/java/android/app/ITransientNotification.aidl \
 	core/java/android/app/IUiAutomationConnection.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f3bb9b6..5b027b3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -197,3 +197,6 @@
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/app/task)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app/task)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/app/TaskManager)
diff --git a/api/current.txt b/api/current.txt
index 7d8e796..d6831c8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -245,7 +245,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 = 16843828; // 0x1010434
+    field public static final int actionBarTheme = 16843827; // 0x1010433
     field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
     field public static final int actionButtonStyle = 16843480; // 0x10102d8
     field public static final int actionDropDownStyle = 16843479; // 0x10102d7
@@ -262,7 +262,7 @@
     field public static final int actionModeSplitBackground = 16843677; // 0x101039d
     field public static final int actionModeStyle = 16843668; // 0x1010394
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
-    field public static final int actionOverflowMenuStyle = 16843847; // 0x1010447
+    field public static final int actionOverflowMenuStyle = 16843846; // 0x1010446
     field public static final int actionProviderClass = 16843657; // 0x1010389
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -308,7 +308,7 @@
     field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
-    field public static final int autoRemoveFromRecents = 16843850; // 0x101044a
+    field public static final int autoRemoveFromRecents = 16843849; // 0x1010449
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -381,22 +381,22 @@
     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 colorAccent = 16843832; // 0x1010438
+    field public static final int colorAccent = 16843831; // 0x1010437
     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 = 16843822; // 0x101042e
-    field public static final int colorControlActivated = 16843821; // 0x101042d
-    field public static final int colorControlHighlight = 16843823; // 0x101042f
-    field public static final int colorControlNormal = 16843820; // 0x101042c
+    field public static final int colorButtonNormal = 16843821; // 0x101042d
+    field public static final int colorControlActivated = 16843820; // 0x101042c
+    field public static final int colorControlHighlight = 16843822; // 0x101042e
+    field public static final int colorControlNormal = 16843819; // 0x101042b
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
-    field public static final int colorPrimary = 16843830; // 0x1010436
-    field public static final int colorPrimaryDark = 16843831; // 0x1010437
+    field public static final int colorPrimary = 16843829; // 0x1010435
+    field public static final int colorPrimaryDark = 16843830; // 0x1010436
     field public static final int columnCount = 16843639; // 0x1010377
     field public static final int columnDelay = 16843215; // 0x10101cf
     field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -411,10 +411,10 @@
     field public static final int content = 16843355; // 0x101025b
     field public static final int contentAuthority = 16843408; // 0x1010290
     field public static final int contentDescription = 16843379; // 0x1010273
-    field public static final int contentInsetEnd = 16843863; // 0x1010457
-    field public static final int contentInsetLeft = 16843864; // 0x1010458
-    field public static final int contentInsetRight = 16843865; // 0x1010459
-    field public static final int contentInsetStart = 16843862; // 0x1010456
+    field public static final int contentInsetEnd = 16843862; // 0x1010456
+    field public static final int contentInsetLeft = 16843863; // 0x1010457
+    field public static final int contentInsetRight = 16843864; // 0x1010458
+    field public static final int contentInsetStart = 16843861; // 0x1010455
     field public static final int controlX1 = 16843798; // 0x1010416
     field public static final int controlX2 = 16843800; // 0x1010418
     field public static final int controlY1 = 16843799; // 0x1010417
@@ -459,7 +459,7 @@
     field public static final int dividerHorizontal = 16843564; // 0x101032c
     field public static final int dividerPadding = 16843562; // 0x101032a
     field public static final int dividerVertical = 16843530; // 0x101030a
-    field public static final int documentLaunchMode = 16843848; // 0x1010448
+    field public static final int documentLaunchMode = 16843847; // 0x1010447
     field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
     field public static final int drawable = 16843161; // 0x1010199
     field public static final int drawableBottom = 16843118; // 0x101016e
@@ -488,8 +488,8 @@
     field public static final int editTextStyle = 16842862; // 0x101006e
     field public static final deprecated int editable = 16843115; // 0x101016b
     field public static final int editorExtras = 16843300; // 0x1010224
-    field public static final int elegantTextHeight = 16843868; // 0x101045c
-    field public static final int elevation = 16843843; // 0x1010443
+    field public static final int elegantTextHeight = 16843867; // 0x101045b
+    field public static final int elevation = 16843842; // 0x1010442
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
@@ -499,10 +499,10 @@
     field public static final int entries = 16842930; // 0x10100b2
     field public static final int entryValues = 16843256; // 0x10101f8
     field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
-    field public static final int excludeClass = 16843845; // 0x1010445
+    field public static final int excludeClass = 16843844; // 0x1010444
     field public static final int excludeFromRecents = 16842775; // 0x1010017
-    field public static final int excludeId = 16843844; // 0x1010444
-    field public static final int excludeViewName = 16843857; // 0x1010451
+    field public static final int excludeId = 16843843; // 0x1010443
+    field public static final int excludeViewName = 16843856; // 0x1010450
     field public static final int exitFadeDuration = 16843533; // 0x101030d
     field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
     field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -564,7 +564,7 @@
     field public static final int freezesText = 16843116; // 0x101016c
     field public static final int fromAlpha = 16843210; // 0x10101ca
     field public static final int fromDegrees = 16843187; // 0x10101b3
-    field public static final int fromId = 16843853; // 0x101044d
+    field public static final int fromId = 16843852; // 0x101044c
     field public static final int fromScene = 16843741; // 0x10103dd
     field public static final int fromXDelta = 16843206; // 0x10101c6
     field public static final int fromXScale = 16843202; // 0x10101c2
@@ -597,7 +597,7 @@
     field public static final int headerBackground = 16843055; // 0x101012f
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int height = 16843093; // 0x1010155
-    field public static final int hideOnContentScroll = 16843846; // 0x1010446
+    field public static final int hideOnContentScroll = 16843845; // 0x1010445
     field public static final int hint = 16843088; // 0x1010150
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
@@ -792,7 +792,7 @@
     field public static final int manageSpaceActivity = 16842756; // 0x1010004
     field public static final int mapViewStyle = 16842890; // 0x101008a
     field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
-    field public static final int matchOrder = 16843858; // 0x1010452
+    field public static final int matchOrder = 16843857; // 0x1010451
     field public static final int max = 16843062; // 0x1010136
     field public static final int maxDate = 16843584; // 0x1010340
     field public static final int maxEms = 16843095; // 0x1010157
@@ -801,7 +801,7 @@
     field public static final int maxLength = 16843104; // 0x1010160
     field public static final int maxLevel = 16843186; // 0x10101b2
     field public static final int maxLines = 16843091; // 0x1010153
-    field public static final int maxRecents = 16843849; // 0x1010449
+    field public static final int maxRecents = 16843848; // 0x1010448
     field public static final int maxRows = 16843059; // 0x1010133
     field public static final int maxSdkVersion = 16843377; // 0x1010271
     field public static final int maxWidth = 16843039; // 0x101011f
@@ -826,10 +826,10 @@
     field public static final int moreIcon = 16843061; // 0x1010135
     field public static final int multiprocess = 16842771; // 0x1010013
     field public static final int name = 16842755; // 0x1010003
-    field public static final int navigationBarColor = 16843861; // 0x1010455
+    field public static final int navigationBarColor = 16843860; // 0x1010454
     field public static final int navigationMode = 16843471; // 0x10102cf
     field public static final int negativeButtonText = 16843254; // 0x10101f6
-    field public static final int nestedScrollingEnabled = 16843833; // 0x1010439
+    field public static final int nestedScrollingEnabled = 16843832; // 0x1010438
     field public static final int nextFocusDown = 16842980; // 0x10100e4
     field public static final int nextFocusForward = 16843580; // 0x101033c
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
@@ -860,7 +860,7 @@
     field public static final int paddingBottom = 16842969; // 0x10100d9
     field public static final int paddingEnd = 16843700; // 0x10103b4
     field public static final int paddingLeft = 16842966; // 0x10100d6
-    field public static final int paddingMode = 16843866; // 0x101045a
+    field public static final int paddingMode = 16843865; // 0x1010459
     field public static final int paddingRight = 16842968; // 0x10100d8
     field public static final int paddingStart = 16843699; // 0x10103b3
     field public static final int paddingTop = 16842967; // 0x10100d7
@@ -879,11 +879,10 @@
     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 = 16843824; // 0x1010430
+    field public static final int persistable = 16843823; // 0x101042f
     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 = 16843819; // 0x101042b
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -956,7 +955,7 @@
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
-    field public static final int reversible = 16843854; // 0x101044e
+    field public static final int reversible = 16843853; // 0x101044d
     field public static final int right = 16843183; // 0x10101af
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
@@ -1010,10 +1009,10 @@
     field public static final int selectAllOnFocus = 16843102; // 0x101015e
     field public static final int selectable = 16843238; // 0x10101e6
     field public static final int selectableItemBackground = 16843534; // 0x101030e
-    field public static final int selectableItemBackgroundBorderless = 16843867; // 0x101045b
+    field public static final int selectableItemBackgroundBorderless = 16843866; // 0x101045a
     field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
     field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
-    field public static final int sessionService = 16843840; // 0x1010440
+    field public static final int sessionService = 16843839; // 0x101043f
     field public static final int settingsActivity = 16843301; // 0x1010225
     field public static final int setupActivity = 16843766; // 0x10103f6
     field public static final int shadowColor = 16843105; // 0x1010161
@@ -1035,7 +1034,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 = 16843827; // 0x1010433
+    field public static final int slideEdge = 16843826; // 0x1010432
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -1047,19 +1046,19 @@
     field public static final int spinnerStyle = 16842881; // 0x1010081
     field public static final int spinnersShown = 16843595; // 0x101034b
     field public static final int splitMotionEvents = 16843503; // 0x10102ef
-    field public static final int splitTrack = 16843855; // 0x101044f
+    field public static final int splitTrack = 16843854; // 0x101044e
     field public static final int src = 16843033; // 0x1010119
     field public static final int ssp = 16843747; // 0x10103e3
     field public static final int sspPattern = 16843749; // 0x10103e5
     field public static final int sspPrefix = 16843748; // 0x10103e4
     field public static final int stackFromBottom = 16843005; // 0x10100fd
-    field public static final int stackViewStyle = 16843841; // 0x1010441
+    field public static final int stackViewStyle = 16843840; // 0x1010440
     field public static final int starStyle = 16842882; // 0x1010082
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
     field public static final deprecated int startYear = 16843132; // 0x101017c
-    field public static final int stateListAnimator = 16843851; // 0x101044b
+    field public static final int stateListAnimator = 16843850; // 0x101044a
     field public static final int stateNotNeeded = 16842774; // 0x1010016
     field public static final int state_above_anchor = 16842922; // 0x10100aa
     field public static final int state_accelerated = 16843547; // 0x101031b
@@ -1084,7 +1083,7 @@
     field public static final int state_single = 16842915; // 0x10100a3
     field public static final int state_window_focused = 16842909; // 0x101009d
     field public static final int staticWallpaperPreview = 16843569; // 0x1010331
-    field public static final int statusBarColor = 16843860; // 0x1010454
+    field public static final int statusBarColor = 16843859; // 0x1010453
     field public static final int stepSize = 16843078; // 0x1010146
     field public static final int stopWithTask = 16843626; // 0x101036a
     field public static final int streamType = 16843273; // 0x1010209
@@ -1096,7 +1095,7 @@
     field public static final int strokeOpacity = 16843810; // 0x1010422
     field public static final int strokeWidth = 16843811; // 0x1010423
     field public static final int subtitle = 16843473; // 0x10102d1
-    field public static final int subtitleTextAppearance = 16843826; // 0x1010432
+    field public static final int subtitleTextAppearance = 16843825; // 0x1010431
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int subtypeExtraValue = 16843674; // 0x101039a
     field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1113,7 +1112,7 @@
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
     field public static final int switchPreferenceStyle = 16843629; // 0x101036d
-    field public static final int switchStyle = 16843842; // 0x1010442
+    field public static final int switchStyle = 16843841; // 0x1010441
     field public static final int switchTextAppearance = 16843630; // 0x101036e
     field public static final int switchTextOff = 16843628; // 0x101036c
     field public static final int switchTextOn = 16843627; // 0x101036b
@@ -1129,7 +1128,7 @@
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
-    field public static final int targetViewName = 16843856; // 0x1010450
+    field public static final int targetViewName = 16843855; // 0x101044f
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
     field public static final int taskCloseExitAnimation = 16842943; // 0x10100bf
@@ -1151,7 +1150,7 @@
     field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
     field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
     field public static final int textAppearanceListItem = 16843678; // 0x101039e
-    field public static final int textAppearanceListItemSecondary = 16843829; // 0x1010435
+    field public static final int textAppearanceListItemSecondary = 16843828; // 0x1010434
     field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
     field public static final int textAppearanceMedium = 16842817; // 0x1010041
     field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
@@ -1215,11 +1214,11 @@
     field public static final int tintMode = 16843797; // 0x1010415
     field public static final int title = 16843233; // 0x10101e1
     field public static final int titleCondensed = 16843234; // 0x10101e2
-    field public static final int titleTextAppearance = 16843825; // 0x1010431
+    field public static final int titleTextAppearance = 16843824; // 0x1010430
     field public static final int titleTextStyle = 16843512; // 0x10102f8
     field public static final int toAlpha = 16843211; // 0x10101cb
     field public static final int toDegrees = 16843188; // 0x10101b4
-    field public static final int toId = 16843852; // 0x101044c
+    field public static final int toId = 16843851; // 0x101044b
     field public static final int toScene = 16843742; // 0x10103de
     field public static final int toXDelta = 16843207; // 0x10101c7
     field public static final int toXScale = 16843203; // 0x10101c3
@@ -1300,8 +1299,8 @@
     field public static final int windowActionBar = 16843469; // 0x10102cd
     field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
     field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
-    field public static final int windowAllowEnterTransitionOverlap = 16843839; // 0x101043f
-    field public static final int windowAllowExitTransitionOverlap = 16843838; // 0x101043e
+    field public static final int windowAllowEnterTransitionOverlap = 16843838; // 0x101043e
+    field public static final int windowAllowExitTransitionOverlap = 16843837; // 0x101043d
     field public static final int windowAnimationStyle = 16842926; // 0x10100ae
     field public static final int windowBackground = 16842836; // 0x1010054
     field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
@@ -1309,12 +1308,12 @@
     field public static final int windowContentTransitionManager = 16843795; // 0x1010413
     field public static final int windowContentTransitions = 16843794; // 0x1010412
     field public static final int windowDisablePreview = 16843298; // 0x1010222
-    field public static final int windowDrawsSystemBarBackgrounds = 16843859; // 0x1010453
+    field public static final int windowDrawsSystemBarBackgrounds = 16843858; // 0x1010452
     field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
     field public static final int windowEnterAnimation = 16842932; // 0x10100b4
-    field public static final int windowEnterTransition = 16843834; // 0x101043a
+    field public static final int windowEnterTransition = 16843833; // 0x1010439
     field public static final int windowExitAnimation = 16842933; // 0x10100b5
-    field public static final int windowExitTransition = 16843835; // 0x101043b
+    field public static final int windowExitTransition = 16843834; // 0x101043a
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
@@ -1325,8 +1324,8 @@
     field public static final int windowNoDisplay = 16843294; // 0x101021e
     field public static final int windowNoTitle = 16842838; // 0x1010056
     field public static final int windowOverscan = 16843727; // 0x10103cf
-    field public static final int windowSharedElementEnterTransition = 16843836; // 0x101043c
-    field public static final int windowSharedElementExitTransition = 16843837; // 0x101043d
+    field public static final int windowSharedElementEnterTransition = 16843835; // 0x101043b
+    field public static final int windowSharedElementExitTransition = 16843836; // 0x101043c
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -1858,52 +1857,52 @@
     field public static final int TextAppearance_Inverse = 16973887; // 0x103003f
     field public static final int TextAppearance_Large = 16973890; // 0x1030042
     field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043
-    field public static final int TextAppearance_Material = 16974348; // 0x103020c
-    field public static final int TextAppearance_Material_Body1 = 16974546; // 0x10302d2
-    field public static final int TextAppearance_Material_Body2 = 16974545; // 0x10302d1
-    field public static final int TextAppearance_Material_Button = 16974549; // 0x10302d5
-    field public static final int TextAppearance_Material_Caption = 16974547; // 0x10302d3
-    field public static final int TextAppearance_Material_DialogWindowTitle = 16974349; // 0x103020d
-    field public static final int TextAppearance_Material_Display1 = 16974541; // 0x10302cd
-    field public static final int TextAppearance_Material_Display2 = 16974540; // 0x10302cc
-    field public static final int TextAppearance_Material_Display3 = 16974539; // 0x10302cb
-    field public static final int TextAppearance_Material_Display4 = 16974538; // 0x10302ca
-    field public static final int TextAppearance_Material_Headline = 16974542; // 0x10302ce
-    field public static final int TextAppearance_Material_Inverse = 16974350; // 0x103020e
-    field public static final int TextAppearance_Material_Large = 16974351; // 0x103020f
-    field public static final int TextAppearance_Material_Large_Inverse = 16974352; // 0x1030210
-    field public static final int TextAppearance_Material_Medium = 16974353; // 0x1030211
-    field public static final int TextAppearance_Material_Medium_Inverse = 16974354; // 0x1030212
-    field public static final int TextAppearance_Material_Menu = 16974548; // 0x10302d4
-    field public static final int TextAppearance_Material_SearchResult_Subtitle = 16974355; // 0x1030213
-    field public static final int TextAppearance_Material_SearchResult_Title = 16974356; // 0x1030214
-    field public static final int TextAppearance_Material_Small = 16974357; // 0x1030215
-    field public static final int TextAppearance_Material_Small_Inverse = 16974358; // 0x1030216
-    field public static final int TextAppearance_Material_Subhead = 16974544; // 0x10302d0
-    field public static final int TextAppearance_Material_Title = 16974543; // 0x10302cf
-    field public static final int TextAppearance_Material_Widget = 16974360; // 0x1030218
-    field public static final int TextAppearance_Material_Widget_ActionBar_Menu = 16974361; // 0x1030219
-    field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle = 16974362; // 0x103021a
-    field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle_Inverse = 16974363; // 0x103021b
-    field public static final int TextAppearance_Material_Widget_ActionBar_Title = 16974364; // 0x103021c
-    field public static final int TextAppearance_Material_Widget_ActionBar_Title_Inverse = 16974365; // 0x103021d
-    field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle = 16974366; // 0x103021e
-    field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle_Inverse = 16974367; // 0x103021f
-    field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974368; // 0x1030220
-    field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974369; // 0x1030221
-    field public static final int TextAppearance_Material_Widget_Button = 16974370; // 0x1030222
-    field public static final int TextAppearance_Material_Widget_DropDownHint = 16974371; // 0x1030223
-    field public static final int TextAppearance_Material_Widget_DropDownItem = 16974372; // 0x1030224
-    field public static final int TextAppearance_Material_Widget_EditText = 16974373; // 0x1030225
-    field public static final int TextAppearance_Material_Widget_IconMenu_Item = 16974374; // 0x1030226
-    field public static final int TextAppearance_Material_Widget_PopupMenu = 16974375; // 0x1030227
-    field public static final int TextAppearance_Material_Widget_PopupMenu_Large = 16974376; // 0x1030228
-    field public static final int TextAppearance_Material_Widget_PopupMenu_Small = 16974377; // 0x1030229
-    field public static final int TextAppearance_Material_Widget_TabWidget = 16974378; // 0x103022a
-    field public static final int TextAppearance_Material_Widget_TextView = 16974379; // 0x103022b
-    field public static final int TextAppearance_Material_Widget_TextView_PopupMenu = 16974380; // 0x103022c
-    field public static final int TextAppearance_Material_Widget_TextView_SpinnerItem = 16974381; // 0x103022d
-    field public static final int TextAppearance_Material_WindowTitle = 16974359; // 0x1030217
+    field public static final int TextAppearance_Material = 16974350; // 0x103020e
+    field public static final int TextAppearance_Material_Body1 = 16974550; // 0x10302d6
+    field public static final int TextAppearance_Material_Body2 = 16974549; // 0x10302d5
+    field public static final int TextAppearance_Material_Button = 16974553; // 0x10302d9
+    field public static final int TextAppearance_Material_Caption = 16974551; // 0x10302d7
+    field public static final int TextAppearance_Material_DialogWindowTitle = 16974351; // 0x103020f
+    field public static final int TextAppearance_Material_Display1 = 16974545; // 0x10302d1
+    field public static final int TextAppearance_Material_Display2 = 16974544; // 0x10302d0
+    field public static final int TextAppearance_Material_Display3 = 16974543; // 0x10302cf
+    field public static final int TextAppearance_Material_Display4 = 16974542; // 0x10302ce
+    field public static final int TextAppearance_Material_Headline = 16974546; // 0x10302d2
+    field public static final int TextAppearance_Material_Inverse = 16974352; // 0x1030210
+    field public static final int TextAppearance_Material_Large = 16974353; // 0x1030211
+    field public static final int TextAppearance_Material_Large_Inverse = 16974354; // 0x1030212
+    field public static final int TextAppearance_Material_Medium = 16974355; // 0x1030213
+    field public static final int TextAppearance_Material_Medium_Inverse = 16974356; // 0x1030214
+    field public static final int TextAppearance_Material_Menu = 16974552; // 0x10302d8
+    field public static final int TextAppearance_Material_SearchResult_Subtitle = 16974357; // 0x1030215
+    field public static final int TextAppearance_Material_SearchResult_Title = 16974358; // 0x1030216
+    field public static final int TextAppearance_Material_Small = 16974359; // 0x1030217
+    field public static final int TextAppearance_Material_Small_Inverse = 16974360; // 0x1030218
+    field public static final int TextAppearance_Material_Subhead = 16974548; // 0x10302d4
+    field public static final int TextAppearance_Material_Title = 16974547; // 0x10302d3
+    field public static final int TextAppearance_Material_Widget = 16974362; // 0x103021a
+    field public static final int TextAppearance_Material_Widget_ActionBar_Menu = 16974363; // 0x103021b
+    field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle = 16974364; // 0x103021c
+    field public static final int TextAppearance_Material_Widget_ActionBar_Subtitle_Inverse = 16974365; // 0x103021d
+    field public static final int TextAppearance_Material_Widget_ActionBar_Title = 16974366; // 0x103021e
+    field public static final int TextAppearance_Material_Widget_ActionBar_Title_Inverse = 16974367; // 0x103021f
+    field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle = 16974368; // 0x1030220
+    field public static final int TextAppearance_Material_Widget_ActionMode_Subtitle_Inverse = 16974369; // 0x1030221
+    field public static final int TextAppearance_Material_Widget_ActionMode_Title = 16974370; // 0x1030222
+    field public static final int TextAppearance_Material_Widget_ActionMode_Title_Inverse = 16974371; // 0x1030223
+    field public static final int TextAppearance_Material_Widget_Button = 16974372; // 0x1030224
+    field public static final int TextAppearance_Material_Widget_DropDownHint = 16974373; // 0x1030225
+    field public static final int TextAppearance_Material_Widget_DropDownItem = 16974374; // 0x1030226
+    field public static final int TextAppearance_Material_Widget_EditText = 16974375; // 0x1030227
+    field public static final int TextAppearance_Material_Widget_IconMenu_Item = 16974376; // 0x1030228
+    field public static final int TextAppearance_Material_Widget_PopupMenu = 16974377; // 0x1030229
+    field public static final int TextAppearance_Material_Widget_PopupMenu_Large = 16974378; // 0x103022a
+    field public static final int TextAppearance_Material_Widget_PopupMenu_Small = 16974379; // 0x103022b
+    field public static final int TextAppearance_Material_Widget_TabWidget = 16974380; // 0x103022c
+    field public static final int TextAppearance_Material_Widget_TextView = 16974381; // 0x103022d
+    field public static final int TextAppearance_Material_Widget_TextView_PopupMenu = 16974382; // 0x103022e
+    field public static final int TextAppearance_Material_Widget_TextView_SpinnerItem = 16974383; // 0x103022f
+    field public static final int TextAppearance_Material_WindowTitle = 16974361; // 0x1030219
     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_Small = 16973894; // 0x1030046
@@ -1929,12 +1928,12 @@
     field public static final int TextAppearance_Widget_TextView_SpinnerItem = 16973906; // 0x1030052
     field public static final int TextAppearance_WindowTitle = 16973907; // 0x1030053
     field public static final int Theme = 16973829; // 0x1030005
-    field public static final int ThemeOverlay = 16974412; // 0x103024c
-    field public static final int ThemeOverlay_Material = 16974413; // 0x103024d
-    field public static final int ThemeOverlay_Material_ActionBar = 16974414; // 0x103024e
-    field public static final int ThemeOverlay_Material_Dark = 16974416; // 0x1030250
-    field public static final int ThemeOverlay_Material_Dark_ActionBar = 16974417; // 0x1030251
-    field public static final int ThemeOverlay_Material_Light = 16974415; // 0x103024f
+    field public static final int ThemeOverlay = 16974414; // 0x103024e
+    field public static final int ThemeOverlay_Material = 16974415; // 0x103024f
+    field public static final int ThemeOverlay_Material_ActionBar = 16974416; // 0x1030250
+    field public static final int ThemeOverlay_Material_Dark = 16974418; // 0x1030252
+    field public static final int ThemeOverlay_Material_Dark_ActionBar = 16974419; // 0x1030253
+    field public static final int ThemeOverlay_Material_Light = 16974417; // 0x1030251
     field public static final int Theme_Black = 16973832; // 0x1030008
     field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
     field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
@@ -2001,36 +2000,36 @@
     field public static final int Theme_Light_NoTitleBar_Fullscreen = 16973838; // 0x103000e
     field public static final int Theme_Light_Panel = 16973914; // 0x103005a
     field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
-    field public static final int Theme_Material = 16974382; // 0x103022e
-    field public static final int Theme_Material_Dialog = 16974383; // 0x103022f
-    field public static final int Theme_Material_DialogWhenLarge = 16974387; // 0x1030233
-    field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974388; // 0x1030234
-    field public static final int Theme_Material_Dialog_MinWidth = 16974384; // 0x1030230
-    field public static final int Theme_Material_Dialog_NoActionBar = 16974385; // 0x1030231
-    field public static final int Theme_Material_Dialog_NoActionBar_MinWidth = 16974386; // 0x1030232
-    field public static final int Theme_Material_InputMethod = 16974389; // 0x1030235
-    field public static final int Theme_Material_Light = 16974398; // 0x103023e
-    field public static final int Theme_Material_Light_DarkActionBar = 16974399; // 0x103023f
-    field public static final int Theme_Material_Light_Dialog = 16974400; // 0x1030240
-    field public static final int Theme_Material_Light_DialogWhenLarge = 16974404; // 0x1030244
-    field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974405; // 0x1030245
-    field public static final int Theme_Material_Light_Dialog_MinWidth = 16974401; // 0x1030241
-    field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974402; // 0x1030242
-    field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974403; // 0x1030243
-    field public static final int Theme_Material_Light_NoActionBar = 16974406; // 0x1030246
-    field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974407; // 0x1030247
-    field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974408; // 0x1030248
-    field public static final int Theme_Material_Light_NoActionBar_TranslucentDecor = 16974409; // 0x1030249
-    field public static final int Theme_Material_Light_Panel = 16974410; // 0x103024a
-    field public static final int Theme_Material_Light_Voice = 16974411; // 0x103024b
-    field public static final int Theme_Material_NoActionBar = 16974390; // 0x1030236
-    field public static final int Theme_Material_NoActionBar_Fullscreen = 16974391; // 0x1030237
-    field public static final int Theme_Material_NoActionBar_Overscan = 16974392; // 0x1030238
-    field public static final int Theme_Material_NoActionBar_TranslucentDecor = 16974393; // 0x1030239
-    field public static final int Theme_Material_Panel = 16974394; // 0x103023a
-    field public static final int Theme_Material_Voice = 16974395; // 0x103023b
-    field public static final int Theme_Material_Wallpaper = 16974396; // 0x103023c
-    field public static final int Theme_Material_Wallpaper_NoTitleBar = 16974397; // 0x103023d
+    field public static final int Theme_Material = 16974384; // 0x1030230
+    field public static final int Theme_Material_Dialog = 16974385; // 0x1030231
+    field public static final int Theme_Material_DialogWhenLarge = 16974389; // 0x1030235
+    field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974390; // 0x1030236
+    field public static final int Theme_Material_Dialog_MinWidth = 16974386; // 0x1030232
+    field public static final int Theme_Material_Dialog_NoActionBar = 16974387; // 0x1030233
+    field public static final int Theme_Material_Dialog_NoActionBar_MinWidth = 16974388; // 0x1030234
+    field public static final int Theme_Material_InputMethod = 16974391; // 0x1030237
+    field public static final int Theme_Material_Light = 16974400; // 0x1030240
+    field public static final int Theme_Material_Light_DarkActionBar = 16974401; // 0x1030241
+    field public static final int Theme_Material_Light_Dialog = 16974402; // 0x1030242
+    field public static final int Theme_Material_Light_DialogWhenLarge = 16974406; // 0x1030246
+    field public static final int Theme_Material_Light_DialogWhenLarge_NoActionBar = 16974407; // 0x1030247
+    field public static final int Theme_Material_Light_Dialog_MinWidth = 16974403; // 0x1030243
+    field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974404; // 0x1030244
+    field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974405; // 0x1030245
+    field public static final int Theme_Material_Light_NoActionBar = 16974408; // 0x1030248
+    field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974409; // 0x1030249
+    field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974410; // 0x103024a
+    field public static final int Theme_Material_Light_NoActionBar_TranslucentDecor = 16974411; // 0x103024b
+    field public static final int Theme_Material_Light_Panel = 16974412; // 0x103024c
+    field public static final int Theme_Material_Light_Voice = 16974413; // 0x103024d
+    field public static final int Theme_Material_NoActionBar = 16974392; // 0x1030238
+    field public static final int Theme_Material_NoActionBar_Fullscreen = 16974393; // 0x1030239
+    field public static final int Theme_Material_NoActionBar_Overscan = 16974394; // 0x103023a
+    field public static final int Theme_Material_NoActionBar_TranslucentDecor = 16974395; // 0x103023b
+    field public static final int Theme_Material_Panel = 16974396; // 0x103023c
+    field public static final int Theme_Material_Voice = 16974397; // 0x103023d
+    field public static final int Theme_Material_Wallpaper = 16974398; // 0x103023e
+    field public static final int Theme_Material_Wallpaper_NoTitleBar = 16974399; // 0x103023f
     field public static final int Theme_NoDisplay = 16973909; // 0x1030055
     field public static final int Theme_NoTitleBar = 16973830; // 0x1030006
     field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007
@@ -2092,7 +2091,7 @@
     field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
     field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
     field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
-    field public static final int Widget_DeviceDefault_FastScroll = 16974344; // 0x1030208
+    field public static final int Widget_DeviceDefault_FastScroll = 16974346; // 0x103020a
     field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
     field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
     field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
@@ -2126,7 +2125,7 @@
     field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
     field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
     field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
-    field public static final int Widget_DeviceDefault_Light_FastScroll = 16974346; // 0x103020a
+    field public static final int Widget_DeviceDefault_Light_FastScroll = 16974348; // 0x103020c
     field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
     field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
     field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
@@ -2150,7 +2149,7 @@
     field public static final int Widget_DeviceDefault_Light_ScrollView = 16974225; // 0x1030191
     field public static final int Widget_DeviceDefault_Light_SeekBar = 16974220; // 0x103018c
     field public static final int Widget_DeviceDefault_Light_Spinner = 16974227; // 0x1030193
-    field public static final int Widget_DeviceDefault_Light_StackView = 16974347; // 0x103020b
+    field public static final int Widget_DeviceDefault_Light_StackView = 16974349; // 0x103020d
     field public static final int Widget_DeviceDefault_Light_Tab = 16974237; // 0x103019d
     field public static final int Widget_DeviceDefault_Light_TabWidget = 16974229; // 0x1030195
     field public static final int Widget_DeviceDefault_Light_TextView = 16974202; // 0x103017a
@@ -2174,7 +2173,7 @@
     field public static final int Widget_DeviceDefault_ScrollView = 16974170; // 0x103015a
     field public static final int Widget_DeviceDefault_SeekBar = 16974165; // 0x1030155
     field public static final int Widget_DeviceDefault_Spinner = 16974172; // 0x103015c
-    field public static final int Widget_DeviceDefault_StackView = 16974345; // 0x1030209
+    field public static final int Widget_DeviceDefault_StackView = 16974347; // 0x103020b
     field public static final int Widget_DeviceDefault_Tab = 16974189; // 0x103016d
     field public static final int Widget_DeviceDefault_TabWidget = 16974174; // 0x103015e
     field public static final int Widget_DeviceDefault_TextView = 16974150; // 0x1030146
@@ -2217,7 +2216,7 @@
     field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
     field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
     field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
-    field public static final int Widget_Holo_FastScroll = 16974339; // 0x1030203
+    field public static final int Widget_Holo_FastScroll = 16974341; // 0x1030205
     field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
     field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
     field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
@@ -2238,7 +2237,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 = 16974341; // 0x1030205
+    field public static final int Widget_Holo_Light_Button_Borderless = 16974343; // 0x1030207
     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
@@ -2252,7 +2251,7 @@
     field public static final int Widget_Holo_Light_DropDownItem_Spinner = 16974041; // 0x10300d9
     field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
     field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
-    field public static final int Widget_Holo_Light_FastScroll = 16974342; // 0x1030206
+    field public static final int Widget_Holo_Light_FastScroll = 16974344; // 0x1030208
     field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
     field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
     field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
@@ -2276,7 +2275,7 @@
     field public static final int Widget_Holo_Light_ScrollView = 16974033; // 0x10300d1
     field public static final int Widget_Holo_Light_SeekBar = 16974028; // 0x10300cc
     field public static final int Widget_Holo_Light_Spinner = 16974035; // 0x10300d3
-    field public static final int Widget_Holo_Light_StackView = 16974343; // 0x1030207
+    field public static final int Widget_Holo_Light_StackView = 16974345; // 0x1030209
     field public static final int Widget_Holo_Light_Tab = 16974052; // 0x10300e4
     field public static final int Widget_Holo_Light_TabWidget = 16974037; // 0x10300d5
     field public static final int Widget_Holo_Light_TextView = 16974010; // 0x10300ba
@@ -2300,7 +2299,7 @@
     field public static final int Widget_Holo_ScrollView = 16973987; // 0x10300a3
     field public static final int Widget_Holo_SeekBar = 16973982; // 0x103009e
     field public static final int Widget_Holo_Spinner = 16973989; // 0x10300a5
-    field public static final int Widget_Holo_StackView = 16974340; // 0x1030204
+    field public static final int Widget_Holo_StackView = 16974342; // 0x1030206
     field public static final int Widget_Holo_Tab = 16974051; // 0x10300e3
     field public static final int Widget_Holo_TabWidget = 16973991; // 0x10300a7
     field public static final int Widget_Holo_TextView = 16973967; // 0x103008f
@@ -2315,126 +2314,128 @@
     field public static final int Widget_ListView_DropDown = 16973872; // 0x1030030
     field public static final int Widget_ListView_Menu = 16973873; // 0x1030031
     field public static final int Widget_ListView_White = 16973871; // 0x103002f
-    field public static final int Widget_Material = 16974418; // 0x1030252
-    field public static final int Widget_Material_ActionBar = 16974419; // 0x1030253
-    field public static final int Widget_Material_ActionBar_Solid = 16974420; // 0x1030254
-    field public static final int Widget_Material_ActionBar_TabBar = 16974421; // 0x1030255
-    field public static final int Widget_Material_ActionBar_TabText = 16974422; // 0x1030256
-    field public static final int Widget_Material_ActionBar_TabView = 16974423; // 0x1030257
-    field public static final int Widget_Material_ActionButton = 16974424; // 0x1030258
-    field public static final int Widget_Material_ActionButton_CloseMode = 16974425; // 0x1030259
-    field public static final int Widget_Material_ActionButton_Overflow = 16974426; // 0x103025a
-    field public static final int Widget_Material_ActionMode = 16974427; // 0x103025b
-    field public static final int Widget_Material_AutoCompleteTextView = 16974428; // 0x103025c
-    field public static final int Widget_Material_Button = 16974429; // 0x103025d
-    field public static final int Widget_Material_ButtonBar = 16974435; // 0x1030263
-    field public static final int Widget_Material_ButtonBar_AlertDialog = 16974436; // 0x1030264
-    field public static final int Widget_Material_Button_Borderless = 16974430; // 0x103025e
-    field public static final int Widget_Material_Button_Borderless_Small = 16974431; // 0x103025f
-    field public static final int Widget_Material_Button_Inset = 16974432; // 0x1030260
-    field public static final int Widget_Material_Button_Small = 16974433; // 0x1030261
-    field public static final int Widget_Material_Button_Toggle = 16974434; // 0x1030262
-    field public static final int Widget_Material_CalendarView = 16974437; // 0x1030265
-    field public static final int Widget_Material_CheckedTextView = 16974438; // 0x1030266
-    field public static final int Widget_Material_CompoundButton_CheckBox = 16974439; // 0x1030267
-    field public static final int Widget_Material_CompoundButton_RadioButton = 16974440; // 0x1030268
-    field public static final int Widget_Material_CompoundButton_Star = 16974441; // 0x1030269
-    field public static final int Widget_Material_DatePicker = 16974442; // 0x103026a
-    field public static final int Widget_Material_DropDownItem = 16974443; // 0x103026b
-    field public static final int Widget_Material_DropDownItem_Spinner = 16974444; // 0x103026c
-    field public static final int Widget_Material_EditText = 16974445; // 0x103026d
-    field public static final int Widget_Material_ExpandableListView = 16974446; // 0x103026e
-    field public static final int Widget_Material_FastScroll = 16974447; // 0x103026f
-    field public static final int Widget_Material_GridView = 16974448; // 0x1030270
-    field public static final int Widget_Material_HorizontalScrollView = 16974449; // 0x1030271
-    field public static final int Widget_Material_ImageButton = 16974450; // 0x1030272
-    field public static final int Widget_Material_Light = 16974477; // 0x103028d
-    field public static final int Widget_Material_Light_ActionBar = 16974478; // 0x103028e
-    field public static final int Widget_Material_Light_ActionBar_Solid = 16974479; // 0x103028f
-    field public static final int Widget_Material_Light_ActionBar_TabBar = 16974480; // 0x1030290
-    field public static final int Widget_Material_Light_ActionBar_TabText = 16974481; // 0x1030291
-    field public static final int Widget_Material_Light_ActionBar_TabView = 16974482; // 0x1030292
-    field public static final int Widget_Material_Light_ActionButton = 16974483; // 0x1030293
-    field public static final int Widget_Material_Light_ActionButton_CloseMode = 16974484; // 0x1030294
-    field public static final int Widget_Material_Light_ActionButton_Overflow = 16974485; // 0x1030295
-    field public static final int Widget_Material_Light_ActionMode = 16974486; // 0x1030296
-    field public static final int Widget_Material_Light_AutoCompleteTextView = 16974487; // 0x1030297
-    field public static final int Widget_Material_Light_Button = 16974488; // 0x1030298
-    field public static final int Widget_Material_Light_ButtonBar = 16974494; // 0x103029e
-    field public static final int Widget_Material_Light_ButtonBar_AlertDialog = 16974495; // 0x103029f
-    field public static final int Widget_Material_Light_Button_Borderless = 16974489; // 0x1030299
-    field public static final int Widget_Material_Light_Button_Borderless_Small = 16974490; // 0x103029a
-    field public static final int Widget_Material_Light_Button_Inset = 16974491; // 0x103029b
-    field public static final int Widget_Material_Light_Button_Small = 16974492; // 0x103029c
-    field public static final int Widget_Material_Light_Button_Toggle = 16974493; // 0x103029d
-    field public static final int Widget_Material_Light_CalendarView = 16974496; // 0x10302a0
-    field public static final int Widget_Material_Light_CheckedTextView = 16974497; // 0x10302a1
-    field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974498; // 0x10302a2
-    field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974499; // 0x10302a3
-    field public static final int Widget_Material_Light_CompoundButton_Star = 16974500; // 0x10302a4
-    field public static final int Widget_Material_Light_DropDownItem = 16974501; // 0x10302a5
-    field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974502; // 0x10302a6
-    field public static final int Widget_Material_Light_EditText = 16974503; // 0x10302a7
-    field public static final int Widget_Material_Light_ExpandableListView = 16974504; // 0x10302a8
-    field public static final int Widget_Material_Light_FastScroll = 16974505; // 0x10302a9
-    field public static final int Widget_Material_Light_GridView = 16974506; // 0x10302aa
-    field public static final int Widget_Material_Light_HorizontalScrollView = 16974507; // 0x10302ab
-    field public static final int Widget_Material_Light_ImageButton = 16974508; // 0x10302ac
-    field public static final int Widget_Material_Light_ListPopupWindow = 16974509; // 0x10302ad
-    field public static final int Widget_Material_Light_ListView = 16974510; // 0x10302ae
-    field public static final int Widget_Material_Light_ListView_DropDown = 16974511; // 0x10302af
-    field public static final int Widget_Material_Light_MediaRouteButton = 16974512; // 0x10302b0
-    field public static final int Widget_Material_Light_PopupMenu = 16974513; // 0x10302b1
-    field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974514; // 0x10302b2
-    field public static final int Widget_Material_Light_PopupWindow = 16974515; // 0x10302b3
-    field public static final int Widget_Material_Light_ProgressBar = 16974516; // 0x10302b4
-    field public static final int Widget_Material_Light_ProgressBar_Horizontal = 16974517; // 0x10302b5
-    field public static final int Widget_Material_Light_ProgressBar_Inverse = 16974518; // 0x10302b6
-    field public static final int Widget_Material_Light_ProgressBar_Large = 16974519; // 0x10302b7
-    field public static final int Widget_Material_Light_ProgressBar_Large_Inverse = 16974520; // 0x10302b8
-    field public static final int Widget_Material_Light_ProgressBar_Small = 16974521; // 0x10302b9
-    field public static final int Widget_Material_Light_ProgressBar_Small_Inverse = 16974522; // 0x10302ba
-    field public static final int Widget_Material_Light_ProgressBar_Small_Title = 16974523; // 0x10302bb
-    field public static final int Widget_Material_Light_RatingBar = 16974524; // 0x10302bc
-    field public static final int Widget_Material_Light_RatingBar_Indicator = 16974525; // 0x10302bd
-    field public static final int Widget_Material_Light_RatingBar_Small = 16974526; // 0x10302be
-    field public static final int Widget_Material_Light_ScrollView = 16974527; // 0x10302bf
-    field public static final int Widget_Material_Light_SeekBar = 16974528; // 0x10302c0
-    field public static final int Widget_Material_Light_SegmentedButton = 16974529; // 0x10302c1
-    field public static final int Widget_Material_Light_Spinner = 16974531; // 0x10302c3
-    field public static final int Widget_Material_Light_StackView = 16974530; // 0x10302c2
-    field public static final int Widget_Material_Light_Tab = 16974532; // 0x10302c4
-    field public static final int Widget_Material_Light_TabWidget = 16974533; // 0x10302c5
-    field public static final int Widget_Material_Light_TextView = 16974534; // 0x10302c6
-    field public static final int Widget_Material_Light_TextView_SpinnerItem = 16974535; // 0x10302c7
-    field public static final int Widget_Material_Light_WebTextView = 16974536; // 0x10302c8
-    field public static final int Widget_Material_Light_WebView = 16974537; // 0x10302c9
-    field public static final int Widget_Material_ListPopupWindow = 16974451; // 0x1030273
-    field public static final int Widget_Material_ListView = 16974452; // 0x1030274
-    field public static final int Widget_Material_ListView_DropDown = 16974453; // 0x1030275
-    field public static final int Widget_Material_MediaRouteButton = 16974454; // 0x1030276
-    field public static final int Widget_Material_PopupMenu = 16974455; // 0x1030277
-    field public static final int Widget_Material_PopupMenu_Overflow = 16974456; // 0x1030278
-    field public static final int Widget_Material_PopupWindow = 16974457; // 0x1030279
-    field public static final int Widget_Material_ProgressBar = 16974458; // 0x103027a
-    field public static final int Widget_Material_ProgressBar_Horizontal = 16974459; // 0x103027b
-    field public static final int Widget_Material_ProgressBar_Large = 16974460; // 0x103027c
-    field public static final int Widget_Material_ProgressBar_Small = 16974461; // 0x103027d
-    field public static final int Widget_Material_ProgressBar_Small_Title = 16974462; // 0x103027e
-    field public static final int Widget_Material_RatingBar = 16974463; // 0x103027f
-    field public static final int Widget_Material_RatingBar_Indicator = 16974464; // 0x1030280
-    field public static final int Widget_Material_RatingBar_Small = 16974465; // 0x1030281
-    field public static final int Widget_Material_ScrollView = 16974466; // 0x1030282
-    field public static final int Widget_Material_SeekBar = 16974467; // 0x1030283
-    field public static final int Widget_Material_SegmentedButton = 16974468; // 0x1030284
-    field public static final int Widget_Material_Spinner = 16974470; // 0x1030286
-    field public static final int Widget_Material_StackView = 16974469; // 0x1030285
-    field public static final int Widget_Material_Tab = 16974471; // 0x1030287
-    field public static final int Widget_Material_TabWidget = 16974472; // 0x1030288
-    field public static final int Widget_Material_TextView = 16974473; // 0x1030289
-    field public static final int Widget_Material_TextView_SpinnerItem = 16974474; // 0x103028a
-    field public static final int Widget_Material_WebTextView = 16974475; // 0x103028b
-    field public static final int Widget_Material_WebView = 16974476; // 0x103028c
+    field public static final int Widget_Material = 16974420; // 0x1030254
+    field public static final int Widget_Material_ActionBar = 16974421; // 0x1030255
+    field public static final int Widget_Material_ActionBar_Solid = 16974422; // 0x1030256
+    field public static final int Widget_Material_ActionBar_TabBar = 16974423; // 0x1030257
+    field public static final int Widget_Material_ActionBar_TabText = 16974424; // 0x1030258
+    field public static final int Widget_Material_ActionBar_TabView = 16974425; // 0x1030259
+    field public static final int Widget_Material_ActionButton = 16974426; // 0x103025a
+    field public static final int Widget_Material_ActionButton_CloseMode = 16974427; // 0x103025b
+    field public static final int Widget_Material_ActionButton_Overflow = 16974428; // 0x103025c
+    field public static final int Widget_Material_ActionMode = 16974429; // 0x103025d
+    field public static final int Widget_Material_AutoCompleteTextView = 16974430; // 0x103025e
+    field public static final int Widget_Material_Button = 16974431; // 0x103025f
+    field public static final int Widget_Material_ButtonBar = 16974437; // 0x1030265
+    field public static final int Widget_Material_ButtonBar_AlertDialog = 16974438; // 0x1030266
+    field public static final int Widget_Material_Button_Borderless = 16974432; // 0x1030260
+    field public static final int Widget_Material_Button_Borderless_Small = 16974433; // 0x1030261
+    field public static final int Widget_Material_Button_Inset = 16974434; // 0x1030262
+    field public static final int Widget_Material_Button_Small = 16974435; // 0x1030263
+    field public static final int Widget_Material_Button_Toggle = 16974436; // 0x1030264
+    field public static final int Widget_Material_CalendarView = 16974439; // 0x1030267
+    field public static final int Widget_Material_CheckedTextView = 16974440; // 0x1030268
+    field public static final int Widget_Material_CompoundButton_CheckBox = 16974441; // 0x1030269
+    field public static final int Widget_Material_CompoundButton_RadioButton = 16974442; // 0x103026a
+    field public static final int Widget_Material_CompoundButton_Star = 16974443; // 0x103026b
+    field public static final int Widget_Material_DatePicker = 16974444; // 0x103026c
+    field public static final int Widget_Material_DropDownItem = 16974445; // 0x103026d
+    field public static final int Widget_Material_DropDownItem_Spinner = 16974446; // 0x103026e
+    field public static final int Widget_Material_EditText = 16974447; // 0x103026f
+    field public static final int Widget_Material_ExpandableListView = 16974448; // 0x1030270
+    field public static final int Widget_Material_FastScroll = 16974449; // 0x1030271
+    field public static final int Widget_Material_GridView = 16974450; // 0x1030272
+    field public static final int Widget_Material_HorizontalScrollView = 16974451; // 0x1030273
+    field public static final int Widget_Material_ImageButton = 16974452; // 0x1030274
+    field public static final int Widget_Material_Light = 16974481; // 0x1030291
+    field public static final int Widget_Material_Light_ActionBar = 16974482; // 0x1030292
+    field public static final int Widget_Material_Light_ActionBar_Solid = 16974483; // 0x1030293
+    field public static final int Widget_Material_Light_ActionBar_TabBar = 16974484; // 0x1030294
+    field public static final int Widget_Material_Light_ActionBar_TabText = 16974485; // 0x1030295
+    field public static final int Widget_Material_Light_ActionBar_TabView = 16974486; // 0x1030296
+    field public static final int Widget_Material_Light_ActionButton = 16974487; // 0x1030297
+    field public static final int Widget_Material_Light_ActionButton_CloseMode = 16974488; // 0x1030298
+    field public static final int Widget_Material_Light_ActionButton_Overflow = 16974489; // 0x1030299
+    field public static final int Widget_Material_Light_ActionMode = 16974490; // 0x103029a
+    field public static final int Widget_Material_Light_AutoCompleteTextView = 16974491; // 0x103029b
+    field public static final int Widget_Material_Light_Button = 16974492; // 0x103029c
+    field public static final int Widget_Material_Light_ButtonBar = 16974498; // 0x10302a2
+    field public static final int Widget_Material_Light_ButtonBar_AlertDialog = 16974499; // 0x10302a3
+    field public static final int Widget_Material_Light_Button_Borderless = 16974493; // 0x103029d
+    field public static final int Widget_Material_Light_Button_Borderless_Small = 16974494; // 0x103029e
+    field public static final int Widget_Material_Light_Button_Inset = 16974495; // 0x103029f
+    field public static final int Widget_Material_Light_Button_Small = 16974496; // 0x10302a0
+    field public static final int Widget_Material_Light_Button_Toggle = 16974497; // 0x10302a1
+    field public static final int Widget_Material_Light_CalendarView = 16974500; // 0x10302a4
+    field public static final int Widget_Material_Light_CheckedTextView = 16974501; // 0x10302a5
+    field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974502; // 0x10302a6
+    field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974503; // 0x10302a7
+    field public static final int Widget_Material_Light_CompoundButton_Star = 16974504; // 0x10302a8
+    field public static final int Widget_Material_Light_DropDownItem = 16974505; // 0x10302a9
+    field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974506; // 0x10302aa
+    field public static final int Widget_Material_Light_EditText = 16974507; // 0x10302ab
+    field public static final int Widget_Material_Light_ExpandableListView = 16974508; // 0x10302ac
+    field public static final int Widget_Material_Light_FastScroll = 16974509; // 0x10302ad
+    field public static final int Widget_Material_Light_GridView = 16974510; // 0x10302ae
+    field public static final int Widget_Material_Light_HorizontalScrollView = 16974511; // 0x10302af
+    field public static final int Widget_Material_Light_ImageButton = 16974512; // 0x10302b0
+    field public static final int Widget_Material_Light_ListPopupWindow = 16974513; // 0x10302b1
+    field public static final int Widget_Material_Light_ListView = 16974514; // 0x10302b2
+    field public static final int Widget_Material_Light_ListView_DropDown = 16974515; // 0x10302b3
+    field public static final int Widget_Material_Light_MediaRouteButton = 16974516; // 0x10302b4
+    field public static final int Widget_Material_Light_PopupMenu = 16974517; // 0x10302b5
+    field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974518; // 0x10302b6
+    field public static final int Widget_Material_Light_PopupWindow = 16974519; // 0x10302b7
+    field public static final int Widget_Material_Light_ProgressBar = 16974520; // 0x10302b8
+    field public static final int Widget_Material_Light_ProgressBar_Horizontal = 16974521; // 0x10302b9
+    field public static final int Widget_Material_Light_ProgressBar_Inverse = 16974522; // 0x10302ba
+    field public static final int Widget_Material_Light_ProgressBar_Large = 16974523; // 0x10302bb
+    field public static final int Widget_Material_Light_ProgressBar_Large_Inverse = 16974524; // 0x10302bc
+    field public static final int Widget_Material_Light_ProgressBar_Small = 16974525; // 0x10302bd
+    field public static final int Widget_Material_Light_ProgressBar_Small_Inverse = 16974526; // 0x10302be
+    field public static final int Widget_Material_Light_ProgressBar_Small_Title = 16974527; // 0x10302bf
+    field public static final int Widget_Material_Light_RatingBar = 16974528; // 0x10302c0
+    field public static final int Widget_Material_Light_RatingBar_Indicator = 16974529; // 0x10302c1
+    field public static final int Widget_Material_Light_RatingBar_Small = 16974530; // 0x10302c2
+    field public static final int Widget_Material_Light_ScrollView = 16974531; // 0x10302c3
+    field public static final int Widget_Material_Light_SeekBar = 16974532; // 0x10302c4
+    field public static final int Widget_Material_Light_SegmentedButton = 16974533; // 0x10302c5
+    field public static final int Widget_Material_Light_Spinner = 16974535; // 0x10302c7
+    field public static final int Widget_Material_Light_StackView = 16974534; // 0x10302c6
+    field public static final int Widget_Material_Light_Tab = 16974536; // 0x10302c8
+    field public static final int Widget_Material_Light_TabWidget = 16974537; // 0x10302c9
+    field public static final int Widget_Material_Light_TextView = 16974538; // 0x10302ca
+    field public static final int Widget_Material_Light_TextView_SpinnerItem = 16974539; // 0x10302cb
+    field public static final int Widget_Material_Light_WebTextView = 16974540; // 0x10302cc
+    field public static final int Widget_Material_Light_WebView = 16974541; // 0x10302cd
+    field public static final int Widget_Material_ListPopupWindow = 16974453; // 0x1030275
+    field public static final int Widget_Material_ListView = 16974454; // 0x1030276
+    field public static final int Widget_Material_ListView_DropDown = 16974455; // 0x1030277
+    field public static final int Widget_Material_MediaRouteButton = 16974456; // 0x1030278
+    field public static final int Widget_Material_PopupMenu = 16974457; // 0x1030279
+    field public static final int Widget_Material_PopupMenu_Overflow = 16974458; // 0x103027a
+    field public static final int Widget_Material_PopupWindow = 16974459; // 0x103027b
+    field public static final int Widget_Material_ProgressBar = 16974460; // 0x103027c
+    field public static final int Widget_Material_ProgressBar_Horizontal = 16974461; // 0x103027d
+    field public static final int Widget_Material_ProgressBar_Large = 16974462; // 0x103027e
+    field public static final int Widget_Material_ProgressBar_Small = 16974463; // 0x103027f
+    field public static final int Widget_Material_ProgressBar_Small_Title = 16974464; // 0x1030280
+    field public static final int Widget_Material_RatingBar = 16974465; // 0x1030281
+    field public static final int Widget_Material_RatingBar_Indicator = 16974466; // 0x1030282
+    field public static final int Widget_Material_RatingBar_Small = 16974467; // 0x1030283
+    field public static final int Widget_Material_ScrollView = 16974468; // 0x1030284
+    field public static final int Widget_Material_SeekBar = 16974469; // 0x1030285
+    field public static final int Widget_Material_SegmentedButton = 16974470; // 0x1030286
+    field public static final int Widget_Material_Spinner = 16974472; // 0x1030288
+    field public static final int Widget_Material_StackView = 16974471; // 0x1030287
+    field public static final int Widget_Material_Tab = 16974473; // 0x1030289
+    field public static final int Widget_Material_TabWidget = 16974474; // 0x103028a
+    field public static final int Widget_Material_TextView = 16974475; // 0x103028b
+    field public static final int Widget_Material_TextView_SpinnerItem = 16974476; // 0x103028c
+    field public static final int Widget_Material_Toolbar = 16974477; // 0x103028d
+    field public static final int Widget_Material_Toolbar_Button_Navigation = 16974478; // 0x103028e
+    field public static final int Widget_Material_WebTextView = 16974479; // 0x103028f
+    field public static final int Widget_Material_WebView = 16974480; // 0x1030290
     field public static final int Widget_PopupMenu = 16973958; // 0x1030086
     field public static final int Widget_PopupWindow = 16973878; // 0x1030036
     field public static final int Widget_ProgressBar = 16973852; // 0x103001c
@@ -2454,6 +2455,8 @@
     field public static final int Widget_TextView = 16973858; // 0x1030022
     field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029
     field public static final int Widget_TextView_SpinnerItem = 16973866; // 0x103002a
+    field public static final int Widget_Toolbar = 16974339; // 0x1030203
+    field public static final int Widget_Toolbar_Button_Navigation = 16974340; // 0x1030204
     field public static final int Widget_WebView = 16973875; // 0x1030033
     field public static final int l_resource_pad1 = 16974336; // 0x1030200
     field public static final int l_resource_pad10 = 16974327; // 0x10301f7
@@ -5356,23 +5359,9 @@
 
 }
 
-package android.app.maintenance {
+package android.app.job {
 
-  public abstract class IdleService extends android.app.Service {
-    ctor public IdleService();
-    method public final void finishIdle();
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract boolean onIdleStart();
-    method public abstract void onIdleStop();
-    field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_IDLE_SERVICE";
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.idle.IdleService";
-  }
-
-}
-
-package android.app.task {
-
-  public class Task implements android.os.Parcelable {
+  public class JobInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getBackoffPolicy();
     method public android.os.PersistableBundle getExtras();
@@ -5390,55 +5379,55 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public static abstract interface Task.BackoffPolicy {
+  public static abstract interface JobInfo.BackoffPolicy {
     field public static final int EXPONENTIAL = 1; // 0x1
     field public static final int LINEAR = 0; // 0x0
   }
 
-  public static final class Task.Builder {
-    ctor public Task.Builder(int, android.content.ComponentName);
-    method public android.app.task.Task build();
-    method public android.app.task.Task.Builder setBackoffCriteria(long, int);
-    method public android.app.task.Task.Builder setExtras(android.os.PersistableBundle);
-    method public android.app.task.Task.Builder setMinimumLatency(long);
-    method public android.app.task.Task.Builder setOverrideDeadline(long);
-    method public android.app.task.Task.Builder setPeriodic(long);
-    method public android.app.task.Task.Builder setRequiredNetworkCapabilities(int);
-    method public android.app.task.Task.Builder setRequiresCharging(boolean);
-    method public android.app.task.Task.Builder setRequiresDeviceIdle(boolean);
+  public static final class JobInfo.Builder {
+    ctor public JobInfo.Builder(int, android.content.ComponentName);
+    method public android.app.job.JobInfo build();
+    method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
+    method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
+    method public android.app.job.JobInfo.Builder setMinimumLatency(long);
+    method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
+    method public android.app.job.JobInfo.Builder setPeriodic(long);
+    method public android.app.job.JobInfo.Builder setRequiredNetworkCapabilities(int);
+    method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
+    method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
   }
 
-  public static abstract interface Task.NetworkType {
+  public static abstract interface JobInfo.NetworkType {
     field public static final int ANY = 1; // 0x1
     field public static final int NONE = 0; // 0x0
     field public static final int UNMETERED = 2; // 0x2
   }
 
-  public abstract class TaskManager {
-    ctor public TaskManager();
-    method public abstract void cancel(int);
-    method public abstract void cancelAll();
-    method public abstract java.util.List<android.app.task.Task> getAllPendingTasks();
-    method public abstract int schedule(android.app.task.Task);
-    field public static final int RESULT_FAILURE = 0; // 0x0
-    field public static final int RESULT_SUCCESS = 1; // 0x1
-  }
-
-  public class TaskParams implements android.os.Parcelable {
+  public class JobParameters implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.PersistableBundle getExtras();
-    method public int getTaskId();
+    method public int getJobId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public abstract class TaskService extends android.app.Service {
-    ctor public TaskService();
+  public abstract class JobScheduler {
+    ctor public JobScheduler();
+    method public abstract void cancel(int);
+    method public abstract void cancelAll();
+    method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
+    method public abstract int schedule(android.app.job.JobInfo);
+    field public static final int RESULT_FAILURE = 0; // 0x0
+    field public static final int RESULT_SUCCESS = 1; // 0x1
+  }
+
+  public abstract class JobService extends android.app.Service {
+    ctor public JobService();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract boolean onStartTask(android.app.task.TaskParams);
-    method public abstract boolean onStopTask(android.app.task.TaskParams);
-    method public final void taskFinished(android.app.task.TaskParams, boolean);
-    field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_TASK_SERVICE";
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+    field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
 }
@@ -7006,6 +6995,7 @@
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     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 JOB_SCHEDULER_SERVICE = "jobscheduler";
     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";
@@ -7026,7 +7016,6 @@
     field public static final java.lang.String SEARCH_SERVICE = "search";
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
-    field public static final java.lang.String TASK_SERVICE = "task";
     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";
@@ -11458,6 +11447,7 @@
 
   public class RippleDrawable extends android.graphics.drawable.LayerDrawable {
     ctor public RippleDrawable(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setColor(android.content.res.ColorStateList);
   }
 
   public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
@@ -15951,6 +15941,7 @@
     method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network);
     method public android.net.NetworkInfo getNetworkInfo(int);
     method public deprecated int getNetworkPreference();
+    method public static android.net.Network getProcessDefaultNetwork();
     method public boolean isActiveNetworkMetered();
     method public boolean isNetworkActive();
     method public static boolean isNetworkTypeValid(int);
@@ -15962,6 +15953,7 @@
     method public android.net.NetworkRequest requestNetwork(android.net.NetworkCapabilities, android.app.PendingIntent);
     method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
+    method public static boolean setProcessDefaultNetwork(android.net.Network);
     method public deprecated int startUsingNetworkFeature(int, java.lang.String);
     method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
     method public void unregisterNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -16134,13 +16126,10 @@
   }
 
   public class Network implements android.os.Parcelable {
-    method public void bindProcess();
     method public int describeContents();
     method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
     method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
-    method public static android.net.Network getProcessBoundNetwork();
-    method public javax.net.SocketFactory socketFactory();
-    method public static void unbindProcess();
+    method public javax.net.SocketFactory getSocketFactory();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 23b5f29..946555f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5326,7 +5326,8 @@
      *
      * @hide
      */
-    void convertToTranslucent(TranslucentConversionListener callback, ActivityOptions options) {
+    public void convertToTranslucent(TranslucentConversionListener callback, 
+            ActivityOptions options) {
         boolean drawComplete;
         try {
             mTranslucentCallback = callback;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5bbc43c..c5190d3 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -133,7 +133,7 @@
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
-import android.app.task.ITaskManager;
+import android.app.job.IJobScheduler;
 import android.app.trust.TrustManager;
 
 import com.android.internal.annotations.GuardedBy;
@@ -697,10 +697,10 @@
                 return new UsageStatsManager(ctx.getOuterContext());
         }});
 
-        registerService(TASK_SERVICE, new ServiceFetcher() {
+        registerService(JOB_SCHEDULER_SERVICE, new ServiceFetcher() {
             public Object createService(ContextImpl ctx) {
-                IBinder b = ServiceManager.getService(TASK_SERVICE);
-                return new TaskManagerImpl(ITaskManager.Stub.asInterface(b));
+                IBinder b = ServiceManager.getService(JOB_SCHEDULER_SERVICE);
+                return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b));
             }});
     }
 
diff --git a/core/java/android/app/TaskManagerImpl.java b/core/java/android/app/JobSchedulerImpl.java
similarity index 67%
rename from core/java/android/app/TaskManagerImpl.java
rename to core/java/android/app/JobSchedulerImpl.java
index fe29fb7..09038d5 100644
--- a/core/java/android/app/TaskManagerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -17,38 +17,38 @@
 // in android.app so ContextImpl has package access
 package android.app;
 
-import android.app.task.ITaskManager;
-import android.app.task.Task;
-import android.app.task.TaskManager;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.app.job.IJobScheduler;
 import android.os.RemoteException;
 
 import java.util.List;
 
 
 /**
- * Concrete implementation of the TaskManager interface
+ * Concrete implementation of the JobScheduler interface
  * @hide 
  */
-public class TaskManagerImpl extends TaskManager {
-    ITaskManager mBinder;
+public class JobSchedulerImpl extends JobScheduler {
+    IJobScheduler mBinder;
 
-    /* package */ TaskManagerImpl(ITaskManager binder) {
+    /* package */ JobSchedulerImpl(IJobScheduler binder) {
         mBinder = binder;
     }
 
     @Override
-    public int schedule(Task task) {
+    public int schedule(JobInfo job) {
         try {
-            return mBinder.schedule(task);
+            return mBinder.schedule(job);
         } catch (RemoteException e) {
-            return TaskManager.RESULT_FAILURE;
+            return JobScheduler.RESULT_FAILURE;
         }
     }
 
     @Override
-    public void cancel(int taskId) {
+    public void cancel(int jobId) {
         try {
-            mBinder.cancel(taskId);
+            mBinder.cancel(jobId);
         } catch (RemoteException e) {}
 
     }
@@ -62,9 +62,9 @@
     }
 
     @Override
-    public List<Task> getAllPendingTasks() {
+    public List<JobInfo> getAllPendingJobs() {
         try {
-            return mBinder.getAllPendingTasks();
+            return mBinder.getAllPendingJobs();
         } catch (RemoteException e) {
             return null;
         }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a1cdf59..276f936 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -23,7 +23,6 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
@@ -31,7 +30,6 @@
 import android.media.session.MediaSessionToken;
 import android.net.Uri;
 import android.os.BadParcelableException;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -2568,7 +2566,7 @@
                     R.id.icon,
                     true,
                     -1,
-                    mColor,
+                    resolveColor(),
                     PorterDuff.Mode.SRC_ATOP,
                     -1);
         }
@@ -2595,17 +2593,22 @@
                         R.id.right_icon,
                         true,
                         -1,
-                        mColor,
+                        resolveColor(),
                         PorterDuff.Mode.SRC_ATOP,
                         -1);
             }
         }
 
+        private int sanitizeColor() {
+            if (mColor != COLOR_DEFAULT) {
+                mColor |= 0xFF000000; // no alpha for custom colors
+            }
+            return mColor;
+        }
+
         private int resolveColor() {
             if (mColor == COLOR_DEFAULT) {
-                mColor = mContext.getResources().getColor(R.color.notification_icon_bg_color);
-            } else {
-                mColor |= 0xFF000000; // no alpha for custom colors
+                return mContext.getResources().getColor(R.color.notification_icon_bg_color);
             }
             return mColor;
         }
@@ -2621,7 +2624,7 @@
             n.iconLevel = mSmallIconLevel;
             n.number = mNumber;
 
-            n.color = resolveColor();
+            n.color = sanitizeColor();
 
             n.contentView = makeContentView();
             n.contentIntent = mContentIntent;
diff --git a/core/java/android/app/job/IJobCallback.aidl b/core/java/android/app/job/IJobCallback.aidl
new file mode 100644
index 0000000..2d3948f
--- /dev/null
+++ b/core/java/android/app/job/IJobCallback.aidl
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+/**
+ * The server side of the JobScheduler IPC protocols.  The app-side implementation
+ * invokes on this interface to indicate completion of the (asynchronous) instructions
+ * issued by the server.
+ *
+ * In all cases, the 'who' parameter is the caller's service binder, used to track
+ * which Job Service instance is reporting.
+ *
+ * {@hide}
+ */
+interface IJobCallback {
+    /**
+     * Immediate callback to the system after sending a start signal, used to quickly detect ANR.
+     *
+     * @param jobId Unique integer used to identify this job.
+     * @param ongoing True to indicate that the client is processing the job. False if the job is
+     * complete
+     */
+    void acknowledgeStartMessage(int jobId, boolean ongoing);
+    /**
+     * Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
+     *
+     * @param jobId Unique integer used to identify this job.
+     * @param reschedule Whether or not to reschedule this job.
+     */
+    void acknowledgeStopMessage(int jobId, boolean reschedule);
+    /*
+     * Tell the job manager that the client is done with its execution, so that it can go on to
+     * the next one and stop attributing wakelock time to us etc.
+     *
+     * @param jobId Unique integer used to identify this job.
+     * @param reschedule Whether or not to reschedule this job.
+     */
+    void jobFinished(int jobId, boolean reschedule);
+}
diff --git a/core/java/android/app/task/ITaskManager.aidl b/core/java/android/app/job/IJobScheduler.aidl
similarity index 71%
rename from core/java/android/app/task/ITaskManager.aidl
rename to core/java/android/app/job/IJobScheduler.aidl
index b56c78a..f1258ae 100644
--- a/core/java/android/app/task/ITaskManager.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
-package android.app.task;
+package android.app.job;
 
-import android.app.task.Task;
+import android.app.job.JobInfo;
 
  /**
-  * IPC interface that supports the app-facing {@link #TaskManager} api.
+  * IPC interface that supports the app-facing {@link #JobScheduler} api.
   * {@hide}
   */
-interface ITaskManager {
-    int schedule(in Task task);
-    void cancel(int taskId);
+interface IJobScheduler {
+    int schedule(in JobInfo job);
+    void cancel(int jobId);
     void cancelAll();
-    List<Task> getAllPendingTasks();
+    List<JobInfo> getAllPendingJobs();
 }
diff --git a/core/java/android/app/task/ITaskService.aidl b/core/java/android/app/job/IJobService.aidl
similarity index 62%
rename from core/java/android/app/task/ITaskService.aidl
rename to core/java/android/app/job/IJobService.aidl
index 87b0191..63f8b81 100644
--- a/core/java/android/app/task/ITaskService.aidl
+++ b/core/java/android/app/job/IJobService.aidl
@@ -14,22 +14,19 @@
  * limitations under the License.
  */
 
-package android.app.task;
+package android.app.job;
 
-import android.app.task.ITaskCallback;
-import android.app.task.TaskParams;
-
-import android.os.Bundle;
+import android.app.job.JobParameters;
 
 /**
  * Interface that the framework uses to communicate with application code that implements a
- * TaskService.  End user code does not implement this interface directly; instead, the app's
- * service implementation will extend android.app.task.TaskService.
+ * JobService.  End user code does not implement this interface directly; instead, the app's
+ * service implementation will extend android.app.job.JobService.
  * {@hide}
  */
-oneway interface ITaskService {
-    /** Begin execution of application's task. */
-    void startTask(in TaskParams taskParams);
+oneway interface IJobService {
+    /** Begin execution of application's job. */
+    void startJob(in JobParameters jobParams);
     /** Stop execution of application's task. */
-    void stopTask(in TaskParams taskParams);
+    void stopJob(in JobParameters jobParams);
 }
diff --git a/core/java/android/app/task/Task.aidl b/core/java/android/app/job/JobInfo.aidl
similarity index 92%
rename from core/java/android/app/task/Task.aidl
rename to core/java/android/app/job/JobInfo.aidl
index 1f25439..7b198a8 100644
--- a/core/java/android/app/task/Task.aidl
+++ b/core/java/android/app/job/JobInfo.aidl
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.app.task;
+package android.app.job;
 
-parcelable Task;
- 
\ No newline at end of file
+parcelable JobInfo;
diff --git a/core/java/android/app/task/Task.java b/core/java/android/app/job/JobInfo.java
similarity index 74%
rename from core/java/android/app/task/Task.java
rename to core/java/android/app/job/JobInfo.java
index 0e660b3..a22e4cd 100644
--- a/core/java/android/app/task/Task.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package android.app.task;
+package android.app.job;
 
 import android.content.ComponentName;
 import android.os.Bundle;
@@ -23,22 +23,22 @@
 import android.os.PersistableBundle;
 
 /**
- * Container of data passed to the {@link android.app.task.TaskManager} fully encapsulating the
+ * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
  * parameters required to schedule work against the calling application. These are constructed
- * using the {@link Task.Builder}.
+ * using the {@link JobInfo.Builder}.
  */
-public class Task implements Parcelable {
+public class JobInfo implements Parcelable {
     public interface NetworkType {
         /** Default. */
         public final int NONE = 0;
-        /** This task requires network connectivity. */
+        /** This job requires network connectivity. */
         public final int ANY = 1;
-        /** This task requires network connectivity that is unmetered. */
+        /** This job requires network connectivity that is unmetered. */
         public final int UNMETERED = 2;
     }
 
     /**
-     * Amount of backoff a task has initially by default, in milliseconds.
+     * Amount of backoff a job has initially by default, in milliseconds.
      * @hide.
      */
     public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 5000L;
@@ -63,7 +63,7 @@
         public final int EXPONENTIAL = 1;
     }
 
-    private final int taskId;
+    private final int jobId;
     // TODO: Change this to use PersistableBundle when that lands in master.
     private final PersistableBundle extras;
     private final ComponentName service;
@@ -80,10 +80,10 @@
     private final int backoffPolicy;
 
     /**
-     * Unique task id associated with this class. This is assigned to your task by the scheduler.
+     * Unique job id associated with this class. This is assigned to your job by the scheduler.
      */
     public int getId() {
-        return taskId;
+        return jobId;
     }
 
     /**
@@ -94,43 +94,43 @@
     }
 
     /**
-     * Name of the service endpoint that will be called back into by the TaskManager.
+     * Name of the service endpoint that will be called back into by the JobScheduler.
      */
     public ComponentName getService() {
         return service;
     }
 
     /**
-     * Whether this task needs the device to be plugged in.
+     * Whether this job needs the device to be plugged in.
      */
     public boolean isRequireCharging() {
         return requireCharging;
     }
 
     /**
-     * Whether this task needs the device to be in an Idle maintenance window.
+     * Whether this job needs the device to be in an Idle maintenance window.
      */
     public boolean isRequireDeviceIdle() {
         return requireDeviceIdle;
     }
 
     /**
-     * See {@link android.app.task.Task.NetworkType} for a description of this value.
+     * See {@link android.app.job.JobInfo.NetworkType} for a description of this value.
      */
     public int getNetworkCapabilities() {
         return networkCapabilities;
     }
 
     /**
-     * Set for a task that does not recur periodically, to specify a delay after which the task
-     * will be eligible for execution. This value is not set if the task recurs periodically.
+     * Set for a job that does not recur periodically, to specify a delay after which the job
+     * will be eligible for execution. This value is not set if the job recurs periodically.
      */
     public long getMinLatencyMillis() {
         return minLatencyMillis;
     }
 
     /**
-     * See {@link Builder#setOverrideDeadline(long)}. This value is not set if the task recurs
+     * See {@link Builder#setOverrideDeadline(long)}. This value is not set if the job recurs
      * periodically.
      */
     public long getMaxExecutionDelayMillis() {
@@ -138,23 +138,23 @@
     }
 
     /**
-     * Track whether this task will repeat with a given period.
+     * Track whether this job will repeat with a given period.
      */
     public boolean isPeriodic() {
         return isPeriodic;
     }
 
     /**
-     * Set to the interval between occurrences of this task. This value is <b>not</b> set if the
-     * task does not recur periodically.
+     * Set to the interval between occurrences of this job. This value is <b>not</b> set if the
+     * job does not recur periodically.
      */
     public long getIntervalMillis() {
         return intervalMillis;
     }
 
     /**
-     * The amount of time the TaskManager will wait before rescheduling a failed task. This value
-     * will be increased depending on the backoff policy specified at task creation time. Defaults
+     * The amount of time the JobScheduler will wait before rescheduling a failed job. This value
+     * will be increased depending on the backoff policy specified at job creation time. Defaults
      * to 5 seconds.
      */
     public long getInitialBackoffMillis() {
@@ -162,7 +162,7 @@
     }
 
     /**
-     * See {@link android.app.task.Task.BackoffPolicy} for an explanation of the values this field
+     * See {@link android.app.job.JobInfo.BackoffPolicy} for an explanation of the values this field
      * can take. This defaults to exponential.
      */
     public int getBackoffPolicy() {
@@ -187,8 +187,8 @@
         return hasLateConstraint;
     }
 
-    private Task(Parcel in) {
-        taskId = in.readInt();
+    private JobInfo(Parcel in) {
+        jobId = in.readInt();
         extras = in.readPersistableBundle();
         service = in.readParcelable(null);
         requireCharging = in.readInt() == 1;
@@ -204,10 +204,10 @@
         hasLateConstraint = in.readInt() == 1;
     }
 
-    private Task(Task.Builder b) {
-        taskId = b.mTaskId;
+    private JobInfo(JobInfo.Builder b) {
+        jobId = b.mJobId;
         extras = b.mExtras;
-        service = b.mTaskService;
+        service = b.mJobService;
         requireCharging = b.mRequiresCharging;
         requireDeviceIdle = b.mRequiresDeviceIdle;
         networkCapabilities = b.mNetworkCapabilities;
@@ -228,7 +228,7 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(taskId);
+        out.writeInt(jobId);
         out.writePersistableBundle(extras);
         out.writeParcelable(service, flags);
         out.writeInt(requireCharging ? 1 : 0);
@@ -244,23 +244,23 @@
         out.writeInt(hasLateConstraint ? 1 : 0);
     }
 
-    public static final Creator<Task> CREATOR = new Creator<Task>() {
+    public static final Creator<JobInfo> CREATOR = new Creator<JobInfo>() {
         @Override
-        public Task createFromParcel(Parcel in) {
-            return new Task(in);
+        public JobInfo createFromParcel(Parcel in) {
+            return new JobInfo(in);
         }
 
         @Override
-        public Task[] newArray(int size) {
-            return new Task[size];
+        public JobInfo[] newArray(int size) {
+            return new JobInfo[size];
         }
     };
 
-    /** Builder class for constructing {@link Task} objects. */
+    /** Builder class for constructing {@link JobInfo} objects. */
     public static final class Builder {
-        private int mTaskId;
+        private int mJobId;
         private PersistableBundle mExtras = PersistableBundle.EMPTY;
-        private ComponentName mTaskService;
+        private ComponentName mJobService;
         // Requirements.
         private boolean mRequiresCharging;
         private boolean mRequiresDeviceIdle;
@@ -280,15 +280,15 @@
         private boolean mBackoffPolicySet = false;
 
         /**
-         * @param taskId Application-provided id for this task. Subsequent calls to cancel, or
-         *               tasks created with the same taskId, will update the pre-existing task with
+         * @param jobId Application-provided id for this job. Subsequent calls to cancel, or
+         *               jobs created with the same jobId, will update the pre-existing job with
          *               the same id.
-         * @param taskService The endpoint that you implement that will receive the callback from the
-         *            TaskManager.
+         * @param jobService The endpoint that you implement that will receive the callback from the
+         *            JobScheduler.
          */
-        public Builder(int taskId, ComponentName taskService) {
-            mTaskService = taskService;
-            mTaskId = taskId;
+        public Builder(int jobId, ComponentName jobService) {
+            mJobService = jobService;
+            mJobId = jobId;
         }
 
         /**
@@ -302,10 +302,10 @@
 
         /**
          * Set some description of the kind of network capabilities you would like to have. This
-         * will be a parameter defined in {@link android.app.task.Task.NetworkType}.
+         * will be a parameter defined in {@link android.app.job.JobInfo.NetworkType}.
          * Not calling this function means the network is not necessary.
          * Bear in mind that calling this function defines network as a strict requirement for your
-         * task if the network requested is not available your task will never run. See
+         * job if the network requested is not available your job will never run. See
          * {@link #setOverrideDeadline(long)} to change this behaviour.
          */
         public Builder setRequiredNetworkCapabilities(int networkCapabilities) {
@@ -313,10 +313,10 @@
             return this;
         }
 
-        /*
-         * Specify that to run this task, the device needs to be plugged in. This defaults to
+        /**
+         * Specify that to run this job, the device needs to be plugged in. This defaults to
          * false.
-         * @param requireCharging Whether or not the device is plugged in.
+         * @param requiresCharging Whether or not the device is plugged in.
          */
         public Builder setRequiresCharging(boolean requiresCharging) {
             mRequiresCharging = requiresCharging;
@@ -324,11 +324,11 @@
         }
 
         /**
-         * Specify that to run, the task needs the device to be in idle mode. This defaults to
+         * Specify that to run, the job needs the device to be in idle mode. This defaults to
          * false.
          * <p>Idle mode is a loose definition provided by the system, which means that the device
          * is not in use, and has not been in use for some time. As such, it is a good time to
-         * perform resource heavy tasks. Bear in mind that battery usage will still be attributed
+         * perform resource heavy jobs. Bear in mind that battery usage will still be attributed
          * to your application, and surfaced to the user in battery stats.</p>
          * @param requiresDeviceIdle Whether or not the device need be within an idle maintenance
          *                           window.
@@ -339,17 +339,17 @@
         }
 
         /**
-         * Specify that this task should recur with the provided interval, not more than once per
-         * period. You have no control over when within this interval this task will be executed,
+         * Specify that this job should recur with the provided interval, not more than once per
+         * period. You have no control over when within this interval this job will be executed,
          * only the guarantee that it will be executed at most once within this interval.
-         * A periodic task will be repeated until the phone is turned off, however it will only be
+         * A periodic job will be repeated until the phone is turned off, however it will only be
          * persisted beyond boot if the client app has declared the
          * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission. You can schedule
-         * periodic tasks without this permission, they simply will cease to exist after the phone
+         * periodic jobs without this permission, they simply will cease to exist after the phone
          * restarts.
          * Setting this function on the builder with {@link #setMinimumLatency(long)} or
          * {@link #setOverrideDeadline(long)} will result in an error.
-         * @param intervalMillis Millisecond interval for which this task will repeat.
+         * @param intervalMillis Millisecond interval for which this job will repeat.
          */
         public Builder setPeriodic(long intervalMillis) {
             mIsPeriodic = true;
@@ -359,11 +359,11 @@
         }
 
         /**
-         * Specify that this task should be delayed by the provided amount of time.
-         * Because it doesn't make sense setting this property on a periodic task, doing so will
+         * Specify that this job should be delayed by the provided amount of time.
+         * Because it doesn't make sense setting this property on a periodic job, doing so will
          * throw an {@link java.lang.IllegalArgumentException} when
-         * {@link android.app.task.Task.Builder#build()} is called.
-         * @param minLatencyMillis Milliseconds before which this task will not be considered for
+         * {@link android.app.job.JobInfo.Builder#build()} is called.
+         * @param minLatencyMillis Milliseconds before which this job will not be considered for
          *                         execution.
          */
         public Builder setMinimumLatency(long minLatencyMillis) {
@@ -373,11 +373,11 @@
         }
 
         /**
-         * Set deadline which is the maximum scheduling latency. The task will be run by this
+         * Set deadline which is the maximum scheduling latency. The job will be run by this
          * deadline even if other requirements are not met. Because it doesn't make sense setting
-         * this property on a periodic task, doing so will throw an
+         * this property on a periodic job, doing so will throw an
          * {@link java.lang.IllegalArgumentException} when
-         * {@link android.app.task.Task.Builder#build()} is called.
+         * {@link android.app.job.JobInfo.Builder#build()} is called.
          */
         public Builder setOverrideDeadline(long maxExecutionDelayMillis) {
             mMaxExecutionDelayMillis = maxExecutionDelayMillis;
@@ -389,13 +389,13 @@
          * Set up the back-off/retry policy.
          * This defaults to some respectable values: {5 seconds, Exponential}. We cap back-off at
          * 1hr.
-         * Note that trying to set a backoff criteria for a task with
+         * Note that trying to set a backoff criteria for a job with
          * {@link #setRequiresDeviceIdle(boolean)} will throw an exception when you call build().
-         * This is because back-off typically does not make sense for these types of tasks. See
-         * {@link android.app.task.TaskService#taskFinished(android.app.task.TaskParams, boolean)}
-         * for more description of the return value for the case of a task executing while in idle
+         * This is because back-off typically does not make sense for these types of jobs. See
+         * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
+         * for more description of the return value for the case of a job executing while in idle
          * mode.
-         * @param initialBackoffMillis Millisecond time interval to wait initially when task has
+         * @param initialBackoffMillis Millisecond time interval to wait initially when job has
          *                             failed.
          * @param backoffPolicy is one of {@link BackoffPolicy}
          */
@@ -407,25 +407,25 @@
         }
 
         /**
-         * @return The task object to hand to the TaskManager. This object is immutable.
+         * @return The job object to hand to the JobScheduler. This object is immutable.
          */
-        public Task build() {
+        public JobInfo build() {
             mExtras = new PersistableBundle(mExtras);  // Make our own copy.
-            // Check that a deadline was not set on a periodic task.
+            // Check that a deadline was not set on a periodic job.
             if (mIsPeriodic && (mMaxExecutionDelayMillis != 0L)) {
                 throw new IllegalArgumentException("Can't call setOverrideDeadline() on a " +
-                        "periodic task.");
+                        "periodic job.");
             }
             if (mIsPeriodic && (mMinLatencyMillis != 0L)) {
                 throw new IllegalArgumentException("Can't call setMinimumLatency() on a " +
-                        "periodic task");
+                        "periodic job");
             }
             if (mBackoffPolicySet && mRequiresDeviceIdle) {
-                throw new IllegalArgumentException("An idle mode task will not respect any" +
+                throw new IllegalArgumentException("An idle mode job will not respect any" +
                         " back-off policy, so calling setBackoffCriteria with" +
                         " setRequiresDeviceIdle is an error.");
             }
-            return new Task(this);
+            return new JobInfo(this);
         }
     }
 
diff --git a/core/java/android/app/task/TaskParams.aidl b/core/java/android/app/job/JobParameters.aidl
similarity index 91%
rename from core/java/android/app/task/TaskParams.aidl
rename to core/java/android/app/job/JobParameters.aidl
index 9b25855..e7551b9 100644
--- a/core/java/android/app/task/TaskParams.aidl
+++ b/core/java/android/app/job/JobParameters.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.app.task;
+package android.app.job;
 
-parcelable TaskParams;
\ No newline at end of file
+parcelable JobParameters;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
new file mode 100644
index 0000000..724856a
--- /dev/null
+++ b/core/java/android/app/job/JobParameters.java
@@ -0,0 +1,93 @@
+/*
+ * 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.job;
+
+import android.app.job.IJobCallback;
+import android.app.job.IJobCallback.Stub;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+
+/**
+ * Contains the parameters used to configure/identify your job. You do not create this object
+ * yourself, instead it is handed in to your application by the System.
+ */
+public class JobParameters implements Parcelable {
+
+    private final int jobId;
+    private final PersistableBundle extras;
+    private final IBinder callback;
+
+    /** @hide */
+    public JobParameters(int jobId, PersistableBundle extras, IBinder callback) {
+        this.jobId = jobId;
+        this.extras = extras;
+        this.callback = callback;
+    }
+
+    /**
+     * @return The unique id of this job, specified at creation time.
+     */
+    public int getJobId() {
+        return jobId;
+    }
+
+    /**
+     * @return The extras you passed in when constructing this job with
+     * {@link android.app.job.JobInfo.Builder#setExtras(android.os.PersistableBundle)}. This will
+     * never be null. If you did not set any extras this will be an empty bundle.
+     */
+    public PersistableBundle getExtras() {
+        return extras;
+    }
+
+    /** @hide */
+    public IJobCallback getCallback() {
+        return IJobCallback.Stub.asInterface(callback);
+    }
+
+    private JobParameters(Parcel in) {
+        jobId = in.readInt();
+        extras = in.readPersistableBundle();
+        callback = in.readStrongBinder();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(jobId);
+        dest.writePersistableBundle(extras);
+        dest.writeStrongBinder(callback);
+    }
+
+    public static final Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
+        @Override
+        public JobParameters createFromParcel(Parcel in) {
+            return new JobParameters(in);
+        }
+
+        @Override
+        public JobParameters[] newArray(int size) {
+            return new JobParameters[size];
+        }
+    };
+}
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
new file mode 100644
index 0000000..7fe192c
--- /dev/null
+++ b/core/java/android/app/job/JobScheduler.java
@@ -0,0 +1,72 @@
+/*
+ * 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.job;
+
+import java.util.List;
+
+import android.content.Context;
+
+/**
+ * Class for scheduling various types of jobs with the scheduling framework on the device.
+ *
+ * <p>You do not
+ * instantiate this class directly; instead, retrieve it through
+ * {@link android.content.Context#getSystemService
+ * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
+ */
+public abstract class JobScheduler {
+    /**
+     * Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur
+     * if the run-time for your job is too short, or perhaps the system can't resolve the
+     * requisite {@link JobService} in your package.
+     */
+    public static final int RESULT_FAILURE = 0;
+    /**
+     * Returned from {@link #schedule(JobInfo)} if this application has made too many requests for
+     * work over too short a time.
+     */
+    // TODO: Determine if this is necessary.
+    public static final int RESULT_SUCCESS = 1;
+
+    /**
+     * @param job The job you wish scheduled. See
+     * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
+     * you can schedule.
+     * @return If >0, this int returns the jobId of the successfully scheduled job.
+     * Otherwise you have to compare the return value to the error codes defined in this class.
+     */
+    public abstract int schedule(JobInfo job);
+
+    /**
+     * Cancel a job that is pending in the JobScheduler.
+     * @param jobId unique identifier for this job. Obtain this value from the jobs returned by
+     * {@link #getAllPendingJobs()}.
+     * @return
+     */
+    public abstract void cancel(int jobId);
+
+    /**
+     * Cancel all jobs that have been registered with the JobScheduler by this package.
+     */
+    public abstract void cancelAll();
+
+    /**
+     * @return a list of all the jobs registered by this package that have not yet been executed.
+     */
+    public abstract List<JobInfo> getAllPendingJobs();
+
+}
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
new file mode 100644
index 0000000..eea0268
--- /dev/null
+++ b/core/java/android/app/job/JobService.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.job;
+
+import android.app.Service;
+import android.app.job.IJobCallback;
+import android.app.job.IJobService;
+import android.app.job.IJobService.Stub;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * <p>Entry point for the callback from the {@link android.app.job.JobScheduler}.</p>
+ * <p>This is the base class that handles asynchronous requests that were previously scheduled. You
+ * are responsible for overriding {@link JobService#onStartJob(JobParameters)}, which is where
+ * you will implement your job logic.</p>
+ * <p>This service executes each incoming job on a {@link android.os.Handler} running on your
+ * application's main thread. This means that you <b>must</b> offload your execution logic to
+ * another thread/handler/{@link android.os.AsyncTask} of your choosing. Not doing so will result
+ * in blocking any future callbacks from the JobManager - specifically
+ * {@link #onStopJob(android.app.job.JobParameters)}, which is meant to inform you that the
+ * scheduling requirements are no longer being met.</p>
+ */
+public abstract class JobService extends Service {
+    private static final String TAG = "JobService";
+
+    /**
+     * Job services must be protected with this permission:
+     *
+     * <pre class="prettyprint">
+     *     <service android:name="MyJobService"
+     *              android:permission="android.permission.BIND_JOB_SERVICE" >
+     *         ...
+     *     </service>
+     * </pre>
+     *
+     * <p>If a job service is declared in the manifest but not protected with this
+     * permission, that service will be ignored by the OS.
+     */
+    public static final String PERMISSION_BIND =
+            "android.permission.BIND_JOB_SERVICE";
+
+    /**
+     * Identifier for a message that will result in a call to
+     * {@link #onStartJob(android.app.job.JobParameters)}.
+     */
+    private final int MSG_EXECUTE_JOB = 0;
+    /**
+     * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
+     */
+    private final int MSG_STOP_JOB = 1;
+    /**
+     * Message that the client has completed execution of this job.
+     */
+    private final int MSG_JOB_FINISHED = 2;
+
+    /** Lock object for {@link #mHandler}. */
+    private final Object mHandlerLock = new Object();
+
+    /**
+     * Handler we post jobs to. Responsible for calling into the client logic, and handling the
+     * callback to the system.
+     */
+    @GuardedBy("mHandlerLock")
+    JobHandler mHandler;
+
+    /** Binder for this service. */
+    IJobService mBinder = new IJobService.Stub() {
+        @Override
+        public void startJob(JobParameters jobParams) {
+            ensureHandler();
+            Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);
+            m.sendToTarget();
+        }
+        @Override
+        public void stopJob(JobParameters jobParams) {
+            ensureHandler();
+            Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);
+            m.sendToTarget();
+        }
+    };
+
+    /** @hide */
+    void ensureHandler() {
+        synchronized (mHandlerLock) {
+            if (mHandler == null) {
+                mHandler = new JobHandler(getMainLooper());
+            }
+        }
+    }
+
+    /**
+     * Runs on application's main thread - callbacks are meant to offboard work to some other
+     * (app-specified) mechanism.
+     * @hide
+     */
+    class JobHandler extends Handler {
+        JobHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final JobParameters params = (JobParameters) msg.obj;
+            switch (msg.what) {
+                case MSG_EXECUTE_JOB:
+                    try {
+                        boolean workOngoing = JobService.this.onStartJob(params);
+                        ackStartMessage(params, workOngoing);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error while executing job: " + params.getJobId());
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_STOP_JOB:
+                    try {
+                        boolean ret = JobService.this.onStopJob(params);
+                        ackStopMessage(params, ret);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Application unable to handle onStopJob.", e);
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_JOB_FINISHED:
+                    final boolean needsReschedule = (msg.arg2 == 1);
+                    IJobCallback callback = params.getCallback();
+                    if (callback != null) {
+                        try {
+                            callback.jobFinished(params.getJobId(), needsReschedule);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error reporting job finish to system: binder has gone" +
+                                    "away.");
+                        }
+                    } else {
+                        Log.e(TAG, "finishJob() called for a nonexistent job id.");
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unrecognised message received.");
+                    break;
+            }
+        }
+
+        private void ackStartMessage(JobParameters params, boolean workOngoing) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                     callback.acknowledgeStartMessage(jobId, workOngoing);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for starting job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+
+        private void ackStopMessage(JobParameters params, boolean reschedule) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                    callback.acknowledgeStopMessage(jobId, reschedule);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for stopping job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+    }
+
+    /** @hide */
+    public final IBinder onBind(Intent intent) {
+        return mBinder.asBinder();
+    }
+
+    /**
+     * Override this method with the callback logic for your job. Any such logic needs to be
+     * performed on a separate thread, as this function is executed on your application's main
+     * thread.
+     *
+     * @param params Parameters specifying info about this job, including the extras bundle you
+     *               optionally provided at job-creation time.
+     * @return True if your service needs to process the work (on a separate thread). False if
+     * there's no more work to be done for this job.
+     */
+    public abstract boolean onStartJob(JobParameters params);
+
+    /**
+     * This method is called if the system has determined that you must stop execution of your job
+     * even before you've had a chance to call {@link #jobFinished(JobParameters, boolean)}.
+     *
+     * <p>This will happen if the requirements specified at schedule time are no longer met. For
+     * example you may have requested WiFi with
+     * {@link android.app.job.JobInfo.Builder#setRequiredNetworkCapabilities(int)}, yet while your
+     * job was executing the user toggled WiFi. Another example is if you had specified
+     * {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
+     * idle maintenance window. You are solely responsible for the behaviour of your application
+     * upon receipt of this message; your app will likely start to misbehave if you ignore it. One
+     * immediate repercussion is that the system will cease holding a wakelock for you.</p>
+     *
+     * @param params Parameters specifying info about this job.
+     * @return True to indicate to the JobManager whether you'd like to reschedule this job based
+     * on the retry criteria provided at job creation-time. False to drop the job. Regardless of
+     * the value returned, your job must stop executing.
+     */
+    public abstract boolean onStopJob(JobParameters params);
+
+    /**
+     * Callback to inform the JobManager you've finished executing. This can be called from any
+     * thread, as it will ultimately be run on your application's main thread. When the system
+     * receives this message it will release the wakelock being held.
+     * <p>
+     *     You can specify post-execution behaviour to the scheduler here with
+     *     <code>needsReschedule </code>. This will apply a back-off timer to your job based on
+     *     the default, or what was set with
+     *     {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}. The original
+     *     requirements are always honoured even for a backed-off job. Note that a job running in
+     *     idle mode will not be backed-off. Instead what will happen is the job will be re-added
+     *     to the queue and re-executed within a future idle maintenance window.
+     * </p>
+     *
+     * @param params Parameters specifying system-provided info about this job, this was given to
+     *               your application in {@link #onStartJob(JobParameters)}.
+     * @param needsReschedule True if this job is complete, false if you want the JobManager to
+     *                        reschedule you.
+     */
+    public final void jobFinished(JobParameters params, boolean needsReschedule) {
+        ensureHandler();
+        Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
+        m.arg2 = needsReschedule ? 1 : 0;
+        m.sendToTarget();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/app/maintenance/package.html b/core/java/android/app/maintenance/package.html
new file mode 100644
index 0000000..1c9bf9d
--- /dev/null
+++ b/core/java/android/app/maintenance/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+    {@hide}
+</body>
+</html>
diff --git a/core/java/android/app/task/ITaskCallback.aidl b/core/java/android/app/task/ITaskCallback.aidl
deleted file mode 100644
index d8a32fd..0000000
--- a/core/java/android/app/task/ITaskCallback.aidl
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.task;
-
-import android.app.task.ITaskService;
-import android.app.task.TaskParams;
-
-/**
- * The server side of the TaskManager IPC protocols.  The app-side implementation
- * invokes on this interface to indicate completion of the (asynchronous) instructions
- * issued by the server.
- *
- * In all cases, the 'who' parameter is the caller's service binder, used to track
- * which Task Service instance is reporting.
- *
- * {@hide}
- */
-interface ITaskCallback {
-    /**
-     * Immediate callback to the system after sending a start signal, used to quickly detect ANR.
-     *
-     * @param taskId Unique integer used to identify this task.
-     * @param ongoing True to indicate that the client is processing the task. False if the task is
-     * complete
-     */
-    void acknowledgeStartMessage(int taskId, boolean ongoing);
-    /**
-     * Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
-     *
-     * @param taskId Unique integer used to identify this task.
-     * @param rescheulde Whether or not to reschedule this task.
-     */
-    void acknowledgeStopMessage(int taskId, boolean reschedule);
-    /*
-     * Tell the task manager that the client is done with its execution, so that it can go on to
-     * the next one and stop attributing wakelock time to us etc.
-     *
-     * @param taskId Unique integer used to identify this task.
-     * @param reschedule Whether or not to reschedule this task.
-     */
-    void taskFinished(int taskId, boolean reschedule);
-}
diff --git a/core/java/android/app/task/TaskManager.java b/core/java/android/app/task/TaskManager.java
deleted file mode 100644
index 00f57da..0000000
--- a/core/java/android/app/task/TaskManager.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.app.task;
-
-import java.util.List;
-
-import android.content.Context;
-
-/**
- * Class for scheduling various types of tasks with the scheduling framework on the device.
- *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TASK_SERVICE)}.
- */
-public abstract class TaskManager {
-    /*
-     * Returned from {@link #schedule(Task)} when an invalid parameter was supplied. This can occur
-     * if the run-time for your task is too short, or perhaps the system can't resolve the
-     * requisite {@link TaskService} in your package.
-     */
-    public static final int RESULT_FAILURE = 0;
-    /**
-     * Returned from {@link #schedule(Task)} if this application has made too many requests for
-     * work over too short a time.
-     */
-    // TODO: Determine if this is necessary.
-    public static final int RESULT_SUCCESS = 1;
-
-    /**
-     * @param task The task you wish scheduled. See
-     * {@link android.app.task.Task.Builder Task.Builder} for more detail on the sorts of tasks
-     * you can schedule.
-     * @return If >0, this int returns the taskId of the successfully scheduled task.
-     * Otherwise you have to compare the return value to the error codes defined in this class.
-     */
-    public abstract int schedule(Task task);
-
-    /**
-     * Cancel a task that is pending in the TaskManager.
-     * @param taskId unique identifier for this task. Obtain this value from the tasks returned by
-     * {@link #getAllPendingTasks()}.
-     * @return
-     */
-    public abstract void cancel(int taskId);
-
-    /**
-     * Cancel all tasks that have been registered with the TaskManager by this package.
-     */
-    public abstract void cancelAll();
-
-    /**
-     * @return a list of all the tasks registered by this package that have not yet been executed.
-     */
-    public abstract List<Task> getAllPendingTasks();
-
-}
diff --git a/core/java/android/app/task/TaskParams.java b/core/java/android/app/task/TaskParams.java
deleted file mode 100644
index f4908c6..0000000
--- a/core/java/android/app/task/TaskParams.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.app.task;
-
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PersistableBundle;
-
-/**
- * Contains the parameters used to configure/identify your task. You do not create this object
- * yourself, instead it is handed in to your application by the System.
- */
-public class TaskParams implements Parcelable {
-
-    private final int taskId;
-    private final PersistableBundle extras;
-    private final IBinder callback;
-
-    /** @hide */
-    public TaskParams(int taskId, PersistableBundle extras, IBinder callback) {
-        this.taskId = taskId;
-        this.extras = extras;
-        this.callback = callback;
-    }
-
-    /**
-     * @return The unique id of this task, specified at creation time.
-     */
-    public int getTaskId() {
-        return taskId;
-    }
-
-    /**
-     * @return The extras you passed in when constructing this task with
-     * {@link android.app.task.Task.Builder#setExtras(android.os.PersistableBundle)}. This will
-     * never be null. If you did not set any extras this will be an empty bundle.
-     */
-    public PersistableBundle getExtras() {
-        return extras;
-    }
-
-    /** @hide */
-    public ITaskCallback getCallback() {
-        return ITaskCallback.Stub.asInterface(callback);
-    }
-
-    private TaskParams(Parcel in) {
-        taskId = in.readInt();
-        extras = in.readPersistableBundle();
-        callback = in.readStrongBinder();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(taskId);
-        dest.writePersistableBundle(extras);
-        dest.writeStrongBinder(callback);
-    }
-
-    public static final Creator<TaskParams> CREATOR = new Creator<TaskParams>() {
-        @Override
-        public TaskParams createFromParcel(Parcel in) {
-            return new TaskParams(in);
-        }
-
-        @Override
-        public TaskParams[] newArray(int size) {
-            return new TaskParams[size];
-        }
-    };
-}
diff --git a/core/java/android/app/task/TaskService.java b/core/java/android/app/task/TaskService.java
deleted file mode 100644
index 8ce4484..0000000
--- a/core/java/android/app/task/TaskService.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.app.task;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-/**
- * <p>Entry point for the callback from the {@link android.app.task.TaskManager}.</p>
- * <p>This is the base class that handles asynchronous requests that were previously scheduled. You
- * are responsible for overriding {@link TaskService#onStartTask(TaskParams)}, which is where
- * you will implement your task logic.</p>
- * <p>This service executes each incoming task on a {@link android.os.Handler} running on your
- * application's main thread. This means that you <b>must</b> offload your execution logic to
- * another thread/handler/{@link android.os.AsyncTask} of your choosing. Not doing so will result
- * in blocking any future callbacks from the TaskManager - specifically
- * {@link #onStopTask(android.app.task.TaskParams)}, which is meant to inform you that the
- * scheduling requirements are no longer being met.</p>
- */
-public abstract class TaskService extends Service {
-    private static final String TAG = "TaskService";
-
-    /**
-     * Task services must be protected with this permission:
-     *
-     * <pre class="prettyprint">
-     *     <service android:name="MyTaskService"
-     *              android:permission="android.permission.BIND_TASK_SERVICE" >
-     *         ...
-     *     </service>
-     * </pre>
-     *
-     * <p>If a task service is declared in the manifest but not protected with this
-     * permission, that service will be ignored by the OS.
-     */
-    public static final String PERMISSION_BIND =
-            "android.permission.BIND_TASK_SERVICE";
-
-    /**
-     * Identifier for a message that will result in a call to
-     * {@link #onStartTask(android.app.task.TaskParams)}.
-     */
-    private final int MSG_EXECUTE_TASK = 0;
-    /**
-     * Message that will result in a call to {@link #onStopTask(android.app.task.TaskParams)}.
-     */
-    private final int MSG_STOP_TASK = 1;
-    /**
-     * Message that the client has completed execution of this task.
-     */
-    private final int MSG_TASK_FINISHED = 2;
-
-    /** Lock object for {@link #mHandler}. */
-    private final Object mHandlerLock = new Object();
-
-    /**
-     * Handler we post tasks to. Responsible for calling into the client logic, and handling the
-     * callback to the system.
-     */
-    @GuardedBy("mHandlerLock")
-    TaskHandler mHandler;
-
-    /** Binder for this service. */
-    ITaskService mBinder = new ITaskService.Stub() {
-        @Override
-        public void startTask(TaskParams taskParams) {
-            ensureHandler();
-            Message m = Message.obtain(mHandler, MSG_EXECUTE_TASK, taskParams);
-            m.sendToTarget();
-        }
-        @Override
-        public void stopTask(TaskParams taskParams) {
-            ensureHandler();
-            Message m = Message.obtain(mHandler, MSG_STOP_TASK, taskParams);
-            m.sendToTarget();
-        }
-    };
-
-    /** @hide */
-    void ensureHandler() {
-        synchronized (mHandlerLock) {
-            if (mHandler == null) {
-                mHandler = new TaskHandler(getMainLooper());
-            }
-        }
-    }
-
-    /**
-     * Runs on application's main thread - callbacks are meant to offboard work to some other
-     * (app-specified) mechanism.
-     * @hide
-     */
-    class TaskHandler extends Handler {
-        TaskHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final TaskParams params = (TaskParams) msg.obj;
-            switch (msg.what) {
-                case MSG_EXECUTE_TASK:
-                    try {
-                        boolean workOngoing = TaskService.this.onStartTask(params);
-                        ackStartMessage(params, workOngoing);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error while executing task: " + params.getTaskId());
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_STOP_TASK:
-                    try {
-                        boolean ret = TaskService.this.onStopTask(params);
-                        ackStopMessage(params, ret);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Application unable to handle onStopTask.", e);
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_TASK_FINISHED:
-                    final boolean needsReschedule = (msg.arg2 == 1);
-                    ITaskCallback callback = params.getCallback();
-                    if (callback != null) {
-                        try {
-                            callback.taskFinished(params.getTaskId(), needsReschedule);
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error reporting task finish to system: binder has gone" +
-                                    "away.");
-                        }
-                    } else {
-                        Log.e(TAG, "finishTask() called for a nonexistent task id.");
-                    }
-                    break;
-                default:
-                    Log.e(TAG, "Unrecognised message received.");
-                    break;
-            }
-        }
-
-        private void ackStartMessage(TaskParams params, boolean workOngoing) {
-            final ITaskCallback callback = params.getCallback();
-            final int taskId = params.getTaskId();
-            if (callback != null) {
-                try {
-                     callback.acknowledgeStartMessage(taskId, workOngoing);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for starting task.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a task that has already been processed.");
-                }
-            }
-        }
-
-        private void ackStopMessage(TaskParams params, boolean reschedule) {
-            final ITaskCallback callback = params.getCallback();
-            final int taskId = params.getTaskId();
-            if (callback != null) {
-                try {
-                    callback.acknowledgeStopMessage(taskId, reschedule);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for stopping task.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a task that has already been processed.");
-                }
-            }
-        }
-    }
-
-    /** @hide */
-    public final IBinder onBind(Intent intent) {
-        return mBinder.asBinder();
-    }
-
-    /**
-     * Override this method with the callback logic for your task. Any such logic needs to be
-     * performed on a separate thread, as this function is executed on your application's main
-     * thread.
-     *
-     * @param params Parameters specifying info about this task, including the extras bundle you
-     *               optionally provided at task-creation time.
-     * @return True if your service needs to process the work (on a separate thread). False if
-     * there's no more work to be done for this task.
-     */
-    public abstract boolean onStartTask(TaskParams params);
-
-    /**
-     * This method is called if the system has determined that you must stop execution of your task
-     * even before you've had a chance to call {@link #taskFinished(TaskParams, boolean)}.
-     *
-     * <p>This will happen if the requirements specified at schedule time are no longer met. For
-     * example you may have requested WiFi with
-     * {@link android.app.task.Task.Builder#setRequiredNetworkCapabilities(int)}, yet while your
-     * task was executing the user toggled WiFi. Another example is if you had specified
-     * {@link android.app.task.Task.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
-     * idle maintenance window. You are solely responsible for the behaviour of your application
-     * upon receipt of this message; your app will likely start to misbehave if you ignore it. One
-     * immediate repercussion is that the system will cease holding a wakelock for you.</p>
-     *
-     * @param params Parameters specifying info about this task.
-     * @return True to indicate to the TaskManager whether you'd like to reschedule this task based
-     * on the retry criteria provided at task creation-time. False to drop the task. Regardless of
-     * the value returned, your task must stop executing.
-     */
-    public abstract boolean onStopTask(TaskParams params);
-
-    /**
-     * Callback to inform the TaskManager you've finished executing. This can be called from any
-     * thread, as it will ultimately be run on your application's main thread. When the system
-     * receives this message it will release the wakelock being held.
-     * <p>
-     *     You can specify post-execution behaviour to the scheduler here with
-     *     <code>needsReschedule </code>. This will apply a back-off timer to your task based on
-     *     the default, or what was set with
-     *     {@link android.app.task.Task.Builder#setBackoffCriteria(long, int)}. The original
-     *     requirements are always honoured even for a backed-off task. Note that a task running in
-     *     idle mode will not be backed-off. Instead what will happen is the task will be re-added
-     *     to the queue and re-executed within a future idle maintenance window.
-     * </p>
-     *
-     * @param params Parameters specifying system-provided info about this task, this was given to
-     *               your application in {@link #onStartTask(TaskParams)}.
-     * @param needsReschedule True if this task is complete, false if you want the TaskManager to
-     *                        reschedule you.
-     */
-    public final void taskFinished(TaskParams params, boolean needsReschedule) {
-        ensureHandler();
-        Message m = Message.obtain(mHandler, MSG_TASK_FINISHED, params);
-        m.arg2 = needsReschedule ? 1 : 0;
-        m.sendToTarget();
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9fe9bce..cdcfd2e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2059,7 +2059,7 @@
             PRINT_SERVICE,
             MEDIA_SESSION_SERVICE,
             BATTERY_SERVICE,
-            TASK_SERVICE,
+            JOB_SCHEDULER_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -2116,8 +2116,8 @@
      * <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
      * <dt> {@link #BATTERY_SERVICE} ("batterymanager")
      * <dd> A {@link android.os.BatteryManager} for managing battery state
-     * <dt> {@link #TASK_SERVICE} ("taskmanager")
-     * <dd>  A {@link android.app.task.TaskManager} for managing scheduled tasks
+     * <dt> {@link #JOB_SCHEDULER_SERVICE} ("taskmanager")
+     * <dd>  A {@link android.app.job.JobScheduler} for managing scheduled tasks
      * </dl>
      *
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -2171,8 +2171,8 @@
      * @see android.app.DownloadManager
      * @see #BATTERY_SERVICE
      * @see android.os.BatteryManager
-     * @see #TASK_SERVICE
-     * @see android.app.task.TaskManager
+     * @see #JOB_SCHEDULER_SERVICE
+     * @see android.app.job.JobScheduler
      */
     public abstract Object getSystemService(@ServiceName @NonNull String name);
 
@@ -2761,12 +2761,12 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
-     * android.app.task.TaskManager} instance for managing occasional
+     * android.app.job.JobScheduler} instance for managing occasional
      * background tasks.
      * @see #getSystemService
-     * @see android.app.task.TaskManager
+     * @see android.app.job.JobScheduler
      */
-    public static final String TASK_SERVICE = "task";
+    public static final String JOB_SCHEDULER_SERVICE = "jobscheduler";
 
     /**
      * Determine whether the given permission is allowed for a particular
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 5fd0f9b..d98bdc2 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -29,19 +29,19 @@
  *
  * <p>Creating a session is an expensive operation and can take several hundred milliseconds, since
  * it requires configuring the camera device's internal pipelines and allocating memory buffers for
- * sending images to the desired targets. While
- * {@link CameraDevice#createCaptureSession createCaptureSession} will provide a
- * CameraCaptureSession object immediately, configuration won't be complete until the
- * {@link CameraCaptureSession.StateListener#onConfigured onConfigured} callback is called for the
- * first time. If configuration cannot be completed, then the
+ * sending images to the desired targets. Therefore the setup is done asynchronously, and
+ * {@link CameraDevice#createCaptureSession createCaptureSession} will send the ready-to-use
+ * CameraCaptureSession to the provided listener's
+ * {@link CameraCaptureSession.StateListener#onConfigured onConfigured} callback. If configuration
+ * cannot be completed, then the
  * {@link CameraCaptureSession.StateListener#onConfigureFailed onConfigureFailed} is called, and the
  * session will not become active.</p>
- *
+ *<!--
  * <p>Any capture requests (repeating or non-repeating) submitted before the session is ready will
  * be queued up and will begin capture once the session becomes ready. In case the session cannot be
  * configured and {@link StateListener#onConfigureFailed onConfigureFailed} is called, all queued
  * capture requests are discarded.</p>
- *
+ *-->
  * <p>If a new session is created by the camera device, then the previous session is closed, and its
  * associated {@link StateListener#onClosed onClosed} callback will be invoked.  All
  * of the session methods will throw an IllegalStateException if called once the session is
@@ -166,10 +166,6 @@
      * capture request will be processed before any further repeating
      * requests are processed.<p>
      *
-     * <p>Repeating requests are a simple way for an application to maintain a
-     * preview or other continuous stream of frames, without having to submit
-     * requests through {@link #capture} at video rates.</p>
-     *
      * <p>To stop the repeating capture, call {@link #stopRepeating}. Calling
      * {@link #abortCaptures} will also clear the request.</p>
      *
@@ -323,7 +319,7 @@
      *
      * @see #setRepeatingRequest
      * @see #setRepeatingBurst
-     * @see #configureOutputs
+     * @see CameraDevice#createCaptureSession
      */
     public abstract void abortCaptures() throws CameraAccessException;
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 08cfc87..ff56720 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -320,7 +320,7 @@
 
     /**
      * <p>List of frame rate ranges supported by the
-     * AE algorithm/hardware</p>
+     * auto-exposure (AE) algorithm/hardware</p>
      */
     public static final Key<android.util.Range<Integer>[]> CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES =
             new Key<android.util.Range<Integer>[]>("android.control.aeAvailableTargetFpsRanges", new TypeReference<android.util.Range<Integer>[]>() {{ }});
@@ -343,7 +343,7 @@
             new Key<Rational>("android.control.aeCompensationStep", Rational.class);
 
     /**
-     * <p>List of AF modes that can be
+     * <p>List of auto-focus (AF) modes that can be
      * selected with {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}.</p>
      * <p>Not all the auto-focus modes may be supported by a
      * given camera device. This entry lists the valid modes for
@@ -496,7 +496,7 @@
             new Key<int[]>("android.hotPixel.availableHotPixelModes", int[].class);
 
     /**
-     * <p>Supported resolutions for the JPEG thumbnail</p>
+     * <p>Supported resolutions for the JPEG thumbnail.</p>
      * <p>Below condiditions will be satisfied for this size list:</p>
      * <ul>
      * <li>The sizes will be sorted by increasing pixel area (width x height).
@@ -784,11 +784,12 @@
      * may be delivered to the application layer from the camera device as
      * soon as they are available.</p>
      * <p>A value of 1 means that partial results are not supported.</p>
-     * <p>A typical use case for this might be: after requesting an AF lock the
-     * new AF state might be available 50% of the way through the pipeline.
-     * The camera device could then immediately dispatch this state via a
-     * partial result to the framework/application layer, and the rest of
-     * the metadata via later partial results.</p>
+     * <p>A typical use case for this might be: after requesting an
+     * auto-focus (AF) lock the new AF state might be available 50%
+     * of the way through the pipeline.  The camera device could
+     * then immediately dispatch this state via a partial result to
+     * the framework/application layer, and the rest of the
+     * metadata via later partial results.</p>
      */
     public static final Key<Integer> REQUEST_PARTIAL_RESULT_COUNT =
             new Key<Integer>("android.request.partialResultCount", int.class);
@@ -1326,7 +1327,13 @@
             new Key<android.graphics.Rect>("android.sensor.info.activeArraySize", android.graphics.Rect.class);
 
     /**
-     * <p>Range of valid sensitivities</p>
+     * <p>Range of valid sensitivities.</p>
+     * <p>The minimum and maximum valid values for the
+     * {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} control.</p>
+     * <p>The values are the standard ISO sensitivity values,
+     * as defined in ISO 12232:2006.</p>
+     *
+     * @see CaptureRequest#SENSOR_SENSITIVITY
      */
     public static final Key<android.util.Range<Integer>> SENSOR_INFO_SENSITIVITY_RANGE =
             new Key<android.util.Range<Integer>>("android.sensor.info.sensitivityRange", new TypeReference<android.util.Range<Integer>>() {{ }});
@@ -1372,8 +1379,11 @@
 
     /**
      * <p>The physical dimensions of the full pixel
-     * array</p>
-     * <p>Needed for FOV calculation for old API</p>
+     * array.</p>
+     * <p>This is the physical size of the sensor pixel
+     * array defined by {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      */
     public static final Key<android.util.SizeF> SENSOR_INFO_PHYSICAL_SIZE =
             new Key<android.util.SizeF>("android.sensor.info.physicalSize", android.util.SizeF.class);
@@ -1381,9 +1391,17 @@
     /**
      * <p>Dimensions of full pixel array, possibly
      * including black calibration pixels.</p>
-     * <p>Maximum output resolution for raw format must
-     * match this in
-     * android.scaler.availableStreamConfigurations.</p>
+     * <p>The pixel count of the full pixel array,
+     * which covers {@link CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE android.sensor.info.physicalSize} area.</p>
+     * <p>If a camera device supports raw sensor formats, either this
+     * or {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is the maximum output
+     * raw size listed in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.
+     * If a size corresponding to pixelArraySize is listed, the resulting
+     * raw sensor image will include black pixels.</p>
+     *
+     * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PHYSICAL_SIZE
      */
     public static final Key<android.util.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE =
             new Key<android.util.Size>("android.sensor.info.pixelArraySize", android.util.Size.class);
@@ -1638,8 +1656,8 @@
             new Key<Integer>("android.sensor.orientation", int.class);
 
     /**
-     * <p>Optional. Defaults to [OFF]. Lists the supported test
-     * pattern modes for {@link CaptureRequest#SENSOR_TEST_PATTERN_MODE android.sensor.testPatternMode}.</p>
+     * <p>Lists the supported sensor test pattern modes for {@link CaptureRequest#SENSOR_TEST_PATTERN_MODE android.sensor.testPatternMode}.</p>
+     * <p>Optional. Defaults to [OFF].</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
@@ -1649,7 +1667,7 @@
 
     /**
      * <p>Which face detection modes are available,
-     * if any</p>
+     * if any.</p>
      * <p>OFF means face detection is disabled, it must
      * be included in the list.</p>
      * <p>SIMPLE means the device supports the
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index e9213c5..68f4d64 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -52,7 +52,7 @@
      * Create a request suitable for a camera preview window. Specifically, this
      * means that high frame rate is given priority over the highest-quality
      * post-processing. These requests would normally be used with the
-     * {@link #setRepeatingRequest} method.
+     * {@link CameraCaptureSession#setRepeatingRequest} method.
      *
      * @see #createCaptureRequest
      */
@@ -61,7 +61,7 @@
     /**
      * Create a request suitable for still image capture. Specifically, this
      * means prioritizing image quality over frame rate. These requests would
-     * commonly be used with the {@link #capture} method.
+     * commonly be used with the {@link CameraCaptureSession#capture} method.
      *
      * @see #createCaptureRequest
      */
@@ -71,7 +71,7 @@
      * Create a request suitable for video recording. Specifically, this means
      * that a stable frame rate is used, and post-processing is set for
      * recording quality. These requests would commonly be used with the
-     * {@link #setRepeatingRequest} method.
+     * {@link CameraCaptureSession#setRepeatingRequest} method.
      *
      * @see #createCaptureRequest
      */
@@ -81,8 +81,8 @@
      * Create a request suitable for still image capture while recording
      * video. Specifically, this means maximizing image quality without
      * disrupting the ongoing recording. These requests would commonly be used
-     * with the {@link #capture} method while a request based on
-     * {@link #TEMPLATE_RECORD} is is in use with {@link #setRepeatingRequest}.
+     * with the {@link CameraCaptureSession#capture} method while a request based on
+     * {@link #TEMPLATE_RECORD} is is in use with {@link CameraCaptureSession#setRepeatingRequest}.
      *
      * @see #createCaptureRequest
      */
@@ -132,116 +132,6 @@
     /**
      * <p>Set up a new output set of Surfaces for the camera device.</p>
      *
-     * <p>The configuration determines the set of potential output Surfaces for
-     * the camera device for each capture request. A given request may use all
-     * or a only some of the outputs. This method must be called before requests
-     * can be submitted to the camera with {@link #capture capture},
-     * {@link #captureBurst captureBurst},
-     * {@link #setRepeatingRequest setRepeatingRequest}, or
-     * {@link #setRepeatingBurst setRepeatingBurst}.</p>
-     *
-     * <p>Surfaces suitable for inclusion as a camera output can be created for
-     * various use cases and targets:</p>
-     *
-     * <ul>
-     *
-     * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set
-     *   the size of the Surface with
-     *   {@link android.view.SurfaceHolder#setFixedSize} to be one of the
-     *   supported
-     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
-     *   before calling {@link android.view.SurfaceHolder#getSurface}.</li>
-     *
-     * <li>For accessing through an OpenGL texture via a
-     *   {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
-     *   the SurfaceTexture with
-     *   {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
-     *   of the supported
-     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
-     *   before creating a Surface from the SurfaceTexture with
-     *   {@link Surface#Surface}.</li>
-     *
-     * <li>For recording with {@link android.media.MediaCodec}: Call
-     *   {@link android.media.MediaCodec#createInputSurface} after configuring
-     *   the media codec to use one of the
-     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
-     *   </li>
-     *
-     * <li>For recording with {@link android.media.MediaRecorder}: TODO</li>
-     *
-     * <li>For efficient YUV processing with {@link android.renderscript}:
-     *   Create a RenderScript
-     *   {@link android.renderscript.Allocation Allocation} with a supported YUV
-     *   type, the IO_INPUT flag, and one of the supported
-     *   {@link StreamConfigurationMap#getOutputSizes(int) processed sizes}. Then
-     *   obtain the Surface with
-     *   {@link android.renderscript.Allocation#getSurface}.</li>
-     *
-     * <li>For access to uncompressed or {@link ImageFormat#JPEG JPEG} data in the application:
-     * Create a {@link android.media.ImageReader} object with the desired
-     * {@link StreamConfigurationMap#getOutputFormats() image format}, and a size from the matching
-     * {@link StreamConfigurationMap#getOutputSizes(int) processed size} and {@code format}.
-     * Then obtain a {@link Surface} from it.</li>
-     * </ul>
-     *
-     * </p>
-     *
-     * <p>This function can take several hundred milliseconds to execute, since
-     * camera hardware may need to be powered on or reconfigured.</p>
-     *
-     * <p>The camera device will query each Surface's size and formats upon this
-     * call, so they must be set to a valid setting at this time (in particular:
-     * if the format is user-visible, it must be one of
-     * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
-     * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
-     *
-     * <p>When this method is called with valid Surfaces, the device will transition to the {@link
-     * StateListener#onBusy busy state}. Once configuration is complete, the device will transition
-     * into the {@link StateListener#onIdle idle state}. Capture requests using the newly-configured
-     * Surfaces may then be submitted with {@link #capture}, {@link #captureBurst}, {@link
-     * #setRepeatingRequest}, or {@link #setRepeatingBurst}.</p>
-     *
-     * <p>If this method is called while the camera device is still actively processing previously
-     * submitted captures, then the following sequence of events occurs: The device transitions to
-     * the busy state and calls the {@link StateListener#onBusy} callback. Second, if a repeating
-     * request is set it is cleared.  Third, the device finishes up all in-flight and pending
-     * requests. Finally, once the device is idle, it then reconfigures its outputs, and calls the
-     * {@link StateListener#onIdle} method once it is again ready to accept capture
-     * requests. Therefore, no submitted work is discarded. To idle as fast as possible, use {@link
-     * #flush} and wait for the idle callback before calling configureOutputs. This will discard
-     * work, but reaches the new configuration sooner.</p>
-     *
-     * <p>Using larger resolution outputs, or more outputs, can result in slower
-     * output rate from the device.</p>
-     *
-     * <p>Configuring the outputs with an empty or null list will transition the camera into an
-     * {@link StateListener#onUnconfigured unconfigured state} instead of the {@link
-     * StateListener#onIdle idle state}.  </p>
-     *
-     * <p>Calling configureOutputs with the same arguments as the last call to
-     * configureOutputs has no effect, and the {@link StateListener#onBusy busy}
-     * and {@link StateListener#onIdle idle} state transitions will happen
-     * immediately.</p>
-     *
-     * @param outputs The new set of Surfaces that should be made available as
-     * targets for captured image data.
-     *
-     * @throws IllegalArgumentException if the set of output Surfaces do not
-     * meet the requirements
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera device is not idle, or
-     *                               if the camera device has been closed
-     *
-     * @see StateListener#onBusy
-     * @see StateListener#onIdle
-     * @see StateListener#onActive
-     * @see StateListener#onUnconfigured
-     * @see #stopRepeating
-     * @see #flush
-     * @see StreamConfigurationMap#getOutputFormats()
-     * @see StreamConfigurationMap#getOutputSizes(int)
-     * @see StreamConfigurationMap#getOutputSizes(Class)
      * @deprecated Use {@link #createCaptureSession} instead
      */
     @Deprecated
@@ -342,10 +232,7 @@
      * @param listener The listener to notify about the status of the new capture session.
      * @param handler The handler on which the listener should be invoked, or {@code null} to use
      *                the current thread's {@link android.os.Looper looper}.
-     * <!--
-     * @return A new camera capture session to use, or null if an empty/null set of Surfaces is
-     *         provided.
-     * -->
+     *
      * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
      *                                  the listener is null, or the handler is null but the current
      *                                  thread has no looper.
@@ -393,92 +280,16 @@
     /**
      * <p>Submit a request for an image to be captured by this CameraDevice.</p>
      *
-     * <p>The request defines all the parameters for capturing the single image,
-     * including sensor, lens, flash, and post-processing settings.</p>
-     *
-     * <p>Each request will produce one {@link CaptureResult} and produce new
-     * frames for one or more target Surfaces, set with the CaptureRequest
-     * builder's {@link CaptureRequest.Builder#addTarget} method. The target
-     * surfaces must be configured as active outputs with
-     * {@link #configureOutputs} before calling this method.</p>
-     *
-     * <p>Multiple requests can be in progress at once. They are processed in
-     * first-in, first-out order, with minimal delays between each
-     * capture. Requests submitted through this method have higher priority than
-     * those submitted through {@link #setRepeatingRequest} or
-     * {@link #setRepeatingBurst}, and will be processed as soon as the current
-     * repeat/repeatBurst processing completes.</p>
-     *
-     * @param request the settings for this capture
-     * @param listener The callback object to notify once this request has been
-     * processed. If null, no metadata will be produced for this capture,
-     * although image data will still be produced.
-     * @param handler the handler on which the listener should be invoked, or
-     * {@code null} to use the current thread's {@link android.os.Looper
-     * looper}.
-     *
-     * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is currently busy or unconfigured,
-     *                               or the camera device has been closed.
-     * @throws IllegalArgumentException If the request targets Surfaces not
-     * currently configured as outputs. Or if the handler is null, the listener
-     * is not null, and the calling thread has no looper.
-     *
-     * @see #captureBurst
-     * @see #setRepeatingRequest
-     * @see #setRepeatingBurst
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#capture} instead
      */
     @Deprecated
     public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
             throws CameraAccessException;
 
     /**
-     * Submit a list of requests to be captured in sequence as a burst. The
-     * burst will be captured in the minimum amount of time possible, and will
-     * not be interleaved with requests submitted by other capture or repeat
-     * calls.
+     * Submit a list of requests to be captured in sequence as a burst.
      *
-     * <p>The requests will be captured in order, each capture producing one
-     * {@link CaptureResult} and image buffers for one or more target
-     * {@link android.view.Surface surfaces}. The target surfaces for each
-     * request (set with {@link CaptureRequest.Builder#addTarget}) must be
-     * configured as active outputs with {@link #configureOutputs} before
-     * calling this method.</p>
-     *
-     * <p>The main difference between this method and simply calling
-     * {@link #capture} repeatedly is that this method guarantees that no
-     * other requests will be interspersed with the burst.</p>
-     *
-     * @param requests the list of settings for this burst capture
-     * @param listener The callback object to notify each time one of the
-     * requests in the burst has been processed. If null, no metadata will be
-     * produced for any requests in this burst, although image data will still
-     * be produced.
-     * @param handler the handler on which the listener should be invoked, or
-     * {@code null} to use the current thread's {@link android.os.Looper
-     * looper}.
-     *
-     * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is currently busy or unconfigured,
-     *                               or the camera device has been closed.
-     * @throws IllegalArgumentException If the requests target Surfaces not
-     * currently configured as outputs. Or if the handler is null, the listener
-     * is not null, and the calling thread has no looper. Or if no requests were
-     * passed in.
-     *
-     * @see #capture
-     * @see #setRepeatingRequest
-     * @see #setRepeatingBurst
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#captureBurst} instead
      */
     @Deprecated
     public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
@@ -487,58 +298,7 @@
     /**
      * Request endlessly repeating capture of images by this CameraDevice.
      *
-     * <p>With this method, the CameraDevice will continually capture images
-     * using the settings in the provided {@link CaptureRequest}, at the maximum
-     * rate possible.</p>
-     *
-     * <p>Repeating requests are a simple way for an application to maintain a
-     * preview or other continuous stream of frames, without having to
-     * continually submit identical requests through {@link #capture}.</p>
-     *
-     * <p>Repeat requests have lower priority than those submitted
-     * through {@link #capture} or {@link #captureBurst}, so if
-     * {@link #capture} is called when a repeating request is active, the
-     * capture request will be processed before any further repeating
-     * requests are processed.<p>
-     *
-     * <p>Repeating requests are a simple way for an application to maintain a
-     * preview or other continuous stream of frames, without having to submit
-     * requests through {@link #capture} at video rates.</p>
-     *
-     * <p>To stop the repeating capture, call {@link #stopRepeating}. Calling
-     * {@link #flush} will also clear the request.</p>
-     *
-     * <p>Calling this method will replace any earlier repeating request or
-     * burst set up by this method or {@link #setRepeatingBurst}, although any
-     * in-progress burst will be completed before the new repeat request will be
-     * used.</p>
-     *
-     * @param request the request to repeat indefinitely
-     * @param listener The callback object to notify every time the
-     * request finishes processing. If null, no metadata will be
-     * produced for this stream of requests, although image data will
-     * still be produced.
-     * @param handler the handler on which the listener should be invoked, or
-     * {@code null} to use the current thread's {@link android.os.Looper
-     * looper}.
-     *
-     * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is currently busy or unconfigured,
-     *                               or the camera device has been closed.
-     * @throws IllegalArgumentException If the requests reference Surfaces not
-     * currently configured as outputs. Or if the handler is null, the listener
-     * is not null, and the calling thread has no looper.
-     *
-     * @see #capture
-     * @see #captureBurst
-     * @see #setRepeatingBurst
-     * @see #stopRepeating
-     * @see #flush
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#setRepeatingRequest} instead
      */
     @Deprecated
     public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
@@ -548,58 +308,7 @@
      * <p>Request endlessly repeating capture of a sequence of images by this
      * CameraDevice.</p>
      *
-     * <p>With this method, the CameraDevice will continually capture images,
-     * cycling through the settings in the provided list of
-     * {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p>
-     *
-     * <p>If a request is submitted through {@link #capture} or
-     * {@link #captureBurst}, the current repetition of the request list will be
-     * completed before the higher-priority request is handled. This guarantees
-     * that the application always receives a complete repeat burst captured in
-     * minimal time, instead of bursts interleaved with higher-priority
-     * captures, or incomplete captures.</p>
-     *
-     * <p>Repeating burst requests are a simple way for an application to
-     * maintain a preview or other continuous stream of frames where each
-     * request is different in a predicatable way, without having to continually
-     * submit requests through {@link #captureBurst} .</p>
-     *
-     * <p>To stop the repeating capture, call {@link #stopRepeating}. Any
-     * ongoing burst will still be completed, however. Calling
-     * {@link #flush} will also clear the request.</p>
-     *
-     * <p>Calling this method will replace a previously-set repeating request or
-     * burst set up by this method or {@link #setRepeatingRequest}, although any
-     * in-progress burst will be completed before the new repeat burst will be
-     * used.</p>
-     *
-     * @param requests the list of requests to cycle through indefinitely
-     * @param listener The callback object to notify each time one of the
-     * requests in the repeating bursts has finished processing. If null, no
-     * metadata will be produced for this stream of requests, although image
-     * data will still be produced.
-     * @param handler the handler on which the listener should be invoked, or
-     * {@code null} to use the current thread's {@link android.os.Looper
-     * looper}.
-     *
-     * @return int A unique capture sequence ID used by
-     *             {@link CaptureListener#onCaptureSequenceCompleted}.
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is currently busy or unconfigured,
-     *                               or the camera device has been closed.
-     * @throws IllegalArgumentException If the requests reference Surfaces not
-     * currently configured as outputs. Or if the handler is null, the listener
-     * is not null, and the calling thread has no looper. Or if no requests were
-     * passed in.
-     *
-     * @see #capture
-     * @see #captureBurst
-     * @see #setRepeatingRequest
-     * @see #stopRepeating
-     * @see #flush
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#setRepeatingBurst} instead
      */
     @Deprecated
     public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
@@ -608,24 +317,9 @@
     /**
      * <p>Cancel any ongoing repeating capture set by either
      * {@link #setRepeatingRequest setRepeatingRequest} or
-     * {@link #setRepeatingBurst}. Has no effect on requests submitted through
-     * {@link #capture capture} or {@link #captureBurst captureBurst}.</p>
+     * {@link #setRepeatingBurst}.
      *
-     * <p>Any currently in-flight captures will still complete, as will any
-     * burst that is mid-capture. To ensure that the device has finished
-     * processing all of its capture requests and is in idle state, wait for the
-     * {@link StateListener#onIdle} callback after calling this
-     * method..</p>
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is currently busy or unconfigured,
-     *                               or the camera device has been closed.
-     *
-     * @see #setRepeatingRequest
-     * @see #setRepeatingBurst
-     * @see StateListener#onIdle
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#stopRepeating} instead
      */
     @Deprecated
     public abstract void stopRepeating() throws CameraAccessException;
@@ -634,36 +328,7 @@
      * Flush all captures currently pending and in-progress as fast as
      * possible.
      *
-     * <p>The camera device will discard all of its current work as fast as
-     * possible. Some in-flight captures may complete successfully and call
-     * {@link CaptureListener#onCaptureCompleted}, while others will trigger
-     * their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating
-     * request or a repeating burst is set, it will be cleared by the flush.</p>
-     *
-     * <p>This method is the fastest way to idle the camera device for
-     * reconfiguration with {@link #configureOutputs}, at the cost of discarding
-     * in-progress work. Once the flush is complete, the idle callback will be
-     * called.</p>
-     *
-     * <p>Flushing will introduce at least a brief pause in the stream of data
-     * from the camera device, since once the flush is complete, the first new
-     * request has to make it through the entire camera pipeline before new
-     * output buffers are produced.</p>
-     *
-     * <p>This means that using {@code flush()} to simply remove pending
-     * requests is not recommended; it's best used for quickly switching output
-     * configurations, or for cancelling long in-progress requests (such as a
-     * multi-second capture).</p>
-     *
-     * @throws CameraAccessException if the camera device is no longer connected or has
-     *                               encountered a fatal error
-     * @throws IllegalStateException if the camera is not idle/active,
-     *                               or the camera device has been closed.
-     *
-     * @see #setRepeatingRequest
-     * @see #setRepeatingBurst
-     * @see #configureOutputs
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession#abortCaptures} instead
      */
     @Deprecated
     public abstract void flush() throws CameraAccessException;
@@ -690,15 +355,7 @@
      * <p>A listener for tracking the progress of a {@link CaptureRequest}
      * submitted to the camera device.</p>
      *
-     * <p>This listener is called when a request triggers a capture to start,
-     * and when the capture is complete. In case on an error capturing an image,
-     * the error method is triggered instead of the completion method.</p>
-     *
-     * @see #capture
-     * @see #captureBurst
-     * @see #setRepeatingRequest
-     * @see #setRepeatingBurst
-     * @deprecated Use {@link CameraCaptureSession} instead
+     * @deprecated Use {@link CameraCaptureSession.CaptureListener} instead
      */
     @Deprecated
     public static abstract class CaptureListener {
@@ -715,29 +372,6 @@
          * This method is called when the camera device has started capturing
          * the output image for the request, at the beginning of image exposure.
          *
-         * <p>This callback is invoked right as the capture of a frame begins,
-         * so it is the most appropriate time for playing a shutter sound,
-         * or triggering UI indicators of capture.</p>
-         *
-         * <p>The request that is being used for this capture is provided, along
-         * with the actual timestamp for the start of exposure. This timestamp
-         * matches the timestamp that will be included in
-         * {@link CaptureResult#SENSOR_TIMESTAMP the result timestamp field},
-         * and in the buffers sent to each output Surface. These buffer
-         * timestamps are accessible through, for example,
-         * {@link android.media.Image#getTimestamp() Image.getTimestamp()} or
-         * {@link android.graphics.SurfaceTexture#getTimestamp()}.</p>
-         *
-         * <p>For the simplest way to play a shutter sound camera shutter or a
-         * video recording start/stop sound, see the
-         * {@link android.media.MediaActionSound} class.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera the CameraDevice sending the callback
-         * @param request the request for the capture that just begun
-         * @param timestamp the timestamp at start of capture, in nanoseconds.
-         *
          * @see android.media.MediaActionSound
          */
         public void onCaptureStarted(CameraDevice camera,
@@ -749,25 +383,6 @@
          * This method is called when some results from an image capture are
          * available.
          *
-         * <p>The result provided here will contain some subset of the fields of
-         * a full result. Multiple onCapturePartial calls may happen per
-         * capture; a given result field will only be present in one partial
-         * capture at most. The final onCaptureCompleted call will always
-         * contain all the fields, whether onCapturePartial was called or
-         * not.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera The CameraDevice sending the callback.
-         * @param request The request that was given to the CameraDevice
-         * @param result The partial output metadata from the capture, which
-         * includes a subset of the CaptureResult fields.
-         *
-         * @see #capture
-         * @see #captureBurst
-         * @see #setRepeatingRequest
-         * @see #setRepeatingBurst
-         *
          * @hide
          */
         public void onCapturePartial(CameraDevice camera,
@@ -779,37 +394,6 @@
          * This method is called when an image capture makes partial forward progress; some
          * (but not all) results from an image capture are available.
          *
-         * <p>The result provided here will contain some subset of the fields of
-         * a full result. Multiple {@link #onCaptureProgressed} calls may happen per
-         * capture; a given result field will only be present in one partial
-         * capture at most. The final {@link #onCaptureCompleted} call will always
-         * contain all the fields (in particular, the union of all the fields of all
-         * the partial results composing the total result).</p>
-         *
-         * <p>For each request, some result data might be available earlier than others. The typical
-         * delay between each partial result (per request) is a single frame interval.
-         * For performance-oriented use-cases, applications should query the metadata they need
-         * to make forward progress from the partial results and avoid waiting for the completed
-         * result.</p>
-         *
-         * <p>Each request will generate at least {@code 1} partial results, and at most
-         * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT} partial results.</p>
-         *
-         * <p>Depending on the request settings, the number of partial results per request
-         * will vary, although typically the partial count could be the same as long as the
-         * camera device subsystems enabled stay the same.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera The CameraDevice sending the callback.
-         * @param request The request that was given to the CameraDevice
-         * @param partialResult The partial output metadata from the capture, which
-         * includes a subset of the {@link TotalCaptureResult} fields.
-         *
-         * @see #capture
-         * @see #captureBurst
-         * @see #setRepeatingRequest
-         * @see #setRepeatingBurst
          */
         public void onCaptureProgressed(CameraDevice camera,
                 CaptureRequest request, CaptureResult partialResult) {
@@ -819,26 +403,6 @@
         /**
          * This method is called when an image capture has fully completed and all the
          * result metadata is available.
-         *
-         * <p>This callback will always fire after the last {@link #onCaptureProgressed};
-         * in other words, no more partial results will be delivered once the completed result
-         * is available.</p>
-         *
-         * <p>For performance-intensive use-cases where latency is a factor, consider
-         * using {@link #onCaptureProgressed} instead.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera The CameraDevice sending the callback.
-         * @param request The request that was given to the CameraDevice
-         * @param result The total output metadata from the capture, including the
-         * final capture parameters and the state of the camera system during
-         * capture.
-         *
-         * @see #capture
-         * @see #captureBurst
-         * @see #setRepeatingRequest
-         * @see #setRepeatingBurst
          */
         public void onCaptureCompleted(CameraDevice camera,
                 CaptureRequest request, TotalCaptureResult result) {
@@ -849,29 +413,6 @@
          * This method is called instead of {@link #onCaptureCompleted} when the
          * camera device failed to produce a {@link CaptureResult} for the
          * request.
-         *
-         * <p>Other requests are unaffected, and some or all image buffers from
-         * the capture may have been pushed to their respective output
-         * streams.</p>
-         *
-         * <p>Some partial results may have been delivered before the capture fails;
-         * however after this callback fires, no more partial results will be delivered by
-         * {@link #onCaptureProgressed}.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera
-         *            The CameraDevice sending the callback.
-         * @param request
-         *            The request that was given to the CameraDevice
-         * @param failure
-         *            The output failure from the capture, including the failure reason
-         *            and the frame number.
-         *
-         * @see #capture
-         * @see #captureBurst
-         * @see #setRepeatingRequest
-         * @see #setRepeatingBurst
          */
         public void onCaptureFailed(CameraDevice camera,
                 CaptureRequest request, CaptureFailure failure) {
@@ -882,26 +423,6 @@
          * This method is called independently of the others in CaptureListener,
          * when a capture sequence finishes and all {@link CaptureResult}
          * or {@link CaptureFailure} for it have been returned via this listener.
-         *
-         * <p>In total, there will be at least one result/failure returned by this listener
-         * before this callback is invoked. If the capture sequence is aborted before any
-         * requests have been processed, {@link #onCaptureSequenceAborted} is invoked instead.</p>
-         *
-         * <p>The default implementation does nothing.</p>
-         *
-         * @param camera
-         *            The CameraDevice sending the callback.
-         * @param sequenceId
-         *            A sequence ID returned by the {@link #capture} family of functions.
-         * @param frameNumber
-         *            The last frame number (returned by {@link CaptureResult#getFrameNumber}
-         *            or {@link CaptureFailure#getFrameNumber}) in the capture sequence.
-         *
-         * @see CaptureResult#getFrameNumber()
-         * @see CaptureFailure#getFrameNumber()
-         * @see CaptureResult#getSequenceId()
-         * @see CaptureFailure#getSequenceId()
-         * @see #onCaptureSequenceAborted
          */
         public void onCaptureSequenceCompleted(CameraDevice camera,
                 int sequenceId, long frameNumber) {
@@ -912,25 +433,6 @@
          * This method is called independently of the others in CaptureListener,
          * when a capture sequence aborts before any {@link CaptureResult}
          * or {@link CaptureFailure} for it have been returned via this listener.
-         *
-         * <p>Due to the asynchronous nature of the camera device, not all submitted captures
-         * are immediately processed. It is possible to clear out the pending requests
-         * by a variety of operations such as {@link CameraDevice#stopRepeating} or
-         * {@link CameraDevice#flush}. When such an event happens,
-         * {@link #onCaptureSequenceCompleted} will not be called.</p>
-         *
-         * <p>The default implementation does nothing.</p>
-         *
-         * @param camera
-         *            The CameraDevice sending the callback.
-         * @param sequenceId
-         *            A sequence ID returned by the {@link #capture} family of functions.
-         *
-         * @see CaptureResult#getFrameNumber()
-         * @see CaptureFailure#getFrameNumber()
-         * @see CaptureResult#getSequenceId()
-         * @see CaptureFailure#getSequenceId()
-         * @see #onCaptureSequenceCompleted
          */
         public void onCaptureSequenceAborted(CameraDevice camera,
                 int sequenceId) {
@@ -945,14 +447,14 @@
      * <p>A listener must be provided to the {@link CameraManager#openCamera}
      * method to open a camera device.</p>
      *
-     * <p>These events include notifications about the device becoming idle (
-     * allowing for {@link #configureOutputs} to be called), about device
-     * disconnection, and about unexpected device errors.</p>
+     * <p>These events include notifications about the device completing startup (
+     * allowing for {@link #createCaptureSession} to be called), about device
+     * disconnection or closure, and about unexpected device errors.</p>
      *
-     * <p>Events about the progress of specific {@link CaptureRequest
-     * CaptureRequests} are provided through a {@link CaptureListener} given to
-     * the {@link #capture}, {@link #captureBurst}, {@link
-     * #setRepeatingRequest}, or {@link #setRepeatingBurst} methods.
+     * <p>Events about the progress of specific {@link CaptureRequest CaptureRequests} are provided
+     * through a {@link CameraCaptureSession.CaptureListener} given to the
+     * {@link CameraCaptureSession#capture}, {@link CameraCaptureSession#captureBurst},
+     * {@link CameraCaptureSession#setRepeatingRequest}, or {@link CameraCaptureSession#setRepeatingBurst} methods.
      *
      * @see CameraManager#openCamera
      */
@@ -1026,8 +528,9 @@
         /**
          * The method called when a camera device has finished opening.
          *
-         * <p>An opened camera will immediately afterwards transition into
-         * {@link #onUnconfigured}.</p>
+         * <p>At this point, the camera device is ready to use, and
+         * {@link CameraDevice#createCaptureSession} can be called to set up the first capture
+         * session.</p>
          *
          * @param camera the camera device that has become opened
          */
@@ -1036,21 +539,7 @@
         /**
          * The method called when a camera device has no outputs configured.
          *
-         * <p>An unconfigured camera device needs to be configured with
-         * {@link CameraDevice#configureOutputs} before being able to
-         * submit any capture request.</p>
-         *
-         * <p>This state may be entered by a newly opened camera or by
-         * calling {@link CameraDevice#configureOutputs} with a null/empty
-         * list of Surfaces when idle.</p>
-         *
-         * <p>Any attempts to submit a capture request while in this state
-         * will result in an {@link IllegalStateException} being thrown.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera the camera device has that become unconfigured
-         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
+         * @deprecated Use {@link #onOpened} instead.
          */
         @Deprecated
         public void onUnconfigured(CameraDevice camera) {
@@ -1061,27 +550,7 @@
          * The method called when a camera device begins processing
          * {@link CaptureRequest capture requests}.
          *
-         * <p>A camera may not be re-configured while in this state. The camera
-         * will transition to the idle state once all pending captures have
-         * completed. If a repeating request is set, the camera will remain active
-         * until it is cleared and the remaining requests finish processing. To
-         * transition to the idle state as quickly as possible, call {@link #flush()},
-         * which will idle the camera device as quickly as possible, likely canceling
-         * most in-progress captures.</p>
-         *
-         * <p>All calls except for {@link CameraDevice#configureOutputs} are
-         * legal while in this state.
-         * </p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera the camera device that has become active
-         *
-         * @see CameraDevice#capture
-         * @see CameraDevice#captureBurst
-         * @see CameraDevice#setRepeatingBurst
-         * @see CameraDevice#setRepeatingRequest
-         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
+         * @deprecated Use {@link CameraCaptureSession.StateListener#onActive} instead.
          */
         @Deprecated
         public void onActive(CameraDevice camera) {
@@ -1091,32 +560,7 @@
         /**
          * The method called when a camera device is busy.
          *
-         * <p>A camera becomes busy while it's outputs are being configured
-         * (after a call to {@link CameraDevice#configureOutputs} or while it's
-         * being flushed (after a call to {@link CameraDevice#flush}.</p>
-         *
-         * <p>Once the on-going operations are complete, the camera will automatically
-         * transition into {@link #onIdle} if there is at least one configured output,
-         * or {@link #onUnconfigured} otherwise.</p>
-         *
-         * <p>Any attempts to manipulate the camera while its is busy
-         * will result in an {@link IllegalStateException} being thrown.</p>
-         *
-         * <p>Only the following methods are valid to call while in this state:
-         * <ul>
-         * <li>{@link CameraDevice#getId}</li>
-         * <li>{@link CameraDevice#createCaptureRequest}</li>
-         * <li>{@link CameraDevice#close}</li>
-         * </ul>
-         * </p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera the camera device that has become busy
-         *
-         * @see CameraDevice#configureOutputs
-         * @see CameraDevice#flush
-         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
+         * @deprecated Use {@link CameraCaptureSession.StateListener#onConfigured} instead.
          */
         @Deprecated
         public void onBusy(CameraDevice camera) {
@@ -1142,30 +586,7 @@
          * The method called when a camera device has finished processing all
          * submitted capture requests and has reached an idle state.
          *
-         * <p>An idle camera device can have its outputs changed by calling {@link
-         * CameraDevice#configureOutputs}, which will transition it into the busy state.</p>
-         *
-         * <p>To idle and reconfigure outputs without canceling any submitted
-         * capture requests, the application needs to clear its repeating
-         * request/burst, if set, with {@link CameraDevice#stopRepeating}, and
-         * then wait for this callback to be called before calling {@link
-         * CameraDevice#configureOutputs}.</p>
-         *
-         * <p>To idle and reconfigure a camera device as fast as possible, the
-         * {@link CameraDevice#flush} method can be used, which will discard all
-         * pending and in-progress capture requests. Once the {@link
-         * CameraDevice#flush} method is called, the application must wait for
-         * this callback to fire before calling {@link
-         * CameraDevice#configureOutputs}.</p>
-         *
-         * <p>The default implementation of this method does nothing.</p>
-         *
-         * @param camera the camera device that has become idle
-         *
-         * @see CameraDevice#configureOutputs
-         * @see CameraDevice#stopRepeating
-         * @see CameraDevice#flush
-         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
+         * @deprecated Use {@link CameraCaptureSession.StateListener#onReady} instead.
          */
         @Deprecated
         public void onIdle(CameraDevice camera) {
@@ -1221,7 +642,7 @@
          *
          * @param camera The device reporting the error
          * @param error The error code, one of the
-         *     {@code CameraDeviceListener.ERROR_*} values.
+         *     {@code StateListener.ERROR_*} values.
          *
          * @see #ERROR_CAMERA_DEVICE
          * @see #ERROR_CAMERA_SERVICE
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 9046b13..a69a813 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -35,7 +35,7 @@
 import java.util.ArrayList;
 
 /**
- * <p>An interface for iterating, listing, and connecting to
+ * <p>A system service manager for detecting, characterizing, and connecting to
  * {@link CameraDevice CameraDevices}.</p>
  *
  * <p>You can get an instance of this class by calling
@@ -244,11 +244,7 @@
                             USE_CALLING_UID, holder);
                     cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
                 } catch (CameraRuntimeException e) {
-                    if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
-                        // Use legacy camera implementation for HAL1 devices
-                        Log.i(TAG, "Using legacy camera HAL.");
-                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
-                    } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
+                    if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
                             e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
                             e.getReason() == CameraAccessException.CAMERA_DISABLED ||
                             e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
@@ -358,14 +354,18 @@
     }
 
     /**
-     * Interface for listening to camera devices becoming available or
-     * unavailable.
+     * A listener for camera devices becoming available or
+     * unavailable to open.
      *
      * <p>Cameras become available when they are no longer in use, or when a new
      * removable camera is connected. They become unavailable when some
      * application or service starts using a camera, or when a removable camera
      * is disconnected.</p>
      *
+     * <p>Extend this listener and pass an instance of the subclass to
+     * {@link CameraManager#addAvailabilityListener} to be notified of such availability
+     * changes.</p>
+     *
      * @see addAvailabilityListener
      */
     public static abstract class AvailabilityListener {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 94a5a79..90e5e4e 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -355,12 +355,14 @@
      * <li>RAW16 is reprocessable into both YUV_420_888 and JPEG
      * formats.</li>
      * <li>The maximum available resolution for RAW16 streams (both
-     * input/output) will match the value in
-     * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</li>
+     * input/output) will match the either value in
+     * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} or
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</li>
      * <li>All DNG-related optional metadata entries are provided
      * by the camera device.</li>
      * </ul>
      *
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
@@ -760,12 +762,14 @@
     public static final int CONTROL_AF_MODE_OFF = 0;
 
     /**
-     * <p>If lens is not fixed focus.</p>
-     * <p>Use {@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} to determine if lens
-     * is fixed-focus. In this mode, the lens does not move unless
+     * <p>Basic automatic focus mode.</p>
+     * <p>In this mode, the lens does not move unless
      * the autofocus trigger action is called. When that trigger
-     * is activated, AF must transition to ACTIVE_SCAN, then to
+     * is activated, AF will transition to ACTIVE_SCAN, then to
      * the outcome of the scan (FOCUSED or NOT_FOCUSED).</p>
+     * <p>Always supported if lens is not fixed focus.</p>
+     * <p>Use {@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} to determine if lens
+     * is fixed-focus.</p>
      * <p>Triggering AF_CANCEL resets the lens position to default,
      * and sets the AF state to INACTIVE.</p>
      *
@@ -775,11 +779,16 @@
     public static final int CONTROL_AF_MODE_AUTO = 1;
 
     /**
+     * <p>Close-up focusing mode.</p>
      * <p>In this mode, the lens does not move unless the
-     * autofocus trigger action is called.</p>
-     * <p>When that trigger is activated, AF must transition to
+     * autofocus trigger action is called. When that trigger is
+     * activated, AF will transition to ACTIVE_SCAN, then to
+     * the outcome of the scan (FOCUSED or NOT_FOCUSED). This
+     * mode is optimized for focusing on objects very close to
+     * the camera.</p>
+     * <p>When that trigger is activated, AF will transition to
      * ACTIVE_SCAN, then to the outcome of the scan (FOCUSED or
-     * NOT_FOCUSED).  Triggering cancel AF resets the lens
+     * NOT_FOCUSED). Triggering cancel AF resets the lens
      * position to default, and sets the AF state to
      * INACTIVE.</p>
      * @see CaptureRequest#CONTROL_AF_MODE
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index d4dfdd5..0ff8cce 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -43,14 +43,14 @@
  * <p>CaptureRequests can be created by using a {@link Builder} instance,
  * obtained by calling {@link CameraDevice#createCaptureRequest}</p>
  *
- * <p>CaptureRequests are given to {@link CameraDevice#capture} or
- * {@link CameraDevice#setRepeatingRequest} to capture images from a camera.</p>
+ * <p>CaptureRequests are given to {@link CameraCaptureSession#capture} or
+ * {@link CameraCaptureSession#setRepeatingRequest} to capture images from a camera.</p>
  *
  * <p>Each request can specify a different subset of target Surfaces for the
  * camera to send the captured data to. All the surfaces used in a request must
  * be part of the surface list given to the last call to
- * {@link CameraDevice#configureOutputs}, when the request is submitted to the
- * camera device.</p>
+ * {@link CameraDevice#createCaptureSession}, when the request is submitted to the
+ * session.</p>
  *
  * <p>For example, a request meant for repeating preview might only include the
  * Surface for the preview SurfaceView or SurfaceTexture, while a
@@ -357,11 +357,11 @@
      * request fields to one of the templates defined in {@link CameraDevice}.
      *
      * @see CameraDevice#createCaptureRequest
-     * @see #TEMPLATE_PREVIEW
-     * @see #TEMPLATE_RECORD
-     * @see #TEMPLATE_STILL_CAPTURE
-     * @see #TEMPLATE_VIDEO_SNAPSHOT
-     * @see #TEMPLATE_MANUAL
+     * @see CameraDevice#TEMPLATE_PREVIEW
+     * @see CameraDevice#TEMPLATE_RECORD
+     * @see CameraDevice#TEMPLATE_STILL_CAPTURE
+     * @see CameraDevice#TEMPLATE_VIDEO_SNAPSHOT
+     * @see CameraDevice#TEMPLATE_MANUAL
      */
     public final static class Builder {
 
@@ -381,7 +381,7 @@
          * <p>Add a surface to the list of targets for this request</p>
          *
          * <p>The Surface added must be one of the surfaces included in the most
-         * recent call to {@link CameraDevice#configureOutputs}, when the
+         * recent call to {@link CameraDevice#createCaptureSession}, when the
          * request is given to the camera device.</p>
          *
          * <p>Adding a target more than once has no effect.</p>
@@ -473,7 +473,7 @@
     /**
      * <p>The mode control selects how the image data is converted from the
      * sensor's native color into linear sRGB color.</p>
-     * <p>When auto-white balance is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
+     * <p>When auto-white balance (AWB) is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
      * control is overridden by the AWB routine. When AWB is disabled, the
      * application controls how the color mapping is performed.</p>
      * <p>We define the expected processing pipeline below. For consistency
@@ -524,7 +524,7 @@
 
     /**
      * <p>A color transform matrix to use to transform
-     * from sensor RGB color space to output linear sRGB color space</p>
+     * from sensor RGB color space to output linear sRGB color space.</p>
      * <p>This matrix is either set by the camera device when the request
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
@@ -600,13 +600,17 @@
             new Key<Integer>("android.control.aeAntibandingMode", int.class);
 
     /**
-     * <p>Adjustment to AE target image
-     * brightness</p>
-     * <p>For example, if EV step is 0.333, '6' will mean an
-     * exposure compensation of +2 EV; -3 will mean an exposure
-     * compensation of -1 EV. Note that this control will only be effective
-     * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when
-     * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
+     * <p>Adjustment to auto-exposure (AE) target image
+     * brightness.</p>
+     * <p>The adjustment is measured as a count of steps, with the
+     * step size defined by {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} and the
+     * allowed range by {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_RANGE android.control.aeCompensationRange}.</p>
+     * <p>For example, if the exposure value (EV) step is 0.333, '6'
+     * will mean an exposure compensation of +2 EV; -3 will mean an
+     * exposure compensation of -1 EV. One EV represents a doubling
+     * of image brightness. Note that this control will only be
+     * effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control
+     * will take effect even when {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
      * <p>In the event of exposure compensation value being changed, camera device
      * may take several frames to reach the newly requested exposure target.
      * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING
@@ -614,6 +618,8 @@
      * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or
      * FLASH_REQUIRED (if the scene is too dark for still capture).</p>
      *
+     * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_RANGE
+     * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureResult#CONTROL_AE_STATE
@@ -622,7 +628,7 @@
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
 
     /**
-     * <p>Whether AE is currently locked to its latest
+     * <p>Whether auto-exposure (AE) is currently locked to its latest
      * calculated values.</p>
      * <p>Note that even when AE is locked, the flash may be
      * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
@@ -711,9 +717,9 @@
 
     /**
      * <p>Range over which fps can be adjusted to
-     * maintain exposure</p>
-     * <p>Only constrains AE algorithm, not manual control
-     * of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
+     * maintain exposure.</p>
+     * <p>Only constrains auto-exposure (AE) algorithm, not
+     * manual control of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
      *
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
@@ -727,9 +733,10 @@
      * included at all in the request settings. When included and
      * set to START, the camera device will trigger the autoexposure
      * precapture metering sequence.</p>
-     * <p>The effect of AE precapture trigger depends on the current
-     * AE mode and state; see {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture
-     * state transition details.</p>
+     * <p>The effect of auto-exposure (AE) precapture trigger depends
+     * on the current AE mode and state; see
+     * {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
+     * details.</p>
      *
      * @see CaptureResult#CONTROL_AE_STATE
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
@@ -739,8 +746,8 @@
             new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
 
     /**
-     * <p>Whether AF is currently enabled, and what
-     * mode it is set to</p>
+     * <p>Whether auto-focus (AF) is currently enabled, and what
+     * mode it is set to.</p>
      * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO and the lens is not fixed focus
      * (i.e. <code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>).</p>
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
@@ -804,7 +811,7 @@
             new Key<Integer>("android.control.afTrigger", int.class);
 
     /**
-     * <p>Whether AWB is currently locked to its
+     * <p>Whether auto-white balance (AWB) is currently locked to its
      * latest calculated values.</p>
      * <p>Note that AWB lock is only meaningful for AUTO
      * mode; in other modes, AWB is already fixed to a specific
@@ -814,7 +821,7 @@
             new Key<Boolean>("android.control.awbLock", boolean.class);
 
     /**
-     * <p>Whether AWB is currently setting the color
+     * <p>Whether auto-white balance (AWB) is currently setting the color
      * transform fields, and what its illumination target
      * is.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
@@ -988,7 +995,7 @@
 
     /**
      * <p>Whether video stabilization is
-     * active</p>
+     * active.</p>
      * <p>If enabled, video stabilization can modify the
      * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
      * stabilized</p>
@@ -1030,7 +1037,7 @@
      * <p>When set to OFF, the camera device will not fire flash for this capture.</p>
      * <p>When set to SINGLE, the camera device will fire flash regardless of the camera
      * device's auto-exposure routine's result. When used in still capture case, this
-     * control should be used along with AE precapture metering sequence
+     * control should be used along with auto-exposure (AE) precapture metering sequence
      * ({@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}), otherwise, the image may be incorrectly exposed.</p>
      * <p>When set to TORCH, the flash will be on continuously. This mode can be used
      * for use cases such as preview, auto-focus assist, still capture, or video recording.</p>
@@ -1102,7 +1109,7 @@
 
     /**
      * <p>Compression quality of the final JPEG
-     * image</p>
+     * image.</p>
      * <p>85-95 is typical usage range</p>
      */
     public static final Key<Byte> JPEG_QUALITY =
@@ -1116,7 +1123,7 @@
             new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
 
     /**
-     * <p>Resolution of embedded JPEG thumbnail</p>
+     * <p>Resolution of embedded JPEG thumbnail.</p>
      * <p>When set to (0, 0) value, the JPEG EXIF will not contain thumbnail,
      * but the captured JPEG will still be a valid image.</p>
      * <p>When a jpeg image capture is issued, the thumbnail size selected should have
@@ -1204,7 +1211,7 @@
 
     /**
      * <p>Distance to plane of sharpest focus,
-     * measured from frontmost surface of the lens</p>
+     * measured from frontmost surface of the lens.</p>
      * <p>0 means infinity focus. Used value will be clamped
      * to [0, {@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance}].</p>
      * <p>Like {@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, this setting won't be applied
@@ -1235,7 +1242,7 @@
             new Key<Integer>("android.lens.opticalStabilizationMode", int.class);
 
     /**
-     * <p>Mode of operation for the noise reduction
+     * <p>Mode of operation for the noise reduction.
      * algorithm</p>
      * <p>Noise filtering control. OFF means no noise reduction
      * will be applied by the camera device.</p>
@@ -1265,40 +1272,39 @@
             new Key<Integer>("android.request.id", int.class);
 
     /**
-     * <p>(x, y, width, height).</p>
-     * <p>A rectangle with the top-level corner of (x,y) and size
-     * (width, height). The region of the sensor that is used for
-     * output. Each stream must use this rectangle to produce its
-     * output, cropping to a smaller region if necessary to
-     * maintain the stream's aspect ratio.</p>
-     * <p>HAL2.x uses only (x, y, width)</p>
-     * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
-     * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage,
-     * it is not croppable. The crop region will be ignored by raw streams.</p>
+     * <p>The region of the sensor to read out for this capture.</p>
+     * <p>The crop region coordinate system is based off
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
+     * top-left corner of the sensor active array.</p>
+     * <p>Output streams use this rectangle to produce their output,
+     * cropping to a smaller region if necessary to maintain the
+     * stream's aspect ratio, then scaling the sensor input to
+     * match the output's configured resolution.</p>
+     * <p>The crop region is applied after the RAW to other color
+     * space (e.g. YUV) conversion. Since raw streams
+     * (e.g. RAW16) don't have the conversion stage, they are not
+     * croppable. The crop region will be ignored by raw streams.</p>
      * <p>For non-raw streams, any additional per-stream cropping will
      * be done to maximize the final pixel area of the stream.</p>
      * <p>For example, if the crop region is set to a 4:3 aspect
-     * ratio, then 4:3 streams should use the exact crop
-     * region. 16:9 streams should further crop vertically
+     * ratio, then 4:3 streams will use the exact crop
+     * region. 16:9 streams will further crop vertically
      * (letterbox).</p>
      * <p>Conversely, if the crop region is set to a 16:9, then 4:3
-     * outputs should crop horizontally (pillarbox), and 16:9
-     * streams should match exactly. These additional crops must
+     * outputs will crop horizontally (pillarbox), and 16:9
+     * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>The output streams must maintain square pixels at all
-     * times, no matter what the relative aspect ratios of the
-     * crop region and the stream are.  Negative values for
-     * corner are allowed for raw output if full pixel array is
-     * larger than active pixel array. Width and height may be
-     * rounded to nearest larger supportable width, especially
-     * for raw output, where only a few fixed scales may be
-     * possible. The width and height of the crop region cannot
-     * be set to be smaller than floor( activeArraySize.width /
-     * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} ) and floor(
-     * activeArraySize.height /
-     * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom}), respectively.</p>
+     * <p>The width and height of the crop region cannot
+     * be set to be smaller than
+     * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
+     * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+     * <p>The camera device may adjust the crop region to account
+     * for rounding and other hardware requirements; the final
+     * crop region used will be included in the output capture
+     * result.</p>
      *
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
@@ -1391,12 +1397,20 @@
             new Key<Long>("android.sensor.frameDuration", long.class);
 
     /**
-     * <p>Gain applied to image data. Must be
-     * implemented through analog gain only if set to values
-     * below 'maximum analog sensitivity'.</p>
-     * <p>If the sensor can't apply this exact gain, it should lessen the
-     * gain to the nearest possible value (rather than gain more).</p>
-     * <p>ISO 12232:2006 REI method</p>
+     * <p>The amount of gain applied to sensor data
+     * before processing.</p>
+     * <p>The sensitivity is the standard ISO sensitivity value,
+     * as defined in ISO 12232:2006.</p>
+     * <p>The sensitivity must be within {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange}, and
+     * if if it less than {@link CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY android.sensor.maxAnalogSensitivity}, the camera device
+     * is guaranteed to use only analog amplification for applying the gain.</p>
+     * <p>If the camera device cannot apply the exact sensitivity
+     * requested, it will reduce the gain to the nearest supported
+     * value. The final sensitivity used will be available in the
+     * output capture result.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
+     * @see CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY
      */
     public static final Key<Integer> SENSOR_SENSITIVITY =
             new Key<Integer>("android.sensor.sensitivity", int.class);
@@ -1459,7 +1473,7 @@
      * lens shading map data in android.statistics.lensShadingMap, with size specified
      * by android.lens.info.shadingMapSize; the returned shading map data will be the one
      * applied by the camera device for this capture request.</p>
-     * <p>The shading map data may depend on the AE and AWB statistics, therefore the reliability
+     * <p>The shading map data may depend on the auto-exposure (AE) and AWB statistics, therefore the reliability
      * of the map data may be affected by the AE and AWB algorithms. When AE and AWB are in
      * AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> OFF),
      * to get best results, it is recommended that the applications wait for the AE and AWB to
@@ -1477,7 +1491,7 @@
 
     /**
      * <p>State of the face detector
-     * unit</p>
+     * unit.</p>
      * <p>Whether face detection is enabled, and whether it
      * should output just the basic fields or the full set of
      * fields. Value must be one of the
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 7d07c92..ce3de1d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -319,7 +319,7 @@
     /**
      * <p>The mode control selects how the image data is converted from the
      * sensor's native color into linear sRGB color.</p>
-     * <p>When auto-white balance is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
+     * <p>When auto-white balance (AWB) is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
      * control is overridden by the AWB routine. When AWB is disabled, the
      * application controls how the color mapping is performed.</p>
      * <p>We define the expected processing pipeline below. For consistency
@@ -370,7 +370,7 @@
 
     /**
      * <p>A color transform matrix to use to transform
-     * from sensor RGB color space to output linear sRGB color space</p>
+     * from sensor RGB color space to output linear sRGB color space.</p>
      * <p>This matrix is either set by the camera device when the request
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
@@ -446,13 +446,17 @@
             new Key<Integer>("android.control.aeAntibandingMode", int.class);
 
     /**
-     * <p>Adjustment to AE target image
-     * brightness</p>
-     * <p>For example, if EV step is 0.333, '6' will mean an
-     * exposure compensation of +2 EV; -3 will mean an exposure
-     * compensation of -1 EV. Note that this control will only be effective
-     * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when
-     * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
+     * <p>Adjustment to auto-exposure (AE) target image
+     * brightness.</p>
+     * <p>The adjustment is measured as a count of steps, with the
+     * step size defined by {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep} and the
+     * allowed range by {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_RANGE android.control.aeCompensationRange}.</p>
+     * <p>For example, if the exposure value (EV) step is 0.333, '6'
+     * will mean an exposure compensation of +2 EV; -3 will mean an
+     * exposure compensation of -1 EV. One EV represents a doubling
+     * of image brightness. Note that this control will only be
+     * effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control
+     * will take effect even when {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
      * <p>In the event of exposure compensation value being changed, camera device
      * may take several frames to reach the newly requested exposure target.
      * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING
@@ -460,6 +464,8 @@
      * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or
      * FLASH_REQUIRED (if the scene is too dark for still capture).</p>
      *
+     * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_RANGE
+     * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureResult#CONTROL_AE_STATE
@@ -468,7 +474,7 @@
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
 
     /**
-     * <p>Whether AE is currently locked to its latest
+     * <p>Whether auto-exposure (AE) is currently locked to its latest
      * calculated values.</p>
      * <p>Note that even when AE is locked, the flash may be
      * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
@@ -557,9 +563,9 @@
 
     /**
      * <p>Range over which fps can be adjusted to
-     * maintain exposure</p>
-     * <p>Only constrains AE algorithm, not manual control
-     * of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
+     * maintain exposure.</p>
+     * <p>Only constrains auto-exposure (AE) algorithm, not
+     * manual control of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
      *
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
@@ -573,9 +579,10 @@
      * included at all in the request settings. When included and
      * set to START, the camera device will trigger the autoexposure
      * precapture metering sequence.</p>
-     * <p>The effect of AE precapture trigger depends on the current
-     * AE mode and state; see {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture
-     * state transition details.</p>
+     * <p>The effect of auto-exposure (AE) precapture trigger depends
+     * on the current AE mode and state; see
+     * {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
+     * details.</p>
      *
      * @see CaptureResult#CONTROL_AE_STATE
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
@@ -585,7 +592,7 @@
             new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
 
     /**
-     * <p>Current state of AE algorithm</p>
+     * <p>Current state of auto-exposure (AE) algorithm.</p>
      * <p>Switching between or enabling AE modes ({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}) always
      * resets the AE state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
      * or {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code> resets all
@@ -783,8 +790,8 @@
             new Key<Integer>("android.control.aeState", int.class);
 
     /**
-     * <p>Whether AF is currently enabled, and what
-     * mode it is set to</p>
+     * <p>Whether auto-focus (AF) is currently enabled, and what
+     * mode it is set to.</p>
      * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO and the lens is not fixed focus
      * (i.e. <code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>).</p>
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
@@ -848,7 +855,7 @@
             new Key<Integer>("android.control.afTrigger", int.class);
 
     /**
-     * <p>Current state of AF algorithm.</p>
+     * <p>Current state of auto-focus (AF) algorithm.</p>
      * <p>Switching between or enabling AF modes ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) always
      * resets the AF state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
      * or {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code> resets all
@@ -1245,7 +1252,7 @@
             new Key<Integer>("android.control.afState", int.class);
 
     /**
-     * <p>Whether AWB is currently locked to its
+     * <p>Whether auto-white balance (AWB) is currently locked to its
      * latest calculated values.</p>
      * <p>Note that AWB lock is only meaningful for AUTO
      * mode; in other modes, AWB is already fixed to a specific
@@ -1255,7 +1262,7 @@
             new Key<Boolean>("android.control.awbLock", boolean.class);
 
     /**
-     * <p>Whether AWB is currently setting the color
+     * <p>Whether auto-white balance (AWB) is currently setting the color
      * transform fields, and what its illumination target
      * is.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
@@ -1338,7 +1345,7 @@
             new Key<Integer>("android.control.captureIntent", int.class);
 
     /**
-     * <p>Current state of AWB algorithm</p>
+     * <p>Current state of auto-white balance (AWB) algorithm.</p>
      * <p>Switching between or enabling AWB modes ({@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}) always
      * resets the AWB state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
      * or {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code> resets all
@@ -1559,7 +1566,7 @@
 
     /**
      * <p>Whether video stabilization is
-     * active</p>
+     * active.</p>
      * <p>If enabled, video stabilization can modify the
      * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
      * stabilized</p>
@@ -1601,7 +1608,7 @@
      * <p>When set to OFF, the camera device will not fire flash for this capture.</p>
      * <p>When set to SINGLE, the camera device will fire flash regardless of the camera
      * device's auto-exposure routine's result. When used in still capture case, this
-     * control should be used along with AE precapture metering sequence
+     * control should be used along with auto-exposure (AE) precapture metering sequence
      * ({@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}), otherwise, the image may be incorrectly exposed.</p>
      * <p>When set to TORCH, the flash will be on continuously. This mode can be used
      * for use cases such as preview, auto-focus assist, still capture, or video recording.</p>
@@ -1690,7 +1697,7 @@
 
     /**
      * <p>Compression quality of the final JPEG
-     * image</p>
+     * image.</p>
      * <p>85-95 is typical usage range</p>
      */
     public static final Key<Byte> JPEG_QUALITY =
@@ -1704,7 +1711,7 @@
             new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
 
     /**
-     * <p>Resolution of embedded JPEG thumbnail</p>
+     * <p>Resolution of embedded JPEG thumbnail.</p>
      * <p>When set to (0, 0) value, the JPEG EXIF will not contain thumbnail,
      * but the captured JPEG will still be a valid image.</p>
      * <p>When a jpeg image capture is issued, the thumbnail size selected should have
@@ -1792,7 +1799,7 @@
 
     /**
      * <p>Distance to plane of sharpest focus,
-     * measured from frontmost surface of the lens</p>
+     * measured from frontmost surface of the lens.</p>
      * <p>Should be zero for fixed-focus cameras</p>
      */
     public static final Key<Float> LENS_FOCUS_DISTANCE =
@@ -1800,7 +1807,7 @@
 
     /**
      * <p>The range of scene distances that are in
-     * sharp focus (depth of field)</p>
+     * sharp focus (depth of field).</p>
      * <p>If variable focus not supported, can still report
      * fixed depth of field range</p>
      */
@@ -1859,7 +1866,7 @@
             new Key<Integer>("android.lens.state", int.class);
 
     /**
-     * <p>Mode of operation for the noise reduction
+     * <p>Mode of operation for the noise reduction.
      * algorithm</p>
      * <p>Noise filtering control. OFF means no noise reduction
      * will be applied by the camera device.</p>
@@ -1934,40 +1941,39 @@
             new Key<Byte>("android.request.pipelineDepth", byte.class);
 
     /**
-     * <p>(x, y, width, height).</p>
-     * <p>A rectangle with the top-level corner of (x,y) and size
-     * (width, height). The region of the sensor that is used for
-     * output. Each stream must use this rectangle to produce its
-     * output, cropping to a smaller region if necessary to
-     * maintain the stream's aspect ratio.</p>
-     * <p>HAL2.x uses only (x, y, width)</p>
-     * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
-     * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage,
-     * it is not croppable. The crop region will be ignored by raw streams.</p>
+     * <p>The region of the sensor to read out for this capture.</p>
+     * <p>The crop region coordinate system is based off
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
+     * top-left corner of the sensor active array.</p>
+     * <p>Output streams use this rectangle to produce their output,
+     * cropping to a smaller region if necessary to maintain the
+     * stream's aspect ratio, then scaling the sensor input to
+     * match the output's configured resolution.</p>
+     * <p>The crop region is applied after the RAW to other color
+     * space (e.g. YUV) conversion. Since raw streams
+     * (e.g. RAW16) don't have the conversion stage, they are not
+     * croppable. The crop region will be ignored by raw streams.</p>
      * <p>For non-raw streams, any additional per-stream cropping will
      * be done to maximize the final pixel area of the stream.</p>
      * <p>For example, if the crop region is set to a 4:3 aspect
-     * ratio, then 4:3 streams should use the exact crop
-     * region. 16:9 streams should further crop vertically
+     * ratio, then 4:3 streams will use the exact crop
+     * region. 16:9 streams will further crop vertically
      * (letterbox).</p>
      * <p>Conversely, if the crop region is set to a 16:9, then 4:3
-     * outputs should crop horizontally (pillarbox), and 16:9
-     * streams should match exactly. These additional crops must
+     * outputs will crop horizontally (pillarbox), and 16:9
+     * streams will match exactly. These additional crops will
      * be centered within the crop region.</p>
-     * <p>The output streams must maintain square pixels at all
-     * times, no matter what the relative aspect ratios of the
-     * crop region and the stream are.  Negative values for
-     * corner are allowed for raw output if full pixel array is
-     * larger than active pixel array. Width and height may be
-     * rounded to nearest larger supportable width, especially
-     * for raw output, where only a few fixed scales may be
-     * possible. The width and height of the crop region cannot
-     * be set to be smaller than floor( activeArraySize.width /
-     * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} ) and floor(
-     * activeArraySize.height /
-     * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom}), respectively.</p>
+     * <p>The width and height of the crop region cannot
+     * be set to be smaller than
+     * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
+     * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+     * <p>The camera device may adjust the crop region to account
+     * for rounding and other hardware requirements; the final
+     * crop region used will be included in the output capture
+     * result.</p>
      *
      * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      */
     public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
             new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
@@ -2060,21 +2066,35 @@
             new Key<Long>("android.sensor.frameDuration", long.class);
 
     /**
-     * <p>Gain applied to image data. Must be
-     * implemented through analog gain only if set to values
-     * below 'maximum analog sensitivity'.</p>
-     * <p>If the sensor can't apply this exact gain, it should lessen the
-     * gain to the nearest possible value (rather than gain more).</p>
-     * <p>ISO 12232:2006 REI method</p>
+     * <p>The amount of gain applied to sensor data
+     * before processing.</p>
+     * <p>The sensitivity is the standard ISO sensitivity value,
+     * as defined in ISO 12232:2006.</p>
+     * <p>The sensitivity must be within {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange}, and
+     * if if it less than {@link CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY android.sensor.maxAnalogSensitivity}, the camera device
+     * is guaranteed to use only analog amplification for applying the gain.</p>
+     * <p>If the camera device cannot apply the exact sensitivity
+     * requested, it will reduce the gain to the nearest supported
+     * value. The final sensitivity used will be available in the
+     * output capture result.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
+     * @see CameraCharacteristics#SENSOR_MAX_ANALOG_SENSITIVITY
      */
     public static final Key<Integer> SENSOR_SENSITIVITY =
             new Key<Integer>("android.sensor.sensitivity", int.class);
 
     /**
      * <p>Time at start of exposure of first
-     * row</p>
-     * <p>Monotonic, should be synced to other timestamps in
-     * system</p>
+     * row of the image sensor, in nanoseconds.</p>
+     * <p>The timestamps are also included in all image
+     * buffers produced for the same capture, and will be identical
+     * on all the outputs. The timestamps measure time since an
+     * unspecified starting point, and are monotonically
+     * increasing.</p>
+     * <p>They can be compared with the timestamps for other captures
+     * from the same camera device, but are not guaranteed to be
+     * comparable to any other time source.</p>
      */
     public static final Key<Long> SENSOR_TIMESTAMP =
             new Key<Long>("android.sensor.timestamp", long.class);
@@ -2188,7 +2208,7 @@
      * lens shading map data in android.statistics.lensShadingMap, with size specified
      * by android.lens.info.shadingMapSize; the returned shading map data will be the one
      * applied by the camera device for this capture request.</p>
-     * <p>The shading map data may depend on the AE and AWB statistics, therefore the reliability
+     * <p>The shading map data may depend on the auto-exposure (AE) and AWB statistics, therefore the reliability
      * of the map data may be affected by the AE and AWB algorithms. When AE and AWB are in
      * AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> OFF),
      * to get best results, it is recommended that the applications wait for the AE and AWB to
@@ -2206,7 +2226,7 @@
 
     /**
      * <p>State of the face detector
-     * unit</p>
+     * unit.</p>
      * <p>Whether face detection is enabled, and whether it
      * should output just the basic fields or the full set of
      * fields. Value must be one of the
@@ -2370,7 +2390,7 @@
      * applied to that frame.</p>
      * <p>The 4 channel gains are defined in Bayer domain,
      * see {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} for details.</p>
-     * <p>This value should always be calculated by the AWB block,
+     * <p>This value should always be calculated by the auto-white balance (AWB) block,
      * regardless of the android.control.* current values.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
@@ -2396,7 +2416,7 @@
      * that frame.</p>
      * <p>These estimates must be provided for all frames, even if
      * capture settings and color transforms are set by the application.</p>
-     * <p>This value should always be calculated by the AWB block,
+     * <p>This value should always be calculated by the auto-white balance (AWB) block,
      * regardless of the android.control.* current values.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * @deprecated
diff --git a/core/java/android/hardware/camera2/package.html b/core/java/android/hardware/camera2/package.html
index 9f6c2a9..ef0d7bd 100644
--- a/core/java/android/hardware/camera2/package.html
+++ b/core/java/android/hardware/camera2/package.html
@@ -34,49 +34,71 @@
 CameraDevices} provide a set of static property information that
 describes the hardware device and the available settings and output
 parameters for the device. This information is provided through the
-{@link android.hardware.camera2.CameraCharacteristics} object.</p>
+{@link android.hardware.camera2.CameraCharacteristics} object, and is
+available through {@link
+android.hardware.camera2.CameraManager#getCameraCharacteristics}</p>
 
 <p>To capture or stream images from a camera device, the application
-must first configure a set of output Surfaces for use with the camera
-device, with {@link
-android.hardware.camera2.CameraDevice#configureOutputs}. Each
-Surface has to be pre-configured with an appropriate size and format
-(if applicable) to match the sizes and formats available from the
-camera device. A target Surface can be obtained from a variety of
-classes, including {@link android.view.SurfaceView}, {@link
-android.graphics.SurfaceTexture} via {@link
-android.view.Surface#Surface(SurfaceTexture), {@link
-android.media.MediaCodec}, and {@link android.media.ImageReader}.
+must first create a {@link
+android.hardware.camera2.CameraCaptureSession camera capture session}
+with a set of output Surfaces for use with the camera device, with
+{@link
+android.hardware.camera2.CameraDevice#createCaptureSession}. Each
+Surface has to be pre-configured with an {@link
+android.hardware.camera2.params.StreamConfigurationMap appropriate
+size and format} (if applicable) to match the sizes and formats
+available from the camera device. A target Surface can be obtained
+from a variety of classes, including {@link android.view.SurfaceView},
+{@link android.graphics.SurfaceTexture} via
+{@link android.view.Surface#Surface(SurfaceTexture)},
+{@link android.media.MediaCodec}, {@link android.media.MediaRecorder},
+{@link android.renderscript.Allocation}, and {@link android.media.ImageReader}.
 </p>
 
+<p>Generally, camera preview images are sent to {@link
+android.view.SurfaceView} or {@link android.view.TextureView} (via its
+{@link android.graphics.SurfaceTexture}). Capture of JPEG images or
+RAW buffers for {@link android.hardware.camera2.DngCreator} can be done
+with {@link android.media.ImageReader} with the
+{android.graphics.ImageFormat#JPEG} and
+{android.graphics.ImageFormat#RAW_SENSOR} formats.  Application-driven
+processing of camera data in RenderScript, OpenGL ES, or directly in
+managed or native code is best done through {@link
+android.renderscript.Allocation} with a YUV {@link
+android.renderscript.Type}, {@link android.graphics.SurfaceTexture},
+and {@link android.media.ImageReader} with a
+{android.graphics.ImageFormat#YUV_420_888} format, respectively.</p>
+
 <p>The application then needs to construct a {@link
 android.hardware.camera2.CaptureRequest}, which defines all the
 capture parameters needed by a camera device to capture a single
 image. The request also lists which of the configured output Surfaces
 should be used as targets for this capture. The CameraDevice has a
 {@link android.hardware.camera2.CameraDevice#createCaptureRequest
-convenience factory method} for creating a request for a given use
-case which is optimized for the Android device the application is
-running on.</p>
+factory method} for creating a {@link
+android.hardware.camera2.CaptureRequest.Builder request builder} for a
+given use case, which is optimized for the Android device the
+application is running on.</p>
 
-<p>Once the request has been set up, it can be handed to the
-CameraDevice either for a one-shot {@link
-android.hardware.camera2.CameraDevice#capture} or for an endlessly
-{@link android.hardware.camera2.CameraDevice#setRepeatingRequest
-repeating} use. Both methods also accept a list of requests to use as
-a burst capture / repeating burst. Repeating requests have a lower
-priority than captures, so a request submitted
+<p>Once the request has been set up, it can be handed to the active
+capture session either for a one-shot {@link
+android.hardware.camera2.CameraCaptureSession#capture capture} or for
+an endlessly {@link
+android.hardware.camera2.CameraCaptureSession#setRepeatingRequest
+repeating} use. Both methods also have a variant that accepts a list
+of requests to use as a burst capture / repeating burst. Repeating
+requests have a lower priority than captures, so a request submitted
 through <code>capture()</code> while there's a repeating request
-configured will be captured as soon as the current repeat (burst)
-capture completes.</p>
+configured will be captured before any new instances of the currently
+repeating (burst) capture will begin capture.</p>
 
 <p>After processing a request, the camera device will produce a {@link
-android.hardware.camera2.CaptureResult} object, which contains
+android.hardware.camera2.TotalCaptureResult} object, which contains
 information about the state of the camera device at time of capture,
 and the final settings used. These may vary somewhat from the request,
 if rounding or resolving contradictory parameters was necessary. The
 camera device will also send a frame of image data into each of the
-output streams included in the request. These are produced
+output {@code Surfaces} included in the request. These are produced
 asynchronously relative to the output CaptureResult, sometimes
 substantially later.</p>
 
diff --git a/core/java/android/hardware/camera2/params/StreamConfiguration.java b/core/java/android/hardware/camera2/params/StreamConfiguration.java
index 1c6b6e9..dd862b5 100644
--- a/core/java/android/hardware/camera2/params/StreamConfiguration.java
+++ b/core/java/android/hardware/camera2/params/StreamConfiguration.java
@@ -28,9 +28,9 @@
 
 /**
  * Immutable class to store the available stream
- * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
- * when configuring streams with {@link CameraDevice#configureOutputs}.
- * <!-- TODO: link to input stream configuration -->
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to set up
+ * {@link android.view.Surface Surfaces} for creating a {@link CameraCaptureSession capture session}
+ * with {@link CameraDevice#createCaptureSession}.  <!-- TODO: link to input stream configuration -->
  *
  * <p>This is the authoritative list for all input/output formats (and sizes respectively
  * for that format) that are supported by a camera device.</p>
@@ -124,7 +124,7 @@
      *
      * @return {@code true} if output configuration, {@code false} otherwise
      *
-     * @see CameraDevice#configureOutputs
+     * @see CameraDevice#createCaptureSession
      */
     public boolean isOutput() {
         return !mInput;
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 4cd6d151..3036425 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -34,8 +34,10 @@
 
 /**
  * Immutable class to store the available stream
- * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP configurations} to be used
- * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP configurations} to set up
+ * {@link android.view.Surface Surfaces} for creating a
+ * {@link android.hardware.camera2.CameraCaptureSession capture session} with
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession}.
  * <!-- TODO: link to input stream configuration -->
  *
  * <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
@@ -56,7 +58,7 @@
  * }</code></pre>
  *
  * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
- * @see CameraDevice#configureOutputs
+ * @see CameraDevice#createCaptureSession
  */
 public final class StreamConfigurationMap {
 
@@ -155,8 +157,8 @@
     }
 
     /**
-     * Determine whether or not output streams can be
-     * {@link CameraDevice#configureOutputs configured} with a particular user-defined format.
+     * Determine whether or not output surfaces with a particular user-defined format can be passed
+     * {@link CameraDevice#createCaptureSession createCaptureSession}.
      *
      * <p>This method determines that the output {@code format} is supported by the camera device;
      * each output {@code surface} target may or may not itself support that {@code format}.
@@ -168,7 +170,7 @@
      * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
      * @return
      *          {@code true} iff using a {@code surface} with this {@code format} will be
-     *          supported with {@link CameraDevice#configureOutputs}
+     *          supported with {@link CameraDevice#createCaptureSession}
      *
      * @throws IllegalArgumentException
      *          if the image format was not a defined named constant
@@ -176,7 +178,7 @@
      *
      * @see ImageFormat
      * @see PixelFormat
-     * @see CameraDevice#configureOutputs
+     * @see CameraDevice#createCaptureSession
      */
     public boolean isOutputSupportedFor(int format) {
         checkArgumentFormat(format);
@@ -210,7 +212,7 @@
      *
      * <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
      * provide a producer endpoint that is suitable to be used with
-     * {@link CameraDevice#configureOutputs}.</p>
+     * {@link CameraDevice#createCaptureSession}.</p>
      *
      * <p>Since not all of the above classes support output of all format and size combinations,
      * the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
@@ -220,7 +222,7 @@
      *
      * @throws NullPointerException if {@code klass} was {@code null}
      *
-     * @see CameraDevice#configureOutputs
+     * @see CameraDevice#createCaptureSession
      * @see #isOutputSupportedFor(Surface)
      */
     public static <T> boolean isOutputSupportedFor(Class<T> klass) {
@@ -244,8 +246,8 @@
     }
 
     /**
-     * Determine whether or not the {@code surface} in its current state is suitable to be
-     * {@link CameraDevice#configureOutputs configured} as an output.
+     * Determine whether or not the {@code surface} in its current state is suitable to be included
+     * in a {@link CameraDevice#createCaptureSession capture session} as an output.
      *
      * <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
      * of that {@code surface} are compatible. Some classes that provide the {@code surface} are
@@ -269,7 +271,7 @@
      *
      * @throws NullPointerException if {@code surface} was {@code null}
      *
-     * @see CameraDevice#configureOutputs
+     * @see CameraDevice#createCaptureSession
      * @see #isOutputSupportedFor(Class)
      */
     public boolean isOutputSupportedFor(Surface surface) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b96f166..60e76e0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -22,6 +22,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.Handler;
@@ -981,13 +982,13 @@
             public void onAvailable(NetworkRequest request, Network network) {
                 currentNetwork = network;
                 Log.d(TAG, "startUsingNetworkFeature got Network:" + network);
-                network.bindProcessForHostResolution();
+                setProcessDefaultNetworkForHostResolution(network);
             }
             @Override
             public void onLost(NetworkRequest request, Network network) {
                 if (network.equals(currentNetwork)) {
                     currentNetwork = null;
-                    network.unbindProcessForHostResolution();
+                    setProcessDefaultNetworkForHostResolution(null);
                 }
                 Log.d(TAG, "startUsingNetworkFeature lost Network:" + network);
             }
@@ -1071,7 +1072,7 @@
      * @return {@code true} on success, {@code false} on failure
      *
      * @deprecated Deprecated in favor of the {@link #requestNetwork},
-     *             {@link Network#bindProcess} and {@link Network#socketFactory} api.
+     *             {@link #setProcessDefaultNetwork} and {@link Network#getSocketFactory} api.
      */
     public boolean requestRouteToHost(int networkType, int hostAddress) {
         InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
@@ -1095,7 +1096,7 @@
      * @return {@code true} on success, {@code false} on failure
      * @hide
      * @deprecated Deprecated in favor of the {@link #requestNetwork} and
-     *             {@link Network#bindProcess} api.
+     *             {@link #setProcessDefaultNetwork} api.
      */
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
         byte[] address = hostAddress.getAddress();
@@ -2347,4 +2348,64 @@
             mService.releaseNetworkRequest(networkRequest);
         } catch (RemoteException e) {}
     }
+
+    /**
+     * Binds the current process to {@code network}.  All Sockets created in the future
+     * (and not explicitly bound via a bound SocketFactory from
+     * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to
+     * {@code network}.  All host name resolutions will be limited to {@code network} as well.
+     * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to
+     * work and all host name resolutions will fail.  This is by design so an application doesn't
+     * accidentally use Sockets it thinks are still bound to a particular {@link Network}.
+     * To clear binding pass {@code null} for {@code network}.  Using individually bound
+     * Sockets created by Network.getSocketFactory().createSocket() and
+     * performing network-specific host name resolutions via
+     * {@link Network#getAllByName Network.getAllByName} is preferred to calling
+     * {@code setProcessDefaultNetwork}.
+     *
+     * @param network The {@link Network} to bind the current process to, or {@code null} to clear
+     *                the current binding.
+     * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid.
+     */
+    public static boolean setProcessDefaultNetwork(Network network) {
+        if (network == null) {
+            NetworkUtils.unbindProcessToNetwork();
+        } else {
+            NetworkUtils.bindProcessToNetwork(network.netId);
+        }
+        // TODO fix return value
+        return true;
+    }
+
+    /**
+     * Returns the {@link Network} currently bound to this process via
+     * {@link #setProcessDefaultNetwork}, or {@code null} if no {@link Network} is explicitly bound.
+     *
+     * @return {@code Network} to which this process is bound, or {@code null}.
+     */
+    public static Network getProcessDefaultNetwork() {
+        int netId = NetworkUtils.getNetworkBoundToProcess();
+        if (netId == 0) return null;
+        return new Network(netId);
+    }
+
+    /**
+     * Binds host resolutions performed by this process to {@code network}.
+     * {@link #setProcessDefaultNetwork} takes precedence over this setting.
+     *
+     * @param network The {@link Network} to bind host resolutions from the current process to, or
+     *                {@code null} to clear the current binding.
+     * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid.
+     * @hide
+     * @deprecated This is strictly for legacy usage to support {@link #startUsingNetworkFeature}.
+     */
+    public static boolean setProcessDefaultNetworkForHostResolution(Network network) {
+        if (network == null) {
+            NetworkUtils.unbindProcessToNetworkForHostResolution();
+        } else {
+            NetworkUtils.bindProcessToNetworkForHostResolution(network.netId);
+        }
+        // TODO hook up the return value.
+        return true;
+    }
 }
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 64516e6..d933f26 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -32,7 +32,8 @@
  * {@link ConnectivityManager.NetworkCallbackListener} in response to
  * {@link ConnectivityManager#requestNetwork} or {@link ConnectivityManager#listenForNetwork}.
  * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis
- * through a targeted {@link SocketFactory} or process-wide via {@link #bindProcess}.
+ * through a targeted {@link SocketFactory} or process-wide via
+ * {@link ConnectivityManager#setProcessDefaultNetwork}.
  */
 public class Network implements Parcelable {
 
@@ -160,63 +161,13 @@
      * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this
      *         {@code Network}.
      */
-    public SocketFactory socketFactory() {
+    public SocketFactory getSocketFactory() {
         if (mNetworkBoundSocketFactory == null) {
             mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
         }
         return mNetworkBoundSocketFactory;
     }
 
-    /**
-     * Binds the current process to this network.  All sockets created in the future (and not
-     * explicitly bound via a bound {@link SocketFactory} (see {@link Network#socketFactory})
-     * will be bound to this network.  Note that if this {@code Network} ever disconnects
-     * all sockets created in this way will cease to work.  This is by design so an application
-     * doesn't accidentally use sockets it thinks are still bound to a particular {@code Network}.
-     */
-    public void bindProcess() {
-        NetworkUtils.bindProcessToNetwork(netId);
-    }
-
-    /**
-     * Binds host resolutions performed by this process to this network.  {@link #bindProcess}
-     * takes precedence over this setting.
-     *
-     * @hide
-     * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
-     */
-    public void bindProcessForHostResolution() {
-        NetworkUtils.bindProcessToNetworkForHostResolution(netId);
-    }
-
-    /**
-     * Clears any process specific {@link Network} binding for host resolution.  This does
-     * not clear bindings enacted via {@link #bindProcess}.
-     *
-     * @hide
-     * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
-     */
-    public void unbindProcessForHostResolution() {
-        NetworkUtils.unbindProcessToNetworkForHostResolution();
-    }
-
-    /**
-     * A static utility method to return any {@code Network} currently bound by this process.
-     *
-     * @return {@code Network} to which this process is bound.
-     */
-    public static Network getProcessBoundNetwork() {
-        return new Network(NetworkUtils.getNetworkBoundToProcess());
-    }
-
-    /**
-     * Clear any process specific {@code Network} binding.  This reverts a call to
-     * {@link Network#bindProcess}.
-     */
-    public static void unbindProcess() {
-        NetworkUtils.unbindProcessToNetwork();
-    }
-
     // implement the Parcelable interface
     public int describeContents() {
         return 0;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index edb3286..b02f88e 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -111,7 +111,7 @@
     /**
      * Binds the current process to the network designated by {@code netId}.  All sockets created
      * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
-     * {@link Network#socketFactory}) will be bound to this network.  Note that if this
+     * {@link Network#getSocketFactory}) will be bound to this network.  Note that if this
      * {@code Network} ever disconnects all sockets created in this way will cease to work.  This
      * is by design so an application doesn't accidentally use sockets it thinks are still bound to
      * a particular {@code Network}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e9ffc52..bd988a6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -791,6 +791,15 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PAIRING_SETTINGS = "android.settings.PAIRING_SETTINGS";
 
+    /**
+     * Activity Action: Show battery saver settings.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_BATTERY_SAVER_SETTINGS
+            = "android.settings.BATTERY_SAVER_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -6018,6 +6027,12 @@
          */
         public static final String LOW_POWER_MODE = "low_power";
 
+        /**
+         * Battery level [1-99] at which low power mode automatically turns on.
+         * @hide
+         */
+        public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
+
          /**
          * If 1, the activity manager will aggressively finish activities and
          * processes as soon as they are no longer needed.  If 0, the normal
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3696806..8768779 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1758,11 +1758,11 @@
 
     <!-- Allows the system to bind to an application's task services
          @hide -->
-    <permission android:name="android.permission.BIND_TASK_SERVICE"
+    <permission android:name="android.permission.BIND_JOB_SERVICE"
         android:protectionLevel="signature"
-        android:label="@string/permlab_bindTaskService"
-        android:description="@string/permdesc_bindTaskService" />
-    <uses-permission android:name="android.permission.BIND_TASK_SERVICE"/>
+        android:label="@string/permlab_bindJobService"
+        android:description="@string/permdesc_bindJobService" />
+    <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -2877,8 +2877,8 @@
         </service>
 
         <service android:name="com.android.server.MountServiceIdler"
-                 android:exported="false"
-                 android:permission="android.permission.BIND_TASK_SERVICE" >
+                 android:exported="true"
+                 android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
     </application>
diff --git a/core/res/res/drawable/btn_borderless_material.xml b/core/res/res/drawable/btn_borderless_material.xml
index 1967b38..a459089 100644
--- a/core/res/res/drawable/btn_borderless_material.xml
+++ b/core/res/res/drawable/btn_borderless_material.xml
@@ -15,7 +15,7 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorControlHighlight">
+    android:color="?attr/colorControlHighlight">
     <item android:id="@id/mask"
         android:drawable="@drawable/btn_mtrl_alpha" />
 </ripple>
diff --git a/core/res/res/drawable/btn_default_material.xml b/core/res/res/drawable/btn_default_material.xml
index acec900..9cee3ab 100644
--- a/core/res/res/drawable/btn_default_material.xml
+++ b/core/res/res/drawable/btn_default_material.xml
@@ -15,7 +15,7 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorControlHighlight">
+    android:color="?attr/colorControlHighlight">
     <item>
         <nine-patch android:src="@drawable/btn_mtrl_alpha"
             android:tint="?attr/colorButtonNormal" />
diff --git a/core/res/res/drawable/btn_toggle_material.xml b/core/res/res/drawable/btn_toggle_material.xml
index 4532c77..73fe4d3 100644
--- a/core/res/res/drawable/btn_toggle_material.xml
+++ b/core/res/res/drawable/btn_toggle_material.xml
@@ -21,7 +21,7 @@
     android:insetRight="4dp">
     <layer-list android:paddingMode="stack">
         <item>
-            <ripple android:tint="?attr/colorControlHighlight">
+            <ripple android:color="?attr/colorControlHighlight">
                 <item>
                     <nine-patch android:src="@drawable/btn_toggle_mtrl_alpha"
                         android:tint="?attr/colorButtonNormal" />
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index 26fd889..86cec8f 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -15,8 +15,7 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorControlActivated"
-    android:tintMode="src_over">
+    android:color="?attr/colorControlActivated">
     <item>
         <selector>
             <item android:state_enabled="false">
diff --git a/core/res/res/drawable/item_background_borderless_material.xml b/core/res/res/drawable/item_background_borderless_material.xml
index c2a1c127..b730618 100644
--- a/core/res/res/drawable/item_background_borderless_material.xml
+++ b/core/res/res/drawable/item_background_borderless_material.xml
@@ -15,5 +15,4 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorControlHighlight"
-    android:pinned="true" />
+    android:color="?attr/colorControlHighlight" />
diff --git a/core/res/res/drawable/item_background_material.xml b/core/res/res/drawable/item_background_material.xml
index 039ca51..45ff181 100644
--- a/core/res/res/drawable/item_background_material.xml
+++ b/core/res/res/drawable/item_background_material.xml
@@ -15,8 +15,8 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="?attr/colorControlHighlight">
+    android:color="?attr/colorControlHighlight">
     <item android:id="@id/mask">
         <color android:color="@color/white" />
     </item>
-</ripple>
\ No newline at end of file
+</ripple>
diff --git a/core/res/res/drawable/notification_bg_dim.xml b/core/res/res/drawable/notification_bg_dim.xml
index ae03d82..5c245f8 100644
--- a/core/res/res/drawable/notification_bg_dim.xml
+++ b/core/res/res/drawable/notification_bg_dim.xml
@@ -15,9 +15,7 @@
   ~ limitations under the License
   -->
 
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="#ff444444"
-    >
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="#ff444444">
     <item android:drawable="@drawable/notification_bg_normal" />
 </ripple>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_material_bg_dim.xml b/core/res/res/drawable/notification_material_bg_dim.xml
index a908be7..9b691e6 100644
--- a/core/res/res/drawable/notification_material_bg_dim.xml
+++ b/core/res/res/drawable/notification_material_bg_dim.xml
@@ -15,15 +15,18 @@
   ~ limitations under the License
   -->
 
-<ripple
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:tint="#ffffffff"
-    android:tintMode="src_over"
-    >
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/white">
     <item>
         <shape>
             <solid android:color="#d4ffffff" />
             <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
         </shape>
     </item>
-</ripple>
\ No newline at end of file
+    <item android:id="@id/mask">
+        <shape>
+            <solid android:color="@color/white" />
+            <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
+        </shape>
+    </item>
+</ripple>
diff --git a/core/res/res/layout/preference_widget_checkbox.xml b/core/res/res/layout/preference_widget_checkbox.xml
index bfd7f0a..f794346 100644
--- a/core/res/res/layout/preference_widget_checkbox.xml
+++ b/core/res/res/layout/preference_widget_checkbox.xml
@@ -21,4 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:focusable="false"
-    android:clickable="false" />
+    android:clickable="false"
+    android:background="@null" />
diff --git a/core/res/res/layout/preference_widget_switch.xml b/core/res/res/layout/preference_widget_switch.xml
index 534c7ec..04a310b 100644
--- a/core/res/res/layout/preference_widget_switch.xml
+++ b/core/res/res/layout/preference_widget_switch.xml
@@ -21,4 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:padding="16dip"
-    android:focusable="false" />
+    android:focusable="false"
+    android:background="@null" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4fa04a9..ed648fb 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4669,12 +4669,8 @@
 
     <!-- Drawable used to show animated touch feedback. -->
     <declare-styleable name="RippleDrawable">
-        <!-- The tint to use for ripple effects. This attribute is required. -->
-        <attr name="tint" />
-        <!-- Specifies the Porter-Duff blending mode used to apply the tint. The default value is src_atop, which draws over the opaque parts of the drawable. -->
-        <attr name="tintMode" />
-        <!-- Whether to pin ripple effects to the center of the drawable. Default value is false. -->
-        <attr name="pinned" format="boolean" />
+        <!-- The color to use for ripple effects. This attribute is required. -->
+        <attr name="color" />
     </declare-styleable>
 
     <declare-styleable name="ScaleDrawable">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 865d92a..59d01de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -589,16 +589,16 @@
 
     <!-- Display low battery warning when battery level dips to this value.
          Also, the battery stats are flushed to disk when we hit this level.  -->
-    <integer name="config_criticalBatteryWarningLevel">4</integer>
+    <integer name="config_criticalBatteryWarningLevel">5</integer>
 
     <!-- Shutdown if the battery temperature exceeds (this value * 0.1) Celsius. -->
     <integer name="config_shutdownBatteryTemperature">680</integer>
 
     <!-- Display low battery warning when battery level dips to this value -->
-    <integer name="config_lowBatteryWarningLevel">15</integer>
+    <integer name="config_lowBatteryWarningLevel">20</integer>
 
     <!-- Close low battery warning when battery level reaches this value -->
-    <integer name="config_lowBatteryCloseWarningLevel">20</integer>
+    <integer name="config_lowBatteryCloseWarningLevel">25</integer>
 
     <!-- Default color for notification LED. -->
     <color name="config_defaultNotificationColor">#ffffffff</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b3e111b..94cf116 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2132,7 +2132,6 @@
   <public type="attr" name="strokeLineJoin" />
   <public type="attr" name="clipToPath" />
   <public type="attr" name="requiredForProfile"/>
-  <public type="attr" name="pinned" />
   <public type="attr" name="colorControlNormal" />
   <public type="attr" name="colorControlActivated" />
   <public type="attr" name="colorButtonNormal" />
@@ -2193,6 +2192,8 @@
 
   <public type="style" name="Widget.FastScroll" />
   <public type="style" name="Widget.StackView" />
+  <public type="style" name="Widget.Toolbar" />
+  <public type="style" name="Widget.Toolbar.Button.Navigation" />
 
   <public type="style" name="Widget.Holo.FastScroll" />
   <public type="style" name="Widget.Holo.StackView" />
@@ -2339,6 +2340,8 @@
   <public type="style" name="Widget.Material.TabWidget" />
   <public type="style" name="Widget.Material.TextView" />
   <public type="style" name="Widget.Material.TextView.SpinnerItem" />
+  <public type="style" name="Widget.Material.Toolbar" />
+  <public type="style" name="Widget.Material.Toolbar.Button.Navigation" />
   <public type="style" name="Widget.Material.WebTextView" />
   <public type="style" name="Widget.Material.WebView" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d521746..a224cd5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1261,10 +1261,10 @@
          permission that an application must be granted by the user.  Instead, it
          is part of a mechanism that applications use to indicate to the system
          that they want to do scheduled background work.  -->
-    <string name="permlab_bindTaskService">run the application\'s scheduled background work</string>
+    <string name="permlab_bindJobService">run the application\'s scheduled background work</string>
     <!-- Description of an application permission, so that the user can understand
          what is being done if they are curious. -->
-    <string name="permdesc_bindTaskService">This permission allows the Android system to run the application in the background when requested.</string>
+    <string name="permdesc_bindJobService">This permission allows the Android system to run the application in the background when requested.</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_diagnostic">read/write to resources owned by diag</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 3d73995..92cce25 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -646,6 +646,14 @@
         <item name="maxWidth">180dip</item>
     </style>
 
+    <style name="Widget.Material.Toolbar" parent="Widget.Toolbar">
+        <item name="android:navigationButtonStyle">@android:style/Widget.Material.Toolbar.Button.Navigation</item>
+    </style>
+
+    <style name="Widget.Material.Toolbar.Button.Navigation" parent="Widget.Toolbar.Button.Navigation">
+        <item name="android:background">?attr/selectableItemBackgroundBorderless</item>
+    </style>
+
     <style name="Widget.Material.WebTextView" parent="Widget.WebTextView"/>
 
     <style name="Widget.Material.WebView" parent="Widget.WebView"/>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index c14d7fc9..1304d2b 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -321,6 +321,8 @@
         <item name="actionModeFindDrawable">@drawable/ic_menu_find_material</item>
         <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_material</item>
 
+        <item name="toolbarStyle">@style/Widget.Material.Toolbar</item>
+
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Widget.Material.ButtonBar</item>
@@ -667,6 +669,8 @@
         <item name="actionModeFindDrawable">@drawable/ic_menu_find_material</item>
         <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_material</item>
 
+        <item name="toolbarStyle">@style/Widget.Material.Toolbar</item>
+
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Widget.Material.Light.ButtonBar</item>
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 4623fa8..0d70e75 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -68,6 +68,8 @@
 
     private float mStartingX;
     private float mStartingY;
+    private float mClampedStartingX;
+    private float mClampedStartingY;
 
     // Hardware rendering properties.
     private CanvasProperty<Paint> mPropPaint;
@@ -112,6 +114,7 @@
     public Ripple(RippleDrawable owner, Rect bounds, float startingX, float startingY) {
         mOwner = owner;
         mBounds = bounds;
+
         mStartingX = startingX;
         mStartingY = startingY;
     }
@@ -131,6 +134,23 @@
         mOuterX = 0;
         mOuterY = 0;
         mDensity = density;
+
+        clampStartingPosition();
+    }
+
+    private void clampStartingPosition() {
+        final float dX = mStartingX - mBounds.exactCenterX();
+        final float dY = mStartingY - mBounds.exactCenterY();
+        final float r = mOuterRadius;
+        if (dX * dX + dY * dY > r * r) {
+            // Point is outside the circle, clamp to the circumference.
+            final double angle = Math.atan2(dY, dX);
+            mClampedStartingX = (float) (Math.cos(angle) * r);
+            mClampedStartingY = (float) (Math.sin(angle) * r);
+        } else {
+            mClampedStartingX = mStartingX;
+            mClampedStartingY = mStartingY;
+        }
     }
 
     public void onHotspotBoundsChanged() {
@@ -138,6 +158,8 @@
             final float halfWidth = mBounds.width() / 2.0f;
             final float halfHeight = mBounds.height() / 2.0f;
             mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
+
+            clampStartingPosition();
         }
     }
 
@@ -247,8 +269,10 @@
         final int alpha = (int) (paintAlpha * mOpacity + 0.5f);
         final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
         if (alpha > 0 && radius > 0) {
-            final float x = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
-            final float y = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
+            final float x = MathUtils.lerp(
+                    mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
+            final float y = MathUtils.lerp(
+                    mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
             p.setAlpha(alpha);
             p.setStyle(Style.FILL);
             c.drawCircle(x, y, radius, p);
@@ -277,6 +301,8 @@
     public void move(float x, float y) {
         mStartingX = x;
         mStartingY = y;
+
+        clampStartingPosition();
     }
 
     /**
@@ -361,8 +387,10 @@
             int inflectionOpacity) {
         mPendingAnimations.clear();
 
-        final float startX = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
-        final float startY = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
+        final float startX = MathUtils.lerp(
+                mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
+        final float startY = MathUtils.lerp(
+                mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
         final Paint outerPaint = new Paint();
         outerPaint.setAntiAlias(true);
         outerPaint.setColor(mColor);
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index e37fbeb..0512ecc 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -48,22 +48,41 @@
  * A touch feedback drawable may contain multiple child layers, including a
  * special mask layer that is not drawn to the screen. A single layer may be set
  * as the mask by specifying its android:id value as {@link android.R.id#mask}.
+ * <pre>
+ * <code>&lt!-- A red ripple masked against an opaque rectangle. --/>
+ * &ltripple android:color="#ffff0000">
+ *   &ltitem android:id="@android:id/mask"
+ *         android:drawable="#ffffffff" />
+ * &ltripple /></code>
+ * </pre>
  * <p>
  * If a mask layer is set, the ripple effect will be masked against that layer
- * before it is blended onto the composite of the remaining child layers.
+ * before it is drawn over the composite of the remaining child layers.
  * <p>
- * If no mask layer is set, the ripple effect is simply blended onto the
- * composite of the child layers using the specified
- * {@link android.R.styleable#RippleDrawable_tintMode}.
+ * If no mask layer is set, the ripple effect is masked against the composite
+ * of the child layers.
+ * <pre>
+ * <code>&lt!-- A blue ripple drawn atop a green rectangle. --/>
+ * &ltripple android:color="#ff00ff00">
+ *   &ltitem android:drawable="#ff0000ff" />
+ * &ltripple />
+ *
+ * &lt!-- A red ripple drawn atop a drawable resource. --/>
+ * &ltripple android:color="#ff00ff00">
+ *   &ltitem android:drawable="@drawable/my_drawable" />
+ * &ltripple /></code>
+ * </pre>
  * <p>
  * If no child layers or mask is specified and the ripple is set as a View
- * background, the ripple will be blended onto the first available parent
- * background within the View's hierarchy using the specified
- * {@link android.R.styleable#RippleDrawable_tintMode}. In this case, the
- * drawing region may extend outside of the Drawable bounds.
+ * background, the ripple will be drawn atop the first available parent
+ * background within the View's hierarchy. In this case, the drawing region
+ * may extend outside of the Drawable bounds.
+ * <pre>
+ * <code>&lt!-- An unbounded green ripple. --/>
+ * &ltripple android:color="#ff0000ff" /></code>
+ * </pre>
  *
- * @attr ref android.R.styleable#DrawableStates_state_focused
- * @attr ref android.R.styleable#DrawableStates_state_pressed
+ * @attr ref android.R.styleable#RippleDrawable_color
  */
 public class RippleDrawable extends LayerDrawable {
     private static final String LOG_TAG = RippleDrawable.class.getSimpleName();
@@ -188,8 +207,8 @@
         setActive(active && enabled);
 
         // Update the paint color. Only applicable when animated in software.
-        if (mRipplePaint != null && mState.mTint != null) {
-            final ColorStateList stateList = mState.mTint;
+        if (mRipplePaint != null && mState.mColor != null) {
+            final ColorStateList stateList = mState.mColor;
             final int newColor = stateList.getColorForState(stateSet, 0);
             final int oldColor = mRipplePaint.getColor();
             if (oldColor != newColor) {
@@ -248,10 +267,8 @@
         return true;
     }
 
-    @Override
-    public void setTint(ColorStateList tint, Mode tintMode) {
-        mState.mTint = tint;
-        mState.setTintMode(tintMode);
+    public void setColor(ColorStateList color) {
+        mState.mColor = color;
         invalidateSelf();
     }
 
@@ -312,22 +329,15 @@
         // Extract the theme attributes, if any.
         state.mTouchThemeAttrs = a.extractThemeAttrs();
 
-        final ColorStateList tint = a.getColorStateList(R.styleable.RippleDrawable_tint);
-        if (tint != null) {
-            mState.mTint = tint;
+        final ColorStateList color = a.getColorStateList(R.styleable.RippleDrawable_color);
+        if (color != null) {
+            mState.mColor = color;
         }
 
-        final int tintMode = a.getInt(R.styleable.RippleDrawable_tintMode, -1);
-        if (tintMode != -1) {
-            mState.setTintMode(Drawable.parseTintMode(tintMode, Mode.SRC_ATOP));
-        }
-
-        mState.mPinned = a.getBoolean(R.styleable.RippleDrawable_pinned, mState.mPinned);
-
         // If we're not waiting on a theme, verify required attributes.
-        if (state.mTouchThemeAttrs == null && mState.mTint == null) {
+        if (state.mTouchThemeAttrs == null && mState.mColor == null) {
             throw new XmlPullParserException(a.getPositionDescription() +
-                    ": <ripple> requires a valid tint attribute");
+                    ": <ripple> requires a valid color attribute");
         }
     }
 
@@ -372,11 +382,6 @@
 
     @Override
     public void setHotspot(float x, float y) {
-        if (mState.mPinned && !circleContains(mHotspotBounds, x, y)) {
-            x = mHotspotBounds.exactCenterX();
-            y = mHotspotBounds.exactCenterY();
-        }
-
         if (mHotspot == null) {
             mHotspot = new Ripple(this, mHotspotBounds, x, y);
 
@@ -388,18 +393,6 @@
         }
     }
 
-    private boolean circleContains(Rect bounds, float x, float y) {
-        final float pX = bounds.exactCenterX() - x;
-        final float pY = bounds.exactCenterY() - y;
-        final double pointRadius = Math.sqrt(pX * pX + pY * pY);
-
-        final float bX = bounds.width() / 2.0f;
-        final float bY = bounds.height() / 2.0f;
-        final double boundsRadius = Math.sqrt(bX * bX + bY * bY);
-
-        return pointRadius < boundsRadius;
-    }
-
     /**
      * Creates an active hotspot at the specified location.
      */
@@ -417,7 +410,7 @@
             mHotspot = new Ripple(this, mHotspotBounds, x, y);
         }
 
-        final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+        final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
         mHotspot.setup(mState.mMaxRadius, color, mDensity);
         mHotspot.enter();
 
@@ -485,8 +478,10 @@
         final int contentLayer = drawNonMaskContent ?
                 drawContentLayer(canvas, bounds, SRC_OVER) : -1;
 
-        // Next, try to draw the ripples (into a layer if necessary).
-        final int rippleLayer = drawRippleLayer(canvas, bounds, mState.mTintXfermode);
+        // Next, try to draw the ripples (into a layer if necessary). If we need
+        // to mask against the underlying content, set the xfermode to SRC_ATOP.
+        final PorterDuffXfermode xfermode = (hasMask || !drawNonMaskContent) ? SRC_OVER : SRC_ATOP;
+        final int rippleLayer = drawRippleLayer(canvas, bounds, xfermode);
 
         // If we have ripples and a non-opaque mask, draw the masking layer.
         if (rippleLayer >= 0 && drawMask) {
@@ -533,14 +528,27 @@
     }
 
     private int drawContentLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
-        // TODO: We don't need a layer if all the content is opaque.
-        final Paint maskingPaint = getMaskingPaint(mode);
-        final int restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
-                bounds.right, bounds.bottom, maskingPaint);
-
-        // Draw everything except the mask.
         final ChildDrawable[] array = mLayerState.mChildren;
         final int count = mLayerState.mNum;
+
+        // We don't need a layer if we don't expect to draw any ripples, we have
+        // an explicit mask, or if the non-mask content is all opaque.
+        boolean needsLayer = false;
+        if (mAnimatingRipplesCount > 0 && mMask == null) {
+            for (int i = 0; i < count; i++) {
+                if (array[i].mId != R.id.mask
+                        && array[i].mDrawable.getOpacity() != PixelFormat.OPAQUE) {
+                    needsLayer = true;
+                    break;
+                }
+            }
+        }
+
+        final Paint maskingPaint = getMaskingPaint(mode);
+        final int restoreToCount = needsLayer ? canvas.saveLayer(bounds.left, bounds.top,
+                bounds.right, bounds.bottom, maskingPaint) : -1;
+
+        // Draw everything except the mask.
         for (int i = 0; i < count; i++) {
             if (array[i].mId != R.id.mask) {
                 array[i].mDrawable.draw(canvas);
@@ -559,8 +567,8 @@
         // Separate the ripple color and alpha channel. The alpha will be
         // applied when we merge the ripples down to the canvas.
         final int rippleARGB;
-        if (mState.mTint != null) {
-            rippleARGB = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+        if (mState.mColor != null) {
+            rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
         } else {
             rippleARGB = Color.TRANSPARENT;
         }
@@ -665,31 +673,19 @@
 
     static class RippleState extends LayerState {
         int[] mTouchThemeAttrs;
-        ColorStateList mTint = null;
-        PorterDuffXfermode mTintXfermode = SRC_ATOP;
+        ColorStateList mColor = null;
         int mMaxRadius = RADIUS_AUTO;
-        boolean mPinned = false;
 
         public RippleState(RippleState orig, RippleDrawable owner, Resources res) {
             super(orig, owner, res);
 
             if (orig != null) {
                 mTouchThemeAttrs = orig.mTouchThemeAttrs;
-                mTint = orig.mTint;
-                mTintXfermode = orig.mTintXfermode;
+                mColor = orig.mColor;
                 mMaxRadius = orig.mMaxRadius;
-                mPinned = orig.mPinned;
             }
         }
 
-        public void setTintMode(Mode mode) {
-            mTintXfermode = new PorterDuffXfermode(mode);
-        }
-
-        public PorterDuffXfermode getTintXfermode() {
-            return mTintXfermode;
-        }
-
         @Override
         public boolean canApplyTheme() {
             return mTouchThemeAttrs != null || super.canApplyTheme();
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
new file mode 100644
index 0000000..d4fdbf3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png
deleted file mode 100644
index 6cd1176..0000000
--- a/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
new file mode 100644
index 0000000..9fc1a3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png
deleted file mode 100644
index 7237f09..0000000
--- a/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
new file mode 100644
index 0000000..f38de93
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png
deleted file mode 100644
index 8d56a1d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
new file mode 100644
index 0000000..8194605
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png
deleted file mode 100644
index aed300b..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ripple_drawable.xml b/packages/SystemUI/res/drawable/ripple_drawable.xml
index d2bff42..af7941f 100644
--- a/packages/SystemUI/res/drawable/ripple_drawable.xml
+++ b/packages/SystemUI/res/drawable/ripple_drawable.xml
@@ -16,6 +16,4 @@
   -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:tint="?android:attr/colorControlHighlight"
-        android:tintMode="src_over"
-        android:pinned="true" />
+    android:color="?android:attr/colorControlHighlight" />
diff --git a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
index 463fee8..4245d49 100644
--- a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
+++ b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
@@ -20,4 +20,4 @@
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal|bottom"
     android:scaleType="fitXY"
-    android:src="@drawable/recents_nav_bar_background" />
\ No newline at end of file
+    android:src="@drawable/recents_lower_gradient" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 693d8c3..4028ec3 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -77,8 +77,9 @@
     <ImageButton android:id="@+id/settings_button"
         style="@android:style/Widget.Material.Button.Borderless"
         android:layout_toStartOf="@id/multi_user_switch"
-        android:layout_width="56dp"
+        android:layout_width="48dp"
         android:layout_height="@dimen/status_bar_header_height"
+        android:layout_marginStart="8dp"
         android:src="@drawable/ic_settings_24dp"
         android:contentDescription="@string/accessibility_desc_quick_settings"/>
 
@@ -86,14 +87,14 @@
         android:layout_width="wrap_content"
         android:layout_height="@dimen/status_bar_header_height"
         android:layout_toStartOf="@id/multi_user_switch"
-        android:layout_marginEnd="4dp"
+        android:layout_marginEnd="2dp"
         />
 
     <com.android.keyguard.CarrierText
         android:id="@+id/keyguard_carrier_text"
         android:layout_width="match_parent"
         android:layout_height="@dimen/status_bar_header_height_keyguard"
-        android:layout_marginLeft="8dp"
+        android:layout_marginLeft="16dp"
         android:layout_toStartOf="@id/system_icons_container"
         android:gravity="center_vertical"
         android:ellipsize="marquee"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 35bc7e3..f750ee2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -338,4 +338,7 @@
     <!-- The width of the region on the left/right edge of the screen for performing the camera/
          phone hints. -->
     <dimen name="edge_tap_area_width">48dp</dimen>
+
+    <!-- end margin for multi user switch in expanded quick settings -->
+    <dimen name="multi_user_switch_expanded_margin">8dp</dimen>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 76e88a5..147ff62 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -106,7 +106,7 @@
             // The height of the peek space relative to the stack height
             public static final float StackPeekHeightPct = 0.1f;
             // The min scale of the last card in the peek area
-            public static final float StackPeekMinScale = 0.9f;
+            public static final float StackPeekMinScale = 0.8f;
             // The number of cards we see in the peek space
             public static final int StackPeekNumCards = 3;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 8680786..96344d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -41,6 +41,8 @@
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsView;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Set;
 
@@ -79,6 +81,19 @@
     boolean mVisible;
     boolean mTaskLaunched;
 
+    private static Method sPropertyMethod;
+    static {
+        try {
+            Class<?> c = Class.forName("android.view.GLES20Canvas");
+            sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
+            if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
     // Broadcast receiver to handle messages from our RecentsService
     BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -139,21 +154,12 @@
         // Add the default no-recents layout
         if (stacks.size() == 1 && stacks.get(0).getTaskCount() == 0) {
             mEmptyView.setVisibility(View.VISIBLE);
-
-            // Dim the background even more
-            WindowManager.LayoutParams wlp = getWindow().getAttributes();
-            wlp.dimAmount = Constants.Values.Window.DarkBackgroundDim;
-            getWindow().setAttributes(wlp);
-            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         } else {
             mEmptyView.setVisibility(View.GONE);
-
-            // Un-dim the background
-            WindowManager.LayoutParams wlp = getWindow().getAttributes();
-            wlp.dimAmount = 0f;
-            getWindow().setAttributes(wlp);
-            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         }
+
+        // Dim the background
+        mRecentsView.setBackgroundColor(0x80000000);
     }
 
     /** Attempts to allocate and bind the search bar app widget */
@@ -277,6 +283,9 @@
         LayoutInflater inflater = LayoutInflater.from(this);
         mEmptyView = inflater.inflate(R.layout.recents_empty, mContainerView, false);
         mNavBarScrimView = inflater.inflate(R.layout.recents_nav_bar_scrim, mContainerView, false);
+        mNavBarScrimView.setLayoutParams(new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
 
         mContainerView = new FrameLayout(this);
         mContainerView.addView(mRecentsView);
@@ -296,6 +305,16 @@
         if (savedInstanceState != null) {
             onConfigurationChange();
         }
+
+        // XXX: Update the shadows
+        try {
+            sPropertyMethod.invoke(null, "ambientShadowStrength", String.valueOf(35f));
+            sPropertyMethod.invoke(null, "ambientRatio", String.valueOf(0.5f));
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            e.printStackTrace();
+        }
     }
 
     void onConfigurationChange() {
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 5830e37..8d9f8be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -156,10 +156,12 @@
         float boundedT = Math.max(t, -(numPeekCards + 1));
 
         // Set the scale relative to its position
+        int numFrontScaledCards = 3;
         float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
         float scaleRange = 1f - minScale;
-        float scaleInc = scaleRange / numPeekCards;
-        float scale = Math.max(minScale, Math.min(1f, 1f + (boundedT * scaleInc)));
+        float scaleInc = scaleRange / (numPeekCards + numFrontScaledCards);
+        float scale = Math.max(minScale, Math.min(1f, minScale + 
+            ((boundedT + (numPeekCards + 1)) * scaleInc)));
         float scaleYOffset = ((1f - scale) * mTaskRect.height()) / 2;
         transform.scale = scale;
 
@@ -171,6 +173,12 @@
             transform.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
         }
 
+        // Set the z translation
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        int minZ = config.taskViewTranslationZMinPx;
+        int incZ = config.taskViewTranslationZIncrementPx;
+        transform.translationZ = (int) Math.max(minZ, minZ + ((boundedT + numPeekCards) * incZ));
+
         // Set the alphas
         transform.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f;
 
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 632c816..5df5e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -142,8 +142,6 @@
     void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
                                              TaskViewTransform toTransform, int duration) {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        int minZ = config.taskViewTranslationZMinPx;
-        int incZ = config.taskViewTranslationZIncrementPx;
 
         // Update the bar view
         mBarView.updateViewPropertiesToTaskTransform(animateFromTransform, toTransform, duration);
@@ -153,14 +151,14 @@
             if (animateFromTransform != null) {
                 setTranslationY(animateFromTransform.translationY);
                 if (Constants.DebugFlags.App.EnableShadows) {
-                    setTranslationZ(Math.max(minZ, minZ + (animateFromTransform.t * incZ)));
+                    setTranslationZ(animateFromTransform.translationZ);
                 }
                 setScaleX(animateFromTransform.scale);
                 setScaleY(animateFromTransform.scale);
                 setAlpha(animateFromTransform.alpha);
             }
             if (Constants.DebugFlags.App.EnableShadows) {
-                animate().translationZ(Math.max(minZ, minZ + (toTransform.t * incZ)));
+                animate().translationZ(toTransform.translationZ);
             }
             animate().translationY(toTransform.translationY)
                     .scaleX(toTransform.scale)
@@ -179,7 +177,7 @@
         } else {
             setTranslationY(toTransform.translationY);
             if (Constants.DebugFlags.App.EnableShadows) {
-                setTranslationZ(Math.max(minZ, minZ + (toTransform.t * incZ)));
+                setTranslationZ(toTransform.translationZ);
             }
             setScaleX(toTransform.scale);
             setScaleY(toTransform.scale);
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 e6391a8..3c3ebd7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -22,6 +22,7 @@
 /* The transform state for a task view */
 public class TaskViewTransform {
     public int translationY = 0;
+    public int translationZ = 0;
     public float scale = 1f;
     public float alpha = 1f;
     public float dismissAlpha = 1f;
@@ -35,6 +36,7 @@
 
     public TaskViewTransform(TaskViewTransform o) {
         translationY = o.translationY;
+        translationZ = o.translationZ;
         scale = o.scale;
         alpha = o.alpha;
         dismissAlpha = o.dismissAlpha;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index 6819d9b..ce5ab5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -65,7 +65,7 @@
     }
 
     private void applyColor(Notification notification, StatusBarIconView view) {
-        if (notification.color != Notification.COLOR_DEFAULT) {
+        if (notification.color == Notification.COLOR_DEFAULT) {
             if (mNotificationColorUtil.isGrayscale(view.getDrawable())) {
                 view.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 865aeff..7837769 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -64,6 +64,8 @@
 
     private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT;
     private int mNormalWidth;
+    private int mPadding;
+    private int mMultiUserExpandedMargin;
 
     private ActivityStarter mActivityStarter;
     private BrightnessController mBrightnessController;
@@ -112,6 +114,10 @@
         mKeyguardHeight = getResources().getDimensionPixelSize(
                 R.dimen.status_bar_header_height_keyguard);
         mNormalWidth = getLayoutParams().width;
+        mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
+        mMultiUserExpandedMargin =
+                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
+
     }
 
     public void setActivityStarter(ActivityStarter activityStarter) {
@@ -139,6 +145,8 @@
             updateZTranslation();
             updateClickTargets();
             updateWidth();
+            updatePadding();
+            updateMultiUserSwitch();
             if (mQSPanel != null) {
                 mQSPanel.setExpanded(expanded && !overscrolled);
             }
@@ -229,6 +237,21 @@
         }
     }
 
+    private void updatePadding() {
+        boolean padded = !mKeyguardShowing || mExpanded;
+        int padding = padded ? mPadding : 0;
+        setPaddingRelative(padding, 0, padding, 0);
+    }
+
+    private void updateMultiUserSwitch() {
+        int marginEnd = !mKeyguardShowing || mExpanded ? mMultiUserExpandedMargin : 0;
+        MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
+        if (marginEnd != lp.getMarginEnd()) {
+            lp.setMarginEnd(marginEnd);
+            mMultiUserSwitch.setLayoutParams(lp);
+        }
+    }
+
     public void setExpansion(float height) {
         height = (height - mCollapsedHeight) * EXPANSION_RUBBERBAND_FACTOR + mCollapsedHeight;
         if (height < mCollapsedHeight) {
@@ -274,6 +297,8 @@
         updateWidth();
         updateVisibilities();
         updateZTranslation();
+        updatePadding();
+        updateMultiUserSwitch();
     }
 
     public void setUserInfoController(UserInfoController userInfoController) {
diff --git a/services/core/java/com/android/server/MountServiceIdler.java b/services/core/java/com/android/server/MountServiceIdler.java
index 61790826..bcb6e9e 100644
--- a/services/core/java/com/android/server/MountServiceIdler.java
+++ b/services/core/java/com/android/server/MountServiceIdler.java
@@ -18,32 +18,32 @@
 
 import java.util.Calendar;
 
-import android.app.task.Task;
-import android.app.task.TaskManager;
-import android.app.task.TaskParams;
-import android.app.task.TaskService;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.util.Slog;
 
-public class MountServiceIdler extends TaskService {
+public class MountServiceIdler extends JobService {
     private static final String TAG = "MountServiceIdler";
 
     private static ComponentName sIdleService =
             new ComponentName(MountServiceIdler.class.getPackage().getName(),
                     MountServiceIdler.class.getName());
 
-    private static int MOUNT_TASK_ID = 808;
+    private static int MOUNT_JOB_ID = 808;
 
     private boolean mStarted;
-    private TaskParams mTaskParams;
+    private JobParameters mJobParams;
     private Runnable mFinishCallback = new Runnable() {
         @Override
         public void run() {
             Slog.i(TAG, "Got mount service completion callback");
             synchronized (mFinishCallback) {
                 if (mStarted) {
-                    taskFinished(mTaskParams, false);
+                    jobFinished(mJobParams, false);
                     mStarted = false;
                 }
             }
@@ -53,12 +53,12 @@
     };
 
     @Override
-    public boolean onStartTask(TaskParams params) {
+    public boolean onStartJob(JobParameters params) {
         // The mount service will run an fstrim operation asynchronously
         // on a designated separate thread, so we provide it with a callback
         // that lets us cleanly end our idle timeslice.  It's safe to call
         // finishIdle() from any thread.
-        mTaskParams = params;
+        mJobParams = params;
         MountService ms = MountService.sSelf;
         if (ms != null) {
             synchronized (mFinishCallback) {
@@ -70,9 +70,9 @@
     }
 
     @Override
-    public boolean onStopTask(TaskParams params) {
+    public boolean onStopJob(JobParameters params) {
         // Once we kick off the fstrim we aren't actually interruptible; just note
-        // that we don't need to call taskFinished(), and let everything happen in
+        // that we don't need to call jobFinished(), and let everything happen in
         // the callback from the mount service.
         synchronized (mFinishCallback) {
             mStarted = false;
@@ -84,12 +84,12 @@
      * Schedule the idle job that will ping the mount service
      */
     public static void scheduleIdlePass(Context context) {
-        TaskManager tm = (TaskManager) context.getSystemService(Context.TASK_SERVICE);
+        JobScheduler tm = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
 
         Calendar calendar = tomorrowMidnight();
         final long timeToMidnight = calendar.getTimeInMillis() - System.currentTimeMillis();
 
-        Task.Builder builder = new Task.Builder(MOUNT_TASK_ID, sIdleService);
+        JobInfo.Builder builder = new JobInfo.Builder(MOUNT_JOB_ID, sIdleService);
         builder.setRequiresDeviceIdle(true);
         builder.setRequiresCharging(true);
         builder.setMinimumLatency(timeToMidnight);
diff --git a/services/core/java/com/android/server/task/TaskCompletedListener.java b/services/core/java/com/android/server/job/JobCompletedListener.java
similarity index 62%
rename from services/core/java/com/android/server/task/TaskCompletedListener.java
rename to services/core/java/com/android/server/job/JobCompletedListener.java
index c53f5ca..a7af9cd 100644
--- a/services/core/java/com/android/server/task/TaskCompletedListener.java
+++ b/services/core/java/com/android/server/job/JobCompletedListener.java
@@ -14,19 +14,19 @@
  * limitations under the License
  */
 
-package com.android.server.task;
+package com.android.server.job;
 
-import com.android.server.task.controllers.TaskStatus;
+import com.android.server.job.controllers.JobStatus;
 
 /**
- * Used for communication between {@link com.android.server.task.TaskServiceContext} and the
- * {@link com.android.server.task.TaskManagerService}.
+ * Used for communication between {@link com.android.server.job.JobServiceContext} and the
+ * {@link com.android.server.job.JobSchedulerService}.
  */
-public interface TaskCompletedListener {
+public interface JobCompletedListener {
 
     /**
-     * Callback for when a task is completed.
-     * @param needsReschedule Whether the implementing class should reschedule this task.
+     * Callback for when a job is completed.
+     * @param needsReschedule Whether the implementing class should reschedule this job.
      */
-    public void onTaskCompleted(TaskStatus taskStatus, boolean needsReschedule);
+    public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule);
 }
diff --git a/services/core/java/com/android/server/task/TaskMapReadFinishedListener.java b/services/core/java/com/android/server/job/JobMapReadFinishedListener.java
similarity index 68%
rename from services/core/java/com/android/server/task/TaskMapReadFinishedListener.java
rename to services/core/java/com/android/server/job/JobMapReadFinishedListener.java
index c68d8db..f3e77e6 100644
--- a/services/core/java/com/android/server/task/TaskMapReadFinishedListener.java
+++ b/services/core/java/com/android/server/job/JobMapReadFinishedListener.java
@@ -14,21 +14,21 @@
  * limitations under the License
  */
 
-package com.android.server.task;
+package com.android.server.job;
 
 import java.util.List;
 
-import com.android.server.task.controllers.TaskStatus;
+import com.android.server.job.controllers.JobStatus;
 
 /**
- * Callback definition for I/O thread to let the TaskManagerService know when
+ * Callback definition for I/O thread to let the JobManagerService know when
  * I/O read has completed. Done this way so we don't stall the main thread on
  * boot.
  */
-public interface TaskMapReadFinishedListener {
+public interface JobMapReadFinishedListener {
 
     /**
-     * Called by the {@link TaskStore} at boot, when the disk read is finished.
+     * Called by the {@link JobStore} at boot, when the disk read is finished.
      */
-    public void onTaskMapReadFinished(List<TaskStatus> tasks);
+    public void onJobMapReadFinished(List<JobStatus> jobs);
 }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
new file mode 100644
index 0000000..0e9a9cc
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -0,0 +1,764 @@
+/*
+ * 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.job;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.job.IJobScheduler;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.server.job.controllers.BatteryController;
+import com.android.server.job.controllers.ConnectivityController;
+import com.android.server.job.controllers.IdleController;
+import com.android.server.job.controllers.JobStatus;
+import com.android.server.job.controllers.StateController;
+import com.android.server.job.controllers.TimeController;
+
+import java.util.LinkedList;
+
+/**
+ * Responsible for taking jobs representing work to be performed by a client app, and determining
+ * based on the criteria specified when that job should be run against the client application's
+ * endpoint.
+ * Implements logic for scheduling, and rescheduling jobs. The JobSchedulerService knows nothing
+ * about constraints, or the state of active jobs. It receives callbacks from the various
+ * controllers and completed jobs and operates accordingly.
+ *
+ * Note on locking: Any operations that manipulate {@link #mJobs} need to lock on that object.
+ * Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}.
+ * @hide
+ */
+public class JobSchedulerService extends com.android.server.SystemService
+        implements StateChangedListener, JobCompletedListener, JobMapReadFinishedListener {
+    // TODO: Switch this off for final version.
+    static final boolean DEBUG = true;
+    /** The number of concurrent jobs we run at one time. */
+    private static final int MAX_JOB_CONTEXTS_COUNT = 3;
+    static final String TAG = "JobManagerService";
+    /** Master list of jobs. */
+    private final JobStore mJobs;
+
+    static final int MSG_JOB_EXPIRED = 0;
+    static final int MSG_CHECK_JOB = 1;
+
+    // Policy constants
+    /**
+     * Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
+     * early.
+     */
+    private static final int MIN_IDLE_COUNT = 1;
+    /**
+     * Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
+     * things early.
+     */
+    private static final int MIN_CONNECTIVITY_COUNT = 2;
+    /**
+     * Minimum # of jobs (with no particular constraints) for which the JMS will be happy running
+     * some work early.
+     */
+    private static final int MIN_READY_JOBS_COUNT = 4;
+
+    /**
+     * Track Services that have currently active or pending jobs. The index is provided by
+     * {@link JobStatus#getServiceToken()}
+     */
+    private final List<JobServiceContext> mActiveServices = new LinkedList<JobServiceContext>();
+    /** List of controllers that will notify this service of updates to jobs. */
+    private List<StateController> mControllers;
+    /**
+     * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
+     * when ready to execute them.
+     */
+    private final LinkedList<JobStatus> mPendingJobs = new LinkedList<JobStatus>();
+
+    private final JobHandler mHandler;
+    private final JobSchedulerStub mJobSchedulerStub;
+    /**
+     * Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
+     * still clean up. On reinstall the package will have a new uid.
+     */
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Slog.d(TAG, "Receieved: " + intent.getAction());
+            if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+                int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
+                }
+                cancelJobsForUid(uidRemoved);
+            } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing jobs for user: " + userId);
+                }
+                cancelJobsForUser(userId);
+            }
+        }
+    };
+
+    /**
+     * Entry point from client to schedule the provided job.
+     * This cancels the job if it's already been scheduled, and replaces it with the one provided.
+     * @param job JobInfo object containing execution parameters
+     * @param uId The package identifier of the application this job is for.
+     * @param canPersistJob Whether or not the client has the appropriate permissions for
+     *                       persisting this job.
+     * @return Result of this operation. See <code>JobScheduler#RESULT_*</code> return codes.
+     */
+    public int schedule(JobInfo job, int uId, boolean canPersistJob) {
+        JobStatus jobStatus = new JobStatus(job, uId, canPersistJob);
+        cancelJob(uId, job.getId());
+        startTrackingJob(jobStatus);
+        return JobScheduler.RESULT_SUCCESS;
+    }
+
+    public List<JobInfo> getPendingJobs(int uid) {
+        ArrayList<JobInfo> outList = new ArrayList<JobInfo>();
+        synchronized (mJobs) {
+            for (JobStatus job : mJobs.getJobs()) {
+                if (job.getUid() == uid) {
+                    outList.add(job.getJob());
+                }
+            }
+        }
+        return outList;
+    }
+
+    private void cancelJobsForUser(int userHandle) {
+        synchronized (mJobs) {
+            List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
+            for (JobStatus toRemove : jobsForUser) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Cancelling: " + toRemove);
+                }
+                cancelJobLocked(toRemove);
+            }
+        }
+    }
+
+    /**
+     * Entry point from client to cancel all jobs originating from their uid.
+     * This will remove the job from the master list, and cancel the job if it was staged for
+     * execution or being executed.
+     * @param uid To check against for removal of a job.
+     */
+    public void cancelJobsForUid(int uid) {
+        // Remove from master list.
+        synchronized (mJobs) {
+            List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
+            for (JobStatus toRemove : jobsForUid) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Cancelling: " + toRemove);
+                }
+                cancelJobLocked(toRemove);
+            }
+        }
+    }
+
+    /**
+     * Entry point from client to cancel the job corresponding to the jobId provided.
+     * This will remove the job from the master list, and cancel the job if it was staged for
+     * execution or being executed.
+     * @param uid Uid of the calling client.
+     * @param jobId Id of the job, provided at schedule-time.
+     */
+    public void cancelJob(int uid, int jobId) {
+        JobStatus toCancel;
+        synchronized (mJobs) {
+            toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
+            if (toCancel != null) {
+                cancelJobLocked(toCancel);
+            }
+        }
+    }
+
+    private void cancelJobLocked(JobStatus cancelled) {
+        // Remove from store.
+        stopTrackingJob(cancelled);
+        // Remove from pending queue.
+        mPendingJobs.remove(cancelled);
+        // Cancel if running.
+        stopJobOnServiceContextLocked(cancelled);
+    }
+
+    /**
+     * Initializes the system service.
+     * <p>
+     * Subclasses must define a single argument constructor that accepts the context
+     * and passes it to super.
+     * </p>
+     *
+     * @param context The system server context.
+     */
+    public JobSchedulerService(Context context) {
+        super(context);
+        // Create the controllers.
+        mControllers = new LinkedList<StateController>();
+        mControllers.add(ConnectivityController.get(this));
+        mControllers.add(TimeController.get(this));
+        mControllers.add(IdleController.get(this));
+        mControllers.add(BatteryController.get(this));
+
+        mHandler = new JobHandler(context.getMainLooper());
+        mJobSchedulerStub = new JobSchedulerStub();
+        // Create the "runners".
+        for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
+            mActiveServices.add(
+                    new JobServiceContext(this, context.getMainLooper()));
+        }
+        mJobs = JobStore.initAndGet(this);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (PHASE_SYSTEM_SERVICES_READY == phase) {
+            // Register br for package removals and user removals.
+            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addDataScheme("package");
+            getContext().registerReceiverAsUser(
+                    mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+            final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+            getContext().registerReceiverAsUser(
+                    mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+        }
+    }
+
+    /**
+     * Called when we have a job status object that we need to insert in our
+     * {@link com.android.server.job.JobStore}, and make sure all the relevant controllers know
+     * about.
+     */
+    private void startTrackingJob(JobStatus jobStatus) {
+        boolean update;
+        synchronized (mJobs) {
+            update = mJobs.add(jobStatus);
+        }
+        for (StateController controller : mControllers) {
+            if (update) {
+                controller.maybeStopTrackingJob(jobStatus);
+            }
+            controller.maybeStartTrackingJob(jobStatus);
+        }
+    }
+
+    /**
+     * Called when we want to remove a JobStatus object that we've finished executing. Returns the
+     * object removed.
+     */
+    private boolean stopTrackingJob(JobStatus jobStatus) {
+        boolean removed;
+        synchronized (mJobs) {
+            // Remove from store as well as controllers.
+            removed = mJobs.remove(jobStatus);
+        }
+        if (removed) {
+            for (StateController controller : mControllers) {
+                controller.maybeStopTrackingJob(jobStatus);
+            }
+        }
+        return removed;
+    }
+
+    private boolean stopJobOnServiceContextLocked(JobStatus job) {
+        for (JobServiceContext jsc : mActiveServices) {
+            final JobStatus executing = jsc.getRunningJob();
+            if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
+                jsc.cancelExecutingJob();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param job JobStatus we are querying against.
+     * @return Whether or not the job represented by the status object is currently being run or
+     * is pending.
+     */
+    private boolean isCurrentlyActiveLocked(JobStatus job) {
+        for (JobServiceContext serviceContext : mActiveServices) {
+            final JobStatus running = serviceContext.getRunningJob();
+            if (running != null && running.matches(job.getUid(), job.getJobId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * A job is rescheduled with exponential back-off if the client requests this from their
+     * execution logic.
+     * A caveat is for idle-mode jobs, for which the idle-mode constraint will usurp the
+     * timeliness of the reschedule. For an idle-mode job, no deadline is given.
+     * @param failureToReschedule Provided job status that we will reschedule.
+     * @return A newly instantiated JobStatus with the same constraints as the last job except
+     * with adjusted timing constraints.
+     */
+    private JobStatus getRescheduleJobForFailure(JobStatus failureToReschedule) {
+        final long elapsedNowMillis = SystemClock.elapsedRealtime();
+        final JobInfo job = failureToReschedule.getJob();
+
+        final long initialBackoffMillis = job.getInitialBackoffMillis();
+        final int backoffAttempt = failureToReschedule.getNumFailures() + 1;
+        long newEarliestRuntimeElapsed = elapsedNowMillis;
+
+        switch (job.getBackoffPolicy()) {
+            case JobInfo.BackoffPolicy.LINEAR:
+                newEarliestRuntimeElapsed += initialBackoffMillis * backoffAttempt;
+                break;
+            default:
+                if (DEBUG) {
+                    Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
+                }
+            case JobInfo.BackoffPolicy.EXPONENTIAL:
+                newEarliestRuntimeElapsed +=
+                        Math.pow(initialBackoffMillis * 0.001, backoffAttempt) * 1000;
+                break;
+        }
+        newEarliestRuntimeElapsed =
+                Math.min(newEarliestRuntimeElapsed, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
+        return new JobStatus(failureToReschedule, newEarliestRuntimeElapsed,
+                JobStatus.NO_LATEST_RUNTIME, backoffAttempt);
+    }
+
+    /**
+     * Called after a periodic has executed so we can to re-add it. We take the last execution time
+     * of the job to be the time of completion (i.e. the time at which this function is called).
+     * This could be inaccurate b/c the job can run for as long as
+     * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
+     * to underscheduling at least, rather than if we had taken the last execution time to be the
+     * start of the execution.
+     * @return A new job representing the execution criteria for this instantiation of the
+     * recurring job.
+     */
+    private JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) {
+        final long elapsedNow = SystemClock.elapsedRealtime();
+        // Compute how much of the period is remaining.
+        long runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0);
+        long newEarliestRunTimeElapsed = elapsedNow + runEarly;
+        long period = periodicToReschedule.getJob().getIntervalMillis();
+        long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period;
+
+        if (DEBUG) {
+            Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
+                    newEarliestRunTimeElapsed/1000 + ", " + newLatestRuntimeElapsed/1000 + "]s");
+        }
+        return new JobStatus(periodicToReschedule, newEarliestRunTimeElapsed,
+                newLatestRuntimeElapsed, 0 /* backoffAttempt */);
+    }
+
+    // JobCompletedListener implementations.
+
+    /**
+     * A job just finished executing. We fetch the
+     * {@link com.android.server.job.controllers.JobStatus} from the store and depending on
+     * whether we want to reschedule we readd it to the controllers.
+     * @param jobStatus Completed job.
+     * @param needsReschedule Whether the implementing class should reschedule this job.
+     */
+    @Override
+    public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule) {
+        if (DEBUG) {
+            Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
+        }
+        if (!stopTrackingJob(jobStatus)) {
+            if (DEBUG) {
+                Slog.e(TAG, "Error removing job: could not find job to remove. Was job " +
+                        "removed while executing?");
+            }
+            return;
+        }
+        if (needsReschedule) {
+            JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
+            startTrackingJob(rescheduled);
+        } else if (jobStatus.getJob().isPeriodic()) {
+            JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
+            startTrackingJob(rescheduledPeriodic);
+        }
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    // StateChangedListener implementations.
+
+    /**
+     * Off-board work to our handler thread as quickly as possible, b/c this call is probably being
+     * made on the main thread.
+     * For now this takes the job and if it's ready to run it will run it. In future we might not
+     * provide the job, so that the StateChangedListener has to run through its list of jobs to
+     * see which are ready. This will further decouple the controllers from the execution logic.
+     */
+    @Override
+    public void onControllerStateChanged() {
+        // Post a message to to run through the list of jobs and start/stop any that are eligible.
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+    }
+
+    @Override
+    public void onRunJobNow(JobStatus jobStatus) {
+        mHandler.obtainMessage(MSG_JOB_EXPIRED, jobStatus).sendToTarget();
+    }
+
+    /**
+     * Disk I/O is finished, take the list of jobs we read from disk and add them to our
+     * {@link JobStore}.
+     * This is run on the {@link com.android.server.IoThread} instance, which is a separate thread,
+     * and is called once at boot.
+     */
+    @Override
+    public void onJobMapReadFinished(List<JobStatus> jobs) {
+        synchronized (mJobs) {
+            for (JobStatus js : jobs) {
+                if (mJobs.containsJobIdForUid(js.getJobId(), js.getUid())) {
+                    // An app with BOOT_COMPLETED *might* have decided to reschedule their job, in
+                    // the same amount of time it took us to read it from disk. If this is the case
+                    // we leave it be.
+                    continue;
+                }
+                startTrackingJob(js);
+            }
+        }
+    }
+
+    private class JobHandler extends Handler {
+
+        public JobHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case MSG_JOB_EXPIRED:
+                    synchronized (mJobs) {
+                        JobStatus runNow = (JobStatus) message.obj;
+                        if (!mPendingJobs.contains(runNow)) {
+                            mPendingJobs.add(runNow);
+                        }
+                    }
+                    queueReadyJobsForExecutionH();
+                    break;
+                case MSG_CHECK_JOB:
+                    // Check the list of jobs and run some of them if we feel inclined.
+                    maybeQueueReadyJobsForExecutionH();
+                    break;
+            }
+            maybeRunPendingJobsH();
+            // Don't remove JOB_EXPIRED in case one came along while processing the queue.
+            removeMessages(MSG_CHECK_JOB);
+        }
+
+        /**
+         * Run through list of jobs and execute all possible - at least one is expired so we do
+         * as many as we can.
+         */
+        private void queueReadyJobsForExecutionH() {
+            synchronized (mJobs) {
+                for (JobStatus job : mJobs.getJobs()) {
+                    if (isReadyToBeExecutedLocked(job)) {
+                        mPendingJobs.add(job);
+                    } else if (isReadyToBeCancelledLocked(job)) {
+                        stopJobOnServiceContextLocked(job);
+                    }
+                }
+            }
+        }
+
+        /**
+         * The state of at least one job has changed. Here is where we could enforce various
+         * policies on when we want to execute jobs.
+         * Right now the policy is such:
+         * If >1 of the ready jobs is idle mode we send all of them off
+         * if more than 2 network connectivity jobs are ready we send them all off.
+         * If more than 4 jobs total are ready we send them all off.
+         * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
+         */
+        private void maybeQueueReadyJobsForExecutionH() {
+            synchronized (mJobs) {
+                int idleCount = 0;
+                int backoffCount = 0;
+                int connectivityCount = 0;
+                List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
+                for (JobStatus job : mJobs.getJobs()) {
+                    if (isReadyToBeExecutedLocked(job)) {
+                        if (job.getNumFailures() > 0) {
+                            backoffCount++;
+                        }
+                        if (job.hasIdleConstraint()) {
+                            idleCount++;
+                        }
+                        if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
+                            connectivityCount++;
+                        }
+                        runnableJobs.add(job);
+                    } else if (isReadyToBeCancelledLocked(job)) {
+                        stopJobOnServiceContextLocked(job);
+                    }
+                }
+                if (backoffCount > 0 || idleCount >= MIN_IDLE_COUNT ||
+                        connectivityCount >= MIN_CONNECTIVITY_COUNT ||
+                        runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
+                    for (JobStatus job : runnableJobs) {
+                        mPendingJobs.add(job);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Criteria for moving a job into the pending queue:
+         *      - It's ready.
+         *      - It's not pending.
+         *      - It's not already running on a JSC.
+         */
+        private boolean isReadyToBeExecutedLocked(JobStatus job) {
+              return job.isReady() && !mPendingJobs.contains(job) && !isCurrentlyActiveLocked(job);
+        }
+
+        /**
+         * Criteria for cancelling an active job:
+         *      - It's not ready
+         *      - It's running on a JSC.
+         */
+        private boolean isReadyToBeCancelledLocked(JobStatus job) {
+            return !job.isReady() && isCurrentlyActiveLocked(job);
+        }
+
+        /**
+         * Reconcile jobs in the pending queue against available execution contexts.
+         * A controller can force a job into the pending queue even if it's already running, but
+         * here is where we decide whether to actually execute it.
+         */
+        private void maybeRunPendingJobsH() {
+            synchronized (mJobs) {
+                Iterator<JobStatus> it = mPendingJobs.iterator();
+                while (it.hasNext()) {
+                    JobStatus nextPending = it.next();
+                    JobServiceContext availableContext = null;
+                    for (JobServiceContext jsc : mActiveServices) {
+                        final JobStatus running = jsc.getRunningJob();
+                        if (running != null && running.matches(nextPending.getUid(),
+                                nextPending.getJobId())) {
+                            // Already running this tId for this uId, skip.
+                            availableContext = null;
+                            break;
+                        }
+                        if (jsc.isAvailable()) {
+                            availableContext = jsc;
+                        }
+                    }
+                    if (availableContext != null) {
+                        if (!availableContext.executeRunnableJob(nextPending)) {
+                            if (DEBUG) {
+                                Slog.d(TAG, "Error executing " + nextPending);
+                            }
+                            mJobs.remove(nextPending);
+                        }
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Binder stub trampoline implementation
+     */
+    final class JobSchedulerStub extends IJobScheduler.Stub {
+        /** Cache determination of whether a given app can persist jobs
+         * key is uid of the calling app; value is undetermined/true/false
+         */
+        private final SparseArray<Boolean> mPersistCache = new SparseArray<Boolean>();
+
+        // Enforce that only the app itself (or shared uid participant) can schedule a
+        // job that runs one of the app's services, as well as verifying that the
+        // named service properly requires the BIND_JOB_SERVICE permission
+        private void enforceValidJobRequest(int uid, JobInfo job) {
+            final PackageManager pm = getContext().getPackageManager();
+            final ComponentName service = job.getService();
+            try {
+                ServiceInfo si = pm.getServiceInfo(service, 0);
+                if (si.applicationInfo.uid != uid) {
+                    throw new IllegalArgumentException("uid " + uid +
+                            " cannot schedule job in " + service.getPackageName());
+                }
+                if (!JobService.PERMISSION_BIND.equals(si.permission)) {
+                    throw new IllegalArgumentException("Scheduled service " + service
+                            + " does not require android.permission.BIND_JOB_SERVICE permission");
+                }
+            } catch (NameNotFoundException e) {
+                throw new IllegalArgumentException("No such service: " + service);
+            }
+        }
+
+        private boolean canPersistJobs(int pid, int uid) {
+            // If we get this far we're good to go; all we need to do now is check
+            // whether the app is allowed to persist its scheduled work.
+            final boolean canPersist;
+            synchronized (mPersistCache) {
+                Boolean cached = mPersistCache.get(uid);
+                if (cached != null) {
+                    canPersist = cached.booleanValue();
+                } else {
+                    // Persisting jobs is tantamount to running at boot, so we permit
+                    // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
+                    // permission
+                    int result = getContext().checkPermission(
+                            android.Manifest.permission.RECEIVE_BOOT_COMPLETED, pid, uid);
+                    canPersist = (result == PackageManager.PERMISSION_GRANTED);
+                    mPersistCache.put(uid, canPersist);
+                }
+            }
+            return canPersist;
+        }
+
+        // IJobScheduler implementation
+        @Override
+        public int schedule(JobInfo job) throws RemoteException {
+            if (DEBUG) {
+                Slog.d(TAG, "Scheduling job: " + job);
+            }
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+
+            enforceValidJobRequest(uid, job);
+            final boolean canPersist = canPersistJobs(pid, uid);
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.schedule(job, uid, canPersist);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public List<JobInfo> getAllPendingJobs() throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return JobSchedulerService.this.getPendingJobs(uid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void cancelAll() throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                JobSchedulerService.this.cancelJobsForUid(uid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void cancel(int jobId) throws RemoteException {
+            final int uid = Binder.getCallingUid();
+
+            long ident = Binder.clearCallingIdentity();
+            try {
+                JobSchedulerService.this.cancelJob(uid, jobId);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * "dumpsys" infrastructure
+         */
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+            long identityToken = Binder.clearCallingIdentity();
+            try {
+                JobSchedulerService.this.dumpInternal(pw);
+            } finally {
+                Binder.restoreCallingIdentity(identityToken);
+            }
+        }
+    };
+
+    void dumpInternal(PrintWriter pw) {
+        synchronized (mJobs) {
+            pw.println("Registered jobs:");
+            if (mJobs.size() > 0) {
+                for (JobStatus job : mJobs.getJobs()) {
+                    job.dump(pw, "  ");
+                }
+            } else {
+                pw.println();
+                pw.println("No jobs scheduled.");
+            }
+            for (StateController controller : mControllers) {
+                pw.println();
+                controller.dumpControllerState(pw);
+            }
+            pw.println();
+            pw.println("Pending");
+            for (JobStatus jobStatus : mPendingJobs) {
+                pw.println(jobStatus.hashCode());
+            }
+            pw.println();
+            pw.println("Active jobs:");
+            for (JobServiceContext jsc : mActiveServices) {
+                if (jsc.isAvailable()) {
+                    continue;
+                } else {
+                    pw.println(jsc.getRunningJob().hashCode() + " for: " +
+                            (SystemClock.elapsedRealtime()
+                                    - jsc.getExecutionStartTimeElapsed())/1000 + "s " +
+                            "timeout: " + jsc.getTimeoutElapsed());
+                }
+            }
+        }
+        pw.println();
+    }
+}
diff --git a/services/core/java/com/android/server/task/TaskServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
similarity index 66%
rename from services/core/java/com/android/server/task/TaskServiceContext.java
rename to services/core/java/com/android/server/job/JobServiceContext.java
index a21de88..92b643c 100644
--- a/services/core/java/com/android/server/task/TaskServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -14,12 +14,12 @@
  * limitations under the License
  */
 
-package com.android.server.task;
+package com.android.server.job;
 
 import android.app.ActivityManager;
-import android.app.task.ITaskCallback;
-import android.app.task.ITaskService;
-import android.app.task.TaskParams;
+import android.app.job.JobParameters;
+import android.app.job.IJobCallback;
+import android.app.job.IJobService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -39,32 +39,32 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.task.controllers.TaskStatus;
+import com.android.server.job.controllers.JobStatus;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * Handles client binding and lifecycle of a task. A task will only execute one at a time on an
+ * Handles client binding and lifecycle of a job. A job will only execute one at a time on an
  * instance of this class.
  */
-public class TaskServiceContext extends ITaskCallback.Stub implements ServiceConnection {
+public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection {
     private static final boolean DEBUG = true;
-    private static final String TAG = "TaskServiceContext";
-    /** Define the maximum # of tasks allowed to run on a service at once. */
-    private static final int defaultMaxActiveTasksPerService =
+    private static final String TAG = "JobServiceContext";
+    /** Define the maximum # of jobs allowed to run on a service at once. */
+    private static final int defaultMaxActiveJobsPerService =
             ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
-    /** Amount of time a task is allowed to execute for before being considered timed-out. */
+    /** Amount of time a job is allowed to execute for before being considered timed-out. */
     private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000;
-    /** Amount of time the TaskManager will wait for a response from an app for a message. */
+    /** Amount of time the JobScheduler will wait for a response from an app for a message. */
     private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
     /** String prefix for all wakelock names. */
-    private static final String TM_WAKELOCK_PREFIX = "*task*/";
+    private static final String JS_WAKELOCK_PREFIX = "*job*/";
 
     private static final String[] VERB_STRINGS = {
             "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_PENDING"
     };
 
-    // States that a task occupies while interacting with the client.
+    // States that a job occupies while interacting with the client.
     static final int VERB_BINDING = 0;
     static final int VERB_STARTING = 1;
     static final int VERB_EXECUTING = 2;
@@ -75,30 +75,30 @@
     private static final int MSG_TIMEOUT = 0;
     /** Received a callback from client. */
     private static final int MSG_CALLBACK = 1;
-    /** Run through list and start any ready tasks.*/
+    /** Run through list and start any ready jobs.*/
     private static final int MSG_SERVICE_BOUND = 2;
-    /** Cancel a task. */
+    /** Cancel a job. */
     private static final int MSG_CANCEL = 3;
-    /** Shutdown the Task. Used when the client crashes and we can't die gracefully.*/
+    /** Shutdown the job. Used when the client crashes and we can't die gracefully.*/
     private static final int MSG_SHUTDOWN_EXECUTION = 4;
 
     private final Handler mCallbackHandler;
-    /** Make callbacks to {@link TaskManagerService} to inform on task completion status. */
-    private final TaskCompletedListener mCompletedListener;
+    /** Make callbacks to {@link JobSchedulerService} to inform on job completion status. */
+    private final JobCompletedListener mCompletedListener;
     /** Used for service binding, etc. */
     private final Context mContext;
     private PowerManager.WakeLock mWakeLock;
 
     // Execution state.
-    private TaskParams mParams;
+    private JobParameters mParams;
     @VisibleForTesting
     int mVerb;
     private AtomicBoolean mCancelled = new AtomicBoolean();
 
-    /** All the information maintained about the task currently being executed. */
-    private TaskStatus mRunningTask;
+    /** All the information maintained about the job currently being executed. */
+    private JobStatus mRunningJob;
     /** Binder to the client service. */
-    ITaskService service;
+    IJobService service;
 
     private final Object mLock = new Object();
     /** Whether this context is free. */
@@ -109,45 +109,45 @@
     /** Track when job will timeout. */
     private long mTimeoutElapsed;
 
-    TaskServiceContext(TaskManagerService service, Looper looper) {
+    JobServiceContext(JobSchedulerService service, Looper looper) {
         this(service.getContext(), service, looper);
     }
 
     @VisibleForTesting
-    TaskServiceContext(Context context, TaskCompletedListener completedListener, Looper looper) {
+    JobServiceContext(Context context, JobCompletedListener completedListener, Looper looper) {
         mContext = context;
-        mCallbackHandler = new TaskServiceHandler(looper);
+        mCallbackHandler = new JobServiceHandler(looper);
         mCompletedListener = completedListener;
         mAvailable = true;
     }
 
     /**
-     * Give a task to this context for execution. Callers must first check {@link #isAvailable()}
+     * Give a job to this context for execution. Callers must first check {@link #isAvailable()}
      * to make sure this is a valid context.
-     * @param ts The status of the task that we are going to run.
-     * @return True if the task is valid and is running. False if the task cannot be executed.
+     * @param job The status of the job that we are going to run.
+     * @return True if the job is valid and is running. False if the job cannot be executed.
      */
-    boolean executeRunnableTask(TaskStatus ts) {
+    boolean executeRunnableJob(JobStatus job) {
         synchronized (mLock) {
             if (!mAvailable) {
                 Slog.e(TAG, "Starting new runnable but context is unavailable > Error.");
                 return false;
             }
 
-            mRunningTask = ts;
-            mParams = new TaskParams(ts.getTaskId(), ts.getExtras(), this);
+            mRunningJob = job;
+            mParams = new JobParameters(job.getJobId(), job.getExtras(), this);
             mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
 
             mVerb = VERB_BINDING;
-            final Intent intent = new Intent().setComponent(ts.getServiceComponent());
+            final Intent intent = new Intent().setComponent(job.getServiceComponent());
             boolean binding = mContext.bindServiceAsUser(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
-                    new UserHandle(ts.getUserId()));
+                    new UserHandle(job.getUserId()));
             if (!binding) {
                 if (DEBUG) {
-                    Slog.d(TAG, ts.getServiceComponent().getShortClassName() + " unavailable.");
+                    Slog.d(TAG, job.getServiceComponent().getShortClassName() + " unavailable.");
                 }
-                mRunningTask = null;
+                mRunningJob = null;
                 mParams = null;
                 mExecutionStartTimeElapsed = 0L;
                 return false;
@@ -157,13 +157,13 @@
         }
     }
 
-    /** Used externally to query the running task. Will return null if there is no task running. */
-    TaskStatus getRunningTask() {
-        return mRunningTask;
+    /** Used externally to query the running job. Will return null if there is no job running. */
+    JobStatus getRunningJob() {
+        return mRunningJob;
     }
 
-    /** Called externally when a task that was scheduled for execution should be cancelled. */
-    void cancelExecutingTask() {
+    /** Called externally when a job that was scheduled for execution should be cancelled. */
+    void cancelExecutingJob() {
         mCallbackHandler.obtainMessage(MSG_CANCEL).sendToTarget();
     }
 
@@ -185,29 +185,29 @@
     }
 
     @Override
-    public void taskFinished(int taskId, boolean reschedule) {
+    public void jobFinished(int jobId, boolean reschedule) {
         if (!verifyCallingUid()) {
             return;
         }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, taskId, reschedule ? 1 : 0)
+        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0)
                 .sendToTarget();
     }
 
     @Override
-    public void acknowledgeStopMessage(int taskId, boolean reschedule) {
+    public void acknowledgeStopMessage(int jobId, boolean reschedule) {
         if (!verifyCallingUid()) {
             return;
         }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, taskId, reschedule ? 1 : 0)
+        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0)
                 .sendToTarget();
     }
 
     @Override
-    public void acknowledgeStartMessage(int taskId, boolean ongoing) {
+    public void acknowledgeStartMessage(int jobId, boolean ongoing) {
         if (!verifyCallingUid()) {
             return;
         }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, taskId, ongoing ? 1 : 0).sendToTarget();
+        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, ongoing ? 1 : 0).sendToTarget();
     }
 
     /**
@@ -219,25 +219,25 @@
      */
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
-        if (!name.equals(mRunningTask.getServiceComponent())) {
+        if (!name.equals(mRunningJob.getServiceComponent())) {
             mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();
             return;
         }
-        this.service = ITaskService.Stub.asInterface(service);
+        this.service = IJobService.Stub.asInterface(service);
         // Remove all timeouts.
         mCallbackHandler.removeMessages(MSG_TIMEOUT);
         final PowerManager pm =
                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
-                TM_WAKELOCK_PREFIX + mRunningTask.getServiceComponent().getPackageName());
-        mWakeLock.setWorkSource(new WorkSource(mRunningTask.getUid()));
+                JS_WAKELOCK_PREFIX + mRunningJob.getServiceComponent().getPackageName());
+        mWakeLock.setWorkSource(new WorkSource(mRunningJob.getUid()));
         mWakeLock.setReferenceCounted(false);
         mWakeLock.acquire();
         mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
     }
 
     /**
-     * If the client service crashes we reschedule this task and clean up.
+     * If the client service crashes we reschedule this job and clean up.
      * @param name The concrete component name of the service whose
      */
     @Override
@@ -251,7 +251,7 @@
      * @return True if the binder calling is coming from the client we expect.
      */
     private boolean verifyCallingUid() {
-        if (mRunningTask == null || Binder.getCallingUid() != mRunningTask.getUid()) {
+        if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) {
             if (DEBUG) {
                 Slog.d(TAG, "Stale callback received, ignoring.");
             }
@@ -261,12 +261,12 @@
     }
 
     /**
-     * Handles the lifecycle of the TaskService binding/callbacks, etc. The convention within this
+     * Handles the lifecycle of the JobService binding/callbacks, etc. The convention within this
      * class is to append 'H' to each function name that can only be called on this handler. This
      * isn't strictly necessary because all of these functions are private, but helps clarity.
      */
-    private class TaskServiceHandler extends Handler {
-        TaskServiceHandler(Looper looper) {
+    private class JobServiceHandler extends Handler {
+        JobServiceHandler(Looper looper) {
             super(looper);
         }
 
@@ -278,7 +278,7 @@
                     break;
                 case MSG_CALLBACK:
                     if (DEBUG) {
-                        Slog.d(TAG, "MSG_CALLBACK of : " + mRunningTask + " v:" +
+                        Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob + " v:" +
                                 VERB_STRINGS[mVerb]);
                     }
                     removeMessages(MSG_TIMEOUT);
@@ -292,7 +292,7 @@
                         handleFinishedH(reschedule);
                     } else {
                         if (DEBUG) {
-                            Slog.d(TAG, "Unrecognised callback: " + mRunningTask);
+                            Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
                         }
                     }
                     break;
@@ -303,42 +303,42 @@
                     handleOpTimeoutH();
                     break;
                 case MSG_SHUTDOWN_EXECUTION:
-                    closeAndCleanupTaskH(true /* needsReschedule */);
+                    closeAndCleanupJobH(true /* needsReschedule */);
                     break;
                 default:
                     Log.e(TAG, "Unrecognised message: " + message);
             }
         }
 
-        /** Start the task on the service. */
+        /** Start the job on the service. */
         private void handleServiceBoundH() {
             if (mVerb != VERB_BINDING) {
-                Slog.e(TAG, "Sending onStartTask for a task that isn't pending. "
+                Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
                         + VERB_STRINGS[mVerb]);
-                closeAndCleanupTaskH(false /* reschedule */);
+                closeAndCleanupJobH(false /* reschedule */);
                 return;
             }
             if (mCancelled.get()) {
                 if (DEBUG) {
-                    Slog.d(TAG, "Task cancelled while waiting for bind to complete. "
-                            + mRunningTask);
+                    Slog.d(TAG, "Job cancelled while waiting for bind to complete. "
+                            + mRunningJob);
                 }
-                closeAndCleanupTaskH(true /* reschedule */);
+                closeAndCleanupJobH(true /* reschedule */);
                 return;
             }
             try {
                 mVerb = VERB_STARTING;
                 scheduleOpTimeOut();
-                service.startTask(mParams);
+                service.startJob(mParams);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error sending onStart message to '" +
-                        mRunningTask.getServiceComponent().getShortClassName() + "' ", e);
+                        mRunningJob.getServiceComponent().getShortClassName() + "' ", e);
             }
         }
 
         /**
          * State behaviours.
-         * VERB_STARTING   -> Successful start, change task to VERB_EXECUTING and post timeout.
+         * VERB_STARTING   -> Successful start, change job to VERB_EXECUTING and post timeout.
          *     _PENDING    -> Error
          *     _EXECUTING  -> Error
          *     _STOPPING   -> Error
@@ -348,7 +348,7 @@
                 case VERB_STARTING:
                     mVerb = VERB_EXECUTING;
                     if (!workOngoing) {
-                        // Task is finished already so fast-forward to handleFinished.
+                        // Job is finished already so fast-forward to handleFinished.
                         handleFinishedH(false);
                         return;
                     }
@@ -360,14 +360,14 @@
                     scheduleOpTimeOut();
                     break;
                 default:
-                    Log.e(TAG, "Handling started task but task wasn't starting! Was "
+                    Log.e(TAG, "Handling started job but job wasn't starting! Was "
                             + VERB_STRINGS[mVerb] + ".");
                     return;
             }
         }
 
         /**
-         * VERB_EXECUTING  -> Client called taskFinished(), clean up and notify done.
+         * VERB_EXECUTING  -> Client called jobFinished(), clean up and notify done.
          *     _STOPPING   -> Successful finish, clean up and notify done.
          *     _STARTING   -> Error
          *     _PENDING    -> Error
@@ -376,20 +376,20 @@
             switch (mVerb) {
                 case VERB_EXECUTING:
                 case VERB_STOPPING:
-                    closeAndCleanupTaskH(reschedule);
+                    closeAndCleanupJobH(reschedule);
                     break;
                 default:
-                    Slog.e(TAG, "Got an execution complete message for a task that wasn't being" +
+                    Slog.e(TAG, "Got an execution complete message for a job that wasn't being" +
                             "executed. Was " + VERB_STRINGS[mVerb] + ".");
             }
         }
 
         /**
-         * A task can be in various states when a cancel request comes in:
+         * A job can be in various states when a cancel request comes in:
          * VERB_BINDING    -> Cancelled before bind completed. Mark as cancelled and wait for
          *                    {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)}
          *     _STARTING   -> Mark as cancelled and wait for
-         *                    {@link TaskServiceContext#acknowledgeStartMessage(int, boolean)}
+         *                    {@link JobServiceContext#acknowledgeStartMessage(int, boolean)}
          *     _EXECUTING  -> call {@link #sendStopMessageH}}.
          *     _ENDING     -> No point in doing anything here, so we ignore.
          */
@@ -406,48 +406,48 @@
                     // Nada.
                     break;
                 default:
-                    Slog.e(TAG, "Cancelling a task without a valid verb: " + mVerb);
+                    Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb);
                     break;
             }
         }
 
         /** Process MSG_TIMEOUT here. */
         private void handleOpTimeoutH() {
-            if (Log.isLoggable(TaskManagerService.TAG, Log.DEBUG)) {
+            if (Log.isLoggable(JobSchedulerService.TAG, Log.DEBUG)) {
                 Log.d(TAG, "MSG_TIMEOUT of " +
-                        mRunningTask.getServiceComponent().getShortClassName() + " : "
-                        + mParams.getTaskId());
+                        mRunningJob.getServiceComponent().getShortClassName() + " : "
+                        + mParams.getJobId());
             }
 
-            final int taskId = mParams.getTaskId();
+            final int jobId = mParams.getJobId();
             switch (mVerb) {
                 case VERB_STARTING:
                     // Client unresponsive - wedged or failed to respond in time. We don't really
-                    // know what happened so let's log it and notify the TaskManager
+                    // know what happened so let's log it and notify the JobScheduler
                     // FINISHED/NO-RETRY.
-                    Log.e(TAG, "No response from client for onStartTask '" +
-                            mRunningTask.getServiceComponent().getShortClassName() + "' tId: "
-                            + taskId);
-                    closeAndCleanupTaskH(false /* needsReschedule */);
+                    Log.e(TAG, "No response from client for onStartJob '" +
+                            mRunningJob.getServiceComponent().getShortClassName() + "' tId: "
+                            + jobId);
+                    closeAndCleanupJobH(false /* needsReschedule */);
                     break;
                 case VERB_STOPPING:
-                    // At least we got somewhere, so fail but ask the TaskManager to reschedule.
-                    Log.e(TAG, "No response from client for onStopTask, '" +
-                            mRunningTask.getServiceComponent().getShortClassName() + "' tId: "
-                            + taskId);
-                    closeAndCleanupTaskH(true /* needsReschedule */);
+                    // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
+                    Log.e(TAG, "No response from client for onStopJob, '" +
+                            mRunningJob.getServiceComponent().getShortClassName() + "' tId: "
+                            + jobId);
+                    closeAndCleanupJobH(true /* needsReschedule */);
                     break;
                 case VERB_EXECUTING:
                     // Not an error - client ran out of time.
-                    Log.i(TAG, "Client timed out while executing (no taskFinished received)." +
+                    Log.i(TAG, "Client timed out while executing (no jobFinished received)." +
                             " sending onStop. "  +
-                            mRunningTask.getServiceComponent().getShortClassName() + "' tId: "
-                            + taskId);
+                            mRunningJob.getServiceComponent().getShortClassName() + "' tId: "
+                            + jobId);
                     sendStopMessageH();
                     break;
                 default:
-                    Log.e(TAG, "Handling timeout for an unknown active task state: "
-                            + mRunningTask);
+                    Log.e(TAG, "Handling timeout for an unknown active job state: "
+                            + mRunningJob);
                     return;
             }
         }
@@ -459,35 +459,35 @@
         private void sendStopMessageH() {
             mCallbackHandler.removeMessages(MSG_TIMEOUT);
             if (mVerb != VERB_EXECUTING) {
-                Log.e(TAG, "Sending onStopTask for a task that isn't started. " + mRunningTask);
-                closeAndCleanupTaskH(false /* reschedule */);
+                Log.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
+                closeAndCleanupJobH(false /* reschedule */);
                 return;
             }
             try {
                 mVerb = VERB_STOPPING;
                 scheduleOpTimeOut();
-                service.stopTask(mParams);
+                service.stopJob(mParams);
             } catch (RemoteException e) {
-                Log.e(TAG, "Error sending onStopTask to client.", e);
-                closeAndCleanupTaskH(false /* reschedule */);
+                Log.e(TAG, "Error sending onStopJob to client.", e);
+                closeAndCleanupJobH(false /* reschedule */);
             }
         }
 
         /**
-         * The provided task has finished, either by calling
-         * {@link android.app.task.TaskService#taskFinished(android.app.task.TaskParams, boolean)}
+         * The provided job has finished, either by calling
+         * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
          * or from acknowledging the stop message we sent. Either way, we're done tracking it and
          * we want to clean up internally.
          */
-        private void closeAndCleanupTaskH(boolean reschedule) {
+        private void closeAndCleanupJobH(boolean reschedule) {
             removeMessages(MSG_TIMEOUT);
             synchronized (mLock) {
                 mWakeLock.release();
-                mContext.unbindService(TaskServiceContext.this);
-                mCompletedListener.onTaskCompleted(mRunningTask, reschedule);
+                mContext.unbindService(JobServiceContext.this);
+                mCompletedListener.onJobCompleted(mRunningJob, reschedule);
 
                 mWakeLock = null;
-                mRunningTask = null;
+                mRunningJob = null;
                 mParams = null;
                 mVerb = -1;
                 mCancelled.set(false);
@@ -508,8 +508,8 @@
                     EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
             if (DEBUG) {
                 Slog.d(TAG, "Scheduling time out for '" +
-                        mRunningTask.getServiceComponent().getShortClassName() + "' tId: " +
-                        mParams.getTaskId() + ", in " + (timeoutMillis / 1000) + " s");
+                        mRunningJob.getServiceComponent().getShortClassName() + "' tId: " +
+                        mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
             }
             Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
             mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
new file mode 100644
index 0000000..5f22b34
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -0,0 +1,663 @@
+/*
+ * 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.job;
+
+import android.content.ComponentName;
+import android.app.job.JobInfo;
+import android.content.Context;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.AtomicFile;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.IoThread;
+import com.android.server.job.controllers.JobStatus;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+/**
+ * Maintain a list of classes, and accessor methods/logic for these jobs.
+ * This class offers the following functionality:
+ *     - When a job is added, it will determine if the job requirements have changed (update) and
+ *       whether the controllers need to be updated.
+ *     - Persists JobInfos, figures out when to to rewrite the JobInfo to disk.
+ *     - Handles rescheduling of jobs.
+ *       - When a periodic job is executed and must be re-added.
+ *       - When a job fails and the client requests that it be retried with backoff.
+ *       - This class <strong>is not</strong> thread-safe.
+ *
+ * Note on locking:
+ *      All callers to this class must <strong>lock on the class object they are calling</strong>.
+ *      This is important b/c {@link com.android.server.job.JobStore.WriteJobsMapToDiskRunnable}
+ *      and {@link com.android.server.job.JobStore.ReadJobMapFromDiskRunnable} lock on that
+ *      object.
+ */
+public class JobStore {
+    private static final String TAG = "JobStore";
+    private static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+    /** Threshold to adjust how often we want to write to the db. */
+    private static final int MAX_OPS_BEFORE_WRITE = 1;
+    final ArraySet<JobStatus> mJobSet;
+    final Context mContext;
+
+    private int mDirtyOperations;
+
+    private static final Object sSingletonLock = new Object();
+    private final AtomicFile mJobsFile;
+    /** Handler backed by IoThread for writing to disk. */
+    private final Handler mIoHandler = IoThread.getHandler();
+    private static JobStore sSingleton;
+
+    /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */
+    static JobStore initAndGet(JobSchedulerService jobManagerService) {
+        synchronized (sSingletonLock) {
+            if (sSingleton == null) {
+                sSingleton = new JobStore(jobManagerService.getContext(),
+                        Environment.getDataDirectory(), jobManagerService);
+            }
+            return sSingleton;
+        }
+    }
+
+    @VisibleForTesting
+    public static JobStore initAndGetForTesting(Context context, File dataDir,
+                                                 JobMapReadFinishedListener callback) {
+        return new JobStore(context, dataDir, callback);
+    }
+
+    private JobStore(Context context, File dataDir, JobMapReadFinishedListener callback) {
+        mContext = context;
+        mDirtyOperations = 0;
+
+        File systemDir = new File(dataDir, "system");
+        File jobDir = new File(systemDir, "job");
+        jobDir.mkdirs();
+        mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
+
+        mJobSet = new ArraySet<JobStatus>();
+
+        readJobMapFromDiskAsync(callback);
+    }
+
+    /**
+     * Add a job to the master list, persisting it if necessary. If the JobStatus already exists,
+     * it will be replaced.
+     * @param jobStatus Job to add.
+     * @return Whether or not an equivalent JobStatus was replaced by this operation.
+     */
+    public boolean add(JobStatus jobStatus) {
+        boolean replaced = mJobSet.remove(jobStatus);
+        mJobSet.add(jobStatus);
+        if (jobStatus.isPersisted()) {
+            maybeWriteStatusToDiskAsync();
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "Added job status to store: " + jobStatus);
+        }
+        return replaced;
+    }
+
+    /**
+     * Whether this jobStatus object already exists in the JobStore.
+     */
+    public boolean containsJobIdForUid(int jobId, int uId) {
+        for (JobStatus ts : mJobSet) {
+            if (ts.getUid() == uId && ts.getJobId() == jobId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public int size() {
+        return mJobSet.size();
+    }
+
+    /**
+     * Remove the provided job. Will also delete the job if it was persisted.
+     * @return Whether or not the job existed to be removed.
+     */
+    public boolean remove(JobStatus jobStatus) {
+        boolean removed = mJobSet.remove(jobStatus);
+        if (!removed) {
+            if (DEBUG) {
+                Slog.d(TAG, "Couldn't remove job: didn't exist: " + jobStatus);
+            }
+            return false;
+        }
+        maybeWriteStatusToDiskAsync();
+        return removed;
+    }
+
+    @VisibleForTesting
+    public void clear() {
+        mJobSet.clear();
+        maybeWriteStatusToDiskAsync();
+    }
+
+    public List<JobStatus> getJobsByUser(int userHandle) {
+        List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
+        Iterator<JobStatus> it = mJobSet.iterator();
+        while (it.hasNext()) {
+            JobStatus ts = it.next();
+            if (UserHandle.getUserId(ts.getUid()) == userHandle) {
+                matchingJobs.add(ts);
+            }
+        }
+        return matchingJobs;
+    }
+
+    /**
+     * @param uid Uid of the requesting app.
+     * @return All JobStatus objects for a given uid from the master list.
+     */
+    public List<JobStatus> getJobsByUid(int uid) {
+        List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
+        Iterator<JobStatus> it = mJobSet.iterator();
+        while (it.hasNext()) {
+            JobStatus ts = it.next();
+            if (ts.getUid() == uid) {
+                matchingJobs.add(ts);
+            }
+        }
+        return matchingJobs;
+    }
+
+    /**
+     * @param uid Uid of the requesting app.
+     * @param jobId Job id, specified at schedule-time.
+     * @return the JobStatus that matches the provided uId and jobId, or null if none found.
+     */
+    public JobStatus getJobByUidAndJobId(int uid, int jobId) {
+        Iterator<JobStatus> it = mJobSet.iterator();
+        while (it.hasNext()) {
+            JobStatus ts = it.next();
+            if (ts.getUid() == uid && ts.getJobId() == jobId) {
+                return ts;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return The live array of JobStatus objects.
+     */
+    public ArraySet<JobStatus> getJobs() {
+        return mJobSet;
+    }
+
+    /** Version of the db schema. */
+    private static final int JOBS_FILE_VERSION = 0;
+    /** Tag corresponds to constraints this job needs. */
+    private static final String XML_TAG_PARAMS_CONSTRAINTS = "constraints";
+    /** Tag corresponds to execution parameters. */
+    private static final String XML_TAG_PERIODIC = "periodic";
+    private static final String XML_TAG_ONEOFF = "one-off";
+    private static final String XML_TAG_EXTRAS = "extras";
+
+    /**
+     * Every time the state changes we write all the jobs in one swath, instead of trying to
+     * track incremental changes.
+     * @return Whether the operation was successful. This will only fail for e.g. if the system is
+     * low on storage. If this happens, we continue as normal
+     */
+    private void maybeWriteStatusToDiskAsync() {
+        mDirtyOperations++;
+        if (mDirtyOperations >= MAX_OPS_BEFORE_WRITE) {
+            if (DEBUG) {
+                Slog.v(TAG, "Writing jobs to disk.");
+            }
+            mIoHandler.post(new WriteJobsMapToDiskRunnable());
+        }
+    }
+
+    private void readJobMapFromDiskAsync(JobMapReadFinishedListener callback) {
+        mIoHandler.post(new ReadJobMapFromDiskRunnable(callback));
+    }
+
+    public void readJobMapFromDisk(JobMapReadFinishedListener callback) {
+        new ReadJobMapFromDiskRunnable(callback).run();
+    }
+
+    /**
+     * Runnable that writes {@link #mJobSet} out to xml.
+     * NOTE: This Runnable locks on JobStore.this
+     */
+    private class WriteJobsMapToDiskRunnable implements Runnable {
+        @Override
+        public void run() {
+            final long startElapsed = SystemClock.elapsedRealtime();
+            synchronized (JobStore.this) {
+                writeJobsMapImpl();
+            }
+            if (JobSchedulerService.DEBUG) {
+                Slog.v(TAG, "Finished writing, took " + (SystemClock.elapsedRealtime()
+                        - startElapsed) + "ms");
+            }
+        }
+
+        private void writeJobsMapImpl() {
+            try {
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                XmlSerializer out = new FastXmlSerializer();
+                out.setOutput(baos, "utf-8");
+                out.startDocument(null, true);
+                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+                out.startTag(null, "job-info");
+                out.attribute(null, "version", Integer.toString(JOBS_FILE_VERSION));
+                for (int i = 0; i < mJobSet.size(); i++) {
+                    final JobStatus jobStatus = mJobSet.valueAt(i);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Saving job " + jobStatus.getJobId());
+                    }
+                    out.startTag(null, "job");
+                    addIdentifierAttributesToJobTag(out, jobStatus);
+                    writeConstraintsToXml(out, jobStatus);
+                    writeExecutionCriteriaToXml(out, jobStatus);
+                    writeBundleToXml(jobStatus.getExtras(), out);
+                    out.endTag(null, "job");
+                }
+                out.endTag(null, "job-info");
+                out.endDocument();
+
+                // Write out to disk in one fell sweep.
+                FileOutputStream fos = mJobsFile.startWrite();
+                fos.write(baos.toByteArray());
+                mJobsFile.finishWrite(fos);
+                mDirtyOperations = 0;
+            } catch (IOException e) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Error writing out job data.", e);
+                }
+            } catch (XmlPullParserException e) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error persisting bundle.", e);
+                }
+            }
+        }
+
+        /** Write out a tag with data comprising the required fields of this job and its client. */
+        private void addIdentifierAttributesToJobTag(XmlSerializer out, JobStatus jobStatus)
+                throws IOException {
+            out.attribute(null, "jobid", Integer.toString(jobStatus.getJobId()));
+            out.attribute(null, "package", jobStatus.getServiceComponent().getPackageName());
+            out.attribute(null, "class", jobStatus.getServiceComponent().getClassName());
+            out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
+        }
+
+        private void writeBundleToXml(PersistableBundle extras, XmlSerializer out)
+                throws IOException, XmlPullParserException {
+            out.startTag(null, XML_TAG_EXTRAS);
+            extras.saveToXml(out);
+            out.endTag(null, XML_TAG_EXTRAS);
+        }
+        /**
+         * Write out a tag with data identifying this job's constraints. If the constraint isn't here
+         * it doesn't apply.
+         */
+        private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
+            out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
+            if (jobStatus.hasUnmeteredConstraint()) {
+                out.attribute(null, "unmetered", Boolean.toString(true));
+            }
+            if (jobStatus.hasConnectivityConstraint()) {
+                out.attribute(null, "connectivity", Boolean.toString(true));
+            }
+            if (jobStatus.hasIdleConstraint()) {
+                out.attribute(null, "idle", Boolean.toString(true));
+            }
+            if (jobStatus.hasChargingConstraint()) {
+                out.attribute(null, "charging", Boolean.toString(true));
+            }
+            out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
+        }
+
+        private void writeExecutionCriteriaToXml(XmlSerializer out, JobStatus jobStatus)
+                throws IOException {
+            final JobInfo job = jobStatus.getJob();
+            if (jobStatus.getJob().isPeriodic()) {
+                out.startTag(null, XML_TAG_PERIODIC);
+                out.attribute(null, "period", Long.toString(job.getIntervalMillis()));
+            } else {
+                out.startTag(null, XML_TAG_ONEOFF);
+            }
+
+            if (jobStatus.hasDeadlineConstraint()) {
+                // Wall clock deadline.
+                final long deadlineWallclock =  System.currentTimeMillis() +
+                        (jobStatus.getLatestRunTimeElapsed() - SystemClock.elapsedRealtime());
+                out.attribute(null, "deadline", Long.toString(deadlineWallclock));
+            }
+            if (jobStatus.hasTimingDelayConstraint()) {
+                final long delayWallclock = System.currentTimeMillis() +
+                        (jobStatus.getEarliestRunTime() - SystemClock.elapsedRealtime());
+                out.attribute(null, "delay", Long.toString(delayWallclock));
+            }
+
+            // Only write out back-off policy if it differs from the default.
+            // This also helps the case where the job is idle -> these aren't allowed to specify
+            // back-off.
+            if (jobStatus.getJob().getInitialBackoffMillis() != JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS
+                    || jobStatus.getJob().getBackoffPolicy() != JobInfo.DEFAULT_BACKOFF_POLICY) {
+                out.attribute(null, "backoff-policy", Integer.toString(job.getBackoffPolicy()));
+                out.attribute(null, "initial-backoff", Long.toString(job.getInitialBackoffMillis()));
+            }
+            if (job.isPeriodic()) {
+                out.endTag(null, XML_TAG_PERIODIC);
+            } else {
+                out.endTag(null, XML_TAG_ONEOFF);
+            }
+        }
+    }
+
+    /**
+     * Runnable that reads list of persisted job from xml.
+     * NOTE: This Runnable locks on JobStore.this
+     */
+    private class ReadJobMapFromDiskRunnable implements Runnable {
+        private JobMapReadFinishedListener mCallback;
+        public ReadJobMapFromDiskRunnable(JobMapReadFinishedListener callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            try {
+                List<JobStatus> jobs;
+                FileInputStream fis = mJobsFile.openRead();
+                synchronized (JobStore.this) {
+                    jobs = readJobMapImpl(fis);
+                }
+                fis.close();
+                if (jobs != null) {
+                    mCallback.onJobMapReadFinished(jobs);
+                }
+            } catch (FileNotFoundException e) {
+                if (JobSchedulerService.DEBUG) {
+                    Slog.d(TAG, "Could not find jobs file, probably there was nothing to load.");
+                }
+            } catch (XmlPullParserException e) {
+                if (JobSchedulerService.DEBUG) {
+                    Slog.d(TAG, "Error parsing xml.", e);
+                }
+            } catch (IOException e) {
+                if (JobSchedulerService.DEBUG) {
+                    Slog.d(TAG, "Error parsing xml.", e);
+                }
+            }
+        }
+
+        private List<JobStatus> readJobMapImpl(FileInputStream fis) throws XmlPullParserException, IOException {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, null);
+
+            int eventType = parser.getEventType();
+            while (eventType != XmlPullParser.START_TAG &&
+                    eventType != XmlPullParser.END_DOCUMENT) {
+                eventType = parser.next();
+                Slog.d(TAG, parser.getName());
+            }
+            if (eventType == XmlPullParser.END_DOCUMENT) {
+                if (DEBUG) {
+                    Slog.d(TAG, "No persisted jobs.");
+                }
+                return null;
+            }
+
+            String tagName = parser.getName();
+            if ("job-info".equals(tagName)) {
+                final List<JobStatus> jobs = new ArrayList<JobStatus>();
+                // Read in version info.
+                try {
+                    int version = Integer.valueOf(parser.getAttributeValue(null, "version"));
+                    if (version != JOBS_FILE_VERSION) {
+                        Slog.d(TAG, "Invalid version number, aborting jobs file read.");
+                        return null;
+                    }
+                } catch (NumberFormatException e) {
+                    Slog.e(TAG, "Invalid version number, aborting jobs file read.");
+                    return null;
+                }
+                eventType = parser.next();
+                do {
+                    // Read each <job/>
+                    if (eventType == XmlPullParser.START_TAG) {
+                        tagName = parser.getName();
+                        // Start reading job.
+                        if ("job".equals(tagName)) {
+                            JobStatus persistedJob = restoreJobFromXml(parser);
+                            if (persistedJob != null) {
+                                if (DEBUG) {
+                                    Slog.d(TAG, "Read out " + persistedJob);
+                                }
+                                jobs.add(persistedJob);
+                            } else {
+                                Slog.d(TAG, "Error reading job from file.");
+                            }
+                        }
+                    }
+                    eventType = parser.next();
+                } while (eventType != XmlPullParser.END_DOCUMENT);
+                return jobs;
+            }
+            return null;
+        }
+
+        /**
+         * @param parser Xml parser at the beginning of a "<job/>" tag. The next "parser.next()" call
+         *               will take the parser into the body of the job tag.
+         * @return Newly instantiated job holding all the information we just read out of the xml tag.
+         */
+        private JobStatus restoreJobFromXml(XmlPullParser parser) throws XmlPullParserException,
+                IOException {
+            JobInfo.Builder jobBuilder;
+            int uid;
+
+            // Read out job identifier attributes.
+            try {
+                jobBuilder = buildBuilderFromXml(parser);
+                uid = Integer.valueOf(parser.getAttributeValue(null, "uid"));
+            } catch (NumberFormatException e) {
+                Slog.e(TAG, "Error parsing job's required fields, skipping");
+                return null;
+            }
+
+            int eventType;
+            // Read out constraints tag.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);  // Push through to next START_TAG.
+
+            if (!(eventType == XmlPullParser.START_TAG &&
+                    XML_TAG_PARAMS_CONSTRAINTS.equals(parser.getName()))) {
+                // Expecting a <constraints> start tag.
+                return null;
+            }
+            try {
+                buildConstraintsFromXml(jobBuilder, parser);
+            } catch (NumberFormatException e) {
+                Slog.d(TAG, "Error reading constraints, skipping.");
+                return null;
+            }
+            parser.next(); // Consume </constraints>
+
+            // Read out execution parameters tag.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);
+            if (eventType != XmlPullParser.START_TAG) {
+                return null;
+            }
+
+            Pair<Long, Long> runtimes;
+            try {
+                runtimes = buildExecutionTimesFromXml(parser);
+            } catch (NumberFormatException e) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error parsing execution time parameters, skipping.");
+                }
+                return null;
+            }
+
+            if (XML_TAG_PERIODIC.equals(parser.getName())) {
+                try {
+                    String val = parser.getAttributeValue(null, "period");
+                    jobBuilder.setPeriodic(Long.valueOf(val));
+                } catch (NumberFormatException e) {
+                    Slog.d(TAG, "Error reading periodic execution criteria, skipping.");
+                    return null;
+                }
+            } else if (XML_TAG_ONEOFF.equals(parser.getName())) {
+                try {
+                    if (runtimes.first != JobStatus.NO_EARLIEST_RUNTIME) {
+                        jobBuilder.setMinimumLatency(runtimes.first - SystemClock.elapsedRealtime());
+                    }
+                    if (runtimes.second != JobStatus.NO_LATEST_RUNTIME) {
+                        jobBuilder.setOverrideDeadline(
+                                runtimes.second - SystemClock.elapsedRealtime());
+                    }
+                } catch (NumberFormatException e) {
+                    Slog.d(TAG, "Error reading job execution criteria, skipping.");
+                    return null;
+                }
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "Invalid parameter tag, skipping - " + parser.getName());
+                }
+                // Expecting a parameters start tag.
+                return null;
+            }
+            maybeBuildBackoffPolicyFromXml(jobBuilder, parser);
+
+            parser.nextTag(); // Consume parameters end tag.
+
+            // Read out extras Bundle.
+            do {
+                eventType = parser.next();
+            } while (eventType == XmlPullParser.TEXT);
+            if (!(eventType == XmlPullParser.START_TAG && XML_TAG_EXTRAS.equals(parser.getName()))) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Error reading extras, skipping.");
+                }
+                return null;
+            }
+
+            PersistableBundle extras = PersistableBundle.restoreFromXml(parser);
+            jobBuilder.setExtras(extras);
+            parser.nextTag(); // Consume </extras>
+
+            return new JobStatus(jobBuilder.build(), uid, runtimes.first, runtimes.second);
+        }
+
+        private JobInfo.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException {
+            // Pull out required fields from <job> attributes.
+            int jobId = Integer.valueOf(parser.getAttributeValue(null, "jobid"));
+            String packageName = parser.getAttributeValue(null, "package");
+            String className = parser.getAttributeValue(null, "class");
+            ComponentName cname = new ComponentName(packageName, className);
+
+            return new JobInfo.Builder(jobId, cname);
+        }
+
+        private void buildConstraintsFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+            String val = parser.getAttributeValue(null, "unmetered");
+            if (val != null) {
+                jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED);
+            }
+            val = parser.getAttributeValue(null, "connectivity");
+            if (val != null) {
+                jobBuilder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY);
+            }
+            val = parser.getAttributeValue(null, "idle");
+            if (val != null) {
+                jobBuilder.setRequiresDeviceIdle(true);
+            }
+            val = parser.getAttributeValue(null, "charging");
+            if (val != null) {
+                jobBuilder.setRequiresCharging(true);
+            }
+        }
+
+        /**
+         * Builds the back-off policy out of the params tag. These attributes may not exist, depending
+         * on whether the back-off was set when the job was first scheduled.
+         */
+        private void maybeBuildBackoffPolicyFromXml(JobInfo.Builder jobBuilder, XmlPullParser parser) {
+            String val = parser.getAttributeValue(null, "initial-backoff");
+            if (val != null) {
+                long initialBackoff = Long.valueOf(val);
+                val = parser.getAttributeValue(null, "backoff-policy");
+                int backoffPolicy = Integer.valueOf(val);  // Will throw NFE which we catch higher up.
+                jobBuilder.setBackoffCriteria(initialBackoff, backoffPolicy);
+            }
+        }
+
+        /**
+         * Convenience function to read out and convert deadline and delay from xml into elapsed real
+         * time.
+         * @return A {@link android.util.Pair}, where the first value is the earliest elapsed runtime
+         * and the second is the latest elapsed runtime.
+         */
+        private Pair<Long, Long> buildExecutionTimesFromXml(XmlPullParser parser)
+                throws NumberFormatException {
+            // Pull out execution time data.
+            final long nowWallclock = System.currentTimeMillis();
+            final long nowElapsed = SystemClock.elapsedRealtime();
+
+            long earliestRunTimeElapsed = JobStatus.NO_EARLIEST_RUNTIME;
+            long latestRunTimeElapsed = JobStatus.NO_LATEST_RUNTIME;
+            String val = parser.getAttributeValue(null, "deadline");
+            if (val != null) {
+                long latestRuntimeWallclock = Long.valueOf(val);
+                long maxDelayElapsed =
+                        Math.max(latestRuntimeWallclock - nowWallclock, 0);
+                latestRunTimeElapsed = nowElapsed + maxDelayElapsed;
+            }
+            val = parser.getAttributeValue(null, "delay");
+            if (val != null) {
+                long earliestRuntimeWallclock = Long.valueOf(val);
+                long minDelayElapsed =
+                        Math.max(earliestRuntimeWallclock - nowWallclock, 0);
+                earliestRunTimeElapsed = nowElapsed + minDelayElapsed;
+
+            }
+            return Pair.create(earliestRunTimeElapsed, latestRunTimeElapsed);
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/job/StateChangedListener.java b/services/core/java/com/android/server/job/StateChangedListener.java
new file mode 100644
index 0000000..90c203a
--- /dev/null
+++ b/services/core/java/com/android/server/job/StateChangedListener.java
@@ -0,0 +1,39 @@
+/*
+ * 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.job;
+
+import com.android.server.job.controllers.JobStatus;
+
+/**
+ * Interface through which a {@link com.android.server.job.controllers.StateController} informs
+ * the {@link com.android.server.job.JobSchedulerService} that there are some tasks potentially
+ * ready to be run.
+ */
+public interface StateChangedListener {
+    /**
+     * Called by the controller to notify the JobManager that it should check on the state of a
+     * task.
+     */
+    public void onControllerStateChanged();
+
+    /**
+     * Called by the controller to notify the JobManager that regardless of the state of the task,
+     * it must be run immediately.
+     * @param jobStatus The state of the task which is to be run immediately.
+     */
+    public void onRunJobNow(JobStatus jobStatus);
+}
diff --git a/services/core/java/com/android/server/task/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
similarity index 80%
rename from services/core/java/com/android/server/task/controllers/BatteryController.java
rename to services/core/java/com/android/server/job/controllers/BatteryController.java
index 443527f..4aef2d31 100644
--- a/services/core/java/com/android/server/task/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.task.controllers;
+package com.android.server.job.controllers;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -32,11 +32,12 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.BatteryService;
-import com.android.server.task.StateChangedListener;
-import com.android.server.task.TaskManagerService;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -45,7 +46,7 @@
  * ACTION_BATTERY_OK.
  */
 public class BatteryController extends StateController {
-    private static final String TAG = "BatteryController";
+    private static final String TAG = "JobScheduler.Batt";
 
     private static final Object sCreationLock = new Object();
     private static volatile BatteryController sController;
@@ -54,10 +55,10 @@
     /** Wait this long after phone is plugged in before doing any work. */
     private static final long STABLE_CHARGING_THRESHOLD_MILLIS = 2 * 60 * 1000; // 2 minutes.
 
-    private List<TaskStatus> mTrackedTasks = new ArrayList<TaskStatus>();
+    private List<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
     private ChargingTracker mChargeTracker;
 
-    public static BatteryController get(TaskManagerService taskManagerService) {
+    public static BatteryController get(JobSchedulerService taskManagerService) {
         synchronized (sCreationLock) {
             if (sController == null) {
                 sController = new BatteryController(taskManagerService,
@@ -85,18 +86,21 @@
     }
 
     @Override
-    public void maybeStartTrackingTask(TaskStatus taskStatus) {
+    public void maybeStartTrackingJob(JobStatus taskStatus) {
         if (taskStatus.hasChargingConstraint()) {
+            final boolean isOnStablePower = mChargeTracker.isOnStablePower();
             synchronized (mTrackedTasks) {
                 mTrackedTasks.add(taskStatus);
-                taskStatus.chargingConstraintSatisfied.set(mChargeTracker.isOnStablePower());
+                taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
+            }
+            if (isOnStablePower) {
+                mStateChangedListener.onControllerStateChanged();
             }
         }
-
     }
 
     @Override
-    public void maybeStopTrackingTask(TaskStatus taskStatus) {
+    public void maybeStopTrackingJob(JobStatus taskStatus) {
         if (taskStatus.hasChargingConstraint()) {
             synchronized (mTrackedTasks) {
                 mTrackedTasks.remove(taskStatus);
@@ -106,9 +110,12 @@
 
     private void maybeReportNewChargingState() {
         final boolean stablePower = mChargeTracker.isOnStablePower();
+        if (DEBUG) {
+            Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
+        }
         boolean reportChange = false;
         synchronized (mTrackedTasks) {
-            for (TaskStatus ts : mTrackedTasks) {
+            for (JobStatus ts : mTrackedTasks) {
                 boolean previous = ts.chargingConstraintSatisfied.getAndSet(stablePower);
                 if (previous != stablePower) {
                     reportChange = true;
@@ -133,8 +140,7 @@
 
         public ChargingTracker() {
             mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-            Intent intent = new Intent(ACTION_CHARGING_STABLE)
-                    .setComponent(new ComponentName(mContext, this.getClass()));
+            Intent intent = new Intent(ACTION_CHARGING_STABLE);
             mStableChargingTriggerIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
         }
 
@@ -147,6 +153,8 @@
             // Charging/not charging.
             filter.addAction(Intent.ACTION_POWER_CONNECTED);
             filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
+            // Charging stable.
+            filter.addAction(ACTION_CHARGING_STABLE);
             mContext.registerReceiver(this, filter);
 
             // Initialise tracker state.
@@ -189,6 +197,10 @@
                 mBatteryHealthy = true;
                 maybeReportNewChargingState();
             } else if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Received charging intent, setting alarm for "
+                            + STABLE_CHARGING_THRESHOLD_MILLIS);
+                }
                 // Set up an alarm for ACTION_CHARGING_STABLE - we don't want to kick off tasks
                 // here if the user unplugs the phone immediately.
                 mAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
@@ -196,6 +208,9 @@
                         mStableChargingTriggerIntent);
                 mCharging = true;
             } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Disconnected from power, cancelling any set alarms.");
+                }
                 // If an alarm is set, breathe a sigh of relief and cancel it - crisis averted.
                 mAlarm.cancel(mStableChargingTriggerIntent);
                 mCharging = false;
@@ -203,7 +218,8 @@
             }else if (ACTION_CHARGING_STABLE.equals(action)) {
                 // Here's where we actually do the notify for a task being ready.
                 if (DEBUG) {
-                    Slog.d(TAG, "Battery connected fired @ " + SystemClock.elapsedRealtime());
+                    Slog.d(TAG, "Battery connected fired @ " + SystemClock.elapsedRealtime()
+                            + " charging: " + mCharging);
                 }
                 if (mCharging) {  // Should never receive this intent if mCharging is false.
                     maybeReportNewChargingState();
@@ -214,6 +230,17 @@
 
     @Override
     public void dumpControllerState(PrintWriter pw) {
-
+        pw.println("Batt.");
+        pw.println("Stable power: " + mChargeTracker.isOnStablePower());
+        synchronized (mTrackedTasks) {
+            Iterator<JobStatus> it = mTrackedTasks.iterator();
+            if (it.hasNext()) {
+                pw.print(String.valueOf(it.next().hashCode()));
+            }
+            while (it.hasNext()) {
+                pw.print("," + String.valueOf(it.next().hashCode()));
+            }
+            pw.println();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/task/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
similarity index 75%
rename from services/core/java/com/android/server/task/controllers/ConnectivityController.java
rename to services/core/java/com/android/server/job/controllers/ConnectivityController.java
index c1ab0f0..7e79ff7 100644
--- a/services/core/java/com/android/server/task/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.task.controllers;
+package com.android.server.job.controllers;
 
 
 import android.content.BroadcastReceiver;
@@ -28,8 +28,8 @@
 import android.util.Slog;
 
 import com.android.server.ConnectivityService;
-import com.android.server.task.StateChangedListener;
-import com.android.server.task.TaskManagerService;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
 
 import java.io.PrintWriter;
 import java.util.LinkedList;
@@ -42,9 +42,9 @@
  */
 public class ConnectivityController extends StateController implements
         ConnectivityManager.OnNetworkActiveListener {
-    private static final String TAG = "TaskManager.Conn";
+    private static final String TAG = "JobScheduler.Conn";
 
-    private final List<TaskStatus> mTrackedTasks = new LinkedList<TaskStatus>();
+    private final List<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();
     private final BroadcastReceiver mConnectivityChangedReceiver =
             new ConnectivityChangedReceiver();
     /** Singleton. */
@@ -55,10 +55,10 @@
     /** Track whether the latest active network is connected. */
     private boolean mNetworkConnected;
 
-    public static ConnectivityController get(TaskManagerService taskManager) {
+    public static ConnectivityController get(JobSchedulerService jms) {
         synchronized (sCreationLock) {
             if (mSingleton == null) {
-                mSingleton = new ConnectivityController(taskManager, taskManager.getContext());
+                mSingleton = new ConnectivityController(jms, jms.getContext());
             }
             return mSingleton;
         }
@@ -82,21 +82,21 @@
     }
 
     @Override
-    public void maybeStartTrackingTask(TaskStatus taskStatus) {
-        if (taskStatus.hasConnectivityConstraint() || taskStatus.hasUnmeteredConstraint()) {
-            synchronized (mTrackedTasks) {
-                taskStatus.connectivityConstraintSatisfied.set(mNetworkConnected);
-                taskStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);
-                mTrackedTasks.add(taskStatus);
+    public void maybeStartTrackingJob(JobStatus jobStatus) {
+        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
+            synchronized (mTrackedJobs) {
+                jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected);
+                jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);
+                mTrackedJobs.add(jobStatus);
             }
         }
     }
 
     @Override
-    public void maybeStopTrackingTask(TaskStatus taskStatus) {
-        if (taskStatus.hasConnectivityConstraint() || taskStatus.hasUnmeteredConstraint()) {
-            synchronized (mTrackedTasks) {
-                mTrackedTasks.remove(taskStatus);
+    public void maybeStopTrackingJob(JobStatus jobStatus) {
+        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
+            synchronized (mTrackedJobs) {
+                mTrackedJobs.remove(jobStatus);
             }
         }
     }
@@ -104,16 +104,16 @@
     /**
      * @param userId Id of the user for whom we are updating the connectivity state.
      */
-    private void updateTrackedTasks(int userId) {
-        synchronized (mTrackedTasks) {
+    private void updateTrackedJobs(int userId) {
+        synchronized (mTrackedJobs) {
             boolean changed = false;
-            for (TaskStatus ts : mTrackedTasks) {
-                if (ts.getUserId() != userId) {
+            for (JobStatus js : mTrackedJobs) {
+                if (js.getUserId() != userId) {
                     continue;
                 }
                 boolean prevIsConnected =
-                        ts.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);
-                boolean prevIsMetered = ts.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);
+                        js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);
+                boolean prevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);
                 if (prevIsConnected != mNetworkConnected || prevIsMetered != mNetworkUnmetered) {
                     changed = true;
                 }
@@ -125,16 +125,16 @@
     }
 
     /**
-     * We know the network has just come up. We want to run any tasks that are ready.
+     * We know the network has just come up. We want to run any jobs that are ready.
      */
     public synchronized void onNetworkActive() {
-        synchronized (mTrackedTasks) {
-            for (TaskStatus ts : mTrackedTasks) {
-                if (ts.isReady()) {
+        synchronized (mTrackedJobs) {
+            for (JobStatus js : mTrackedJobs) {
+                if (js.isReady()) {
                     if (DEBUG) {
-                        Slog.d(TAG, "Running " + ts + " due to network activity.");
+                        Slog.d(TAG, "Running " + js + " due to network activity.");
                     }
-                    mStateChangedListener.onRunTaskNow(ts);
+                    mStateChangedListener.onRunJobNow(js);
                 }
             }
         }
@@ -169,7 +169,7 @@
                 if (activeNetwork == null) {
                     mNetworkUnmetered = false;
                     mNetworkConnected = false;
-                    updateTrackedTasks(userid);
+                    updateTrackedJobs(userid);
                 } else if (activeNetwork.getType() == networkType) {
                     mNetworkUnmetered = false;
                     mNetworkConnected = !intent.getBooleanExtra(
@@ -177,7 +177,7 @@
                     if (mNetworkConnected) {  // No point making the call if we know there's no conn.
                         mNetworkUnmetered = !connManager.isActiveNetworkMetered();
                     }
-                    updateTrackedTasks(userid);
+                    updateTrackedJobs(userid);
                 }
             } else {
                 if (DEBUG) {
@@ -191,10 +191,10 @@
     public void dumpControllerState(PrintWriter pw) {
         pw.println("Conn.");
         pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
-        for (TaskStatus ts: mTrackedTasks) {
-            pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".."
-                    + ": C=" + ts.hasConnectivityConstraint()
-                    + ", UM=" + ts.hasUnmeteredConstraint());
+        for (JobStatus js: mTrackedJobs) {
+            pw.println(String.valueOf(js.hashCode()).substring(0, 3) + ".."
+                    + ": C=" + js.hasConnectivityConstraint()
+                    + ", UM=" + js.hasUnmeteredConstraint());
         }
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/task/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
similarity index 92%
rename from services/core/java/com/android/server/task/controllers/IdleController.java
rename to services/core/java/com/android/server/job/controllers/IdleController.java
index e749b00..07ffe4d 100644
--- a/services/core/java/com/android/server/task/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.task.controllers;
+package com.android.server.job.controllers;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -29,8 +29,8 @@
 import android.os.SystemClock;
 import android.util.Slog;
 
-import com.android.server.task.StateChangedListener;
-import com.android.server.task.TaskManagerService;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
 
 public class IdleController extends StateController {
     private static final String TAG = "IdleController";
@@ -43,14 +43,14 @@
     private static final String ACTION_TRIGGER_IDLE =
             "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE";
 
-    final ArrayList<TaskStatus> mTrackedTasks = new ArrayList<TaskStatus>();
+    final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
     IdlenessTracker mIdleTracker;
 
     // Singleton factory
     private static Object sCreationLock = new Object();
     private static volatile IdleController sController;
 
-    public static IdleController get(TaskManagerService service) {
+    public static IdleController get(JobSchedulerService service) {
         synchronized (sCreationLock) {
             if (sController == null) {
                 sController = new IdleController(service, service.getContext());
@@ -68,7 +68,7 @@
      * StateController interface
      */
     @Override
-    public void maybeStartTrackingTask(TaskStatus taskStatus) {
+    public void maybeStartTrackingJob(JobStatus taskStatus) {
         if (taskStatus.hasIdleConstraint()) {
             synchronized (mTrackedTasks) {
                 mTrackedTasks.add(taskStatus);
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public void maybeStopTrackingTask(TaskStatus taskStatus) {
+    public void maybeStopTrackingJob(JobStatus taskStatus) {
         synchronized (mTrackedTasks) {
             mTrackedTasks.remove(taskStatus);
         }
@@ -89,7 +89,7 @@
      */
     void reportNewIdleState(boolean isIdle) {
         synchronized (mTrackedTasks) {
-            for (TaskStatus task : mTrackedTasks) {
+            for (JobStatus task : mTrackedTasks) {
                 task.idleConstraintSatisfied.set(isIdle);
             }
         }
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
new file mode 100644
index 0000000..15a6b25
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -0,0 +1,217 @@
+/*
+ * 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.job.controllers;
+
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.os.PersistableBundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Uniquely identifies a job internally.
+ * Created from the public {@link android.app.job.JobInfo} object when it lands on the scheduler.
+ * Contains current state of the requirements of the job, as well as a function to evaluate
+ * whether it's ready to run.
+ * This object is shared among the various controllers - hence why the different fields are atomic.
+ * This isn't strictly necessary because each controller is only interested in a specific field,
+ * and the receivers that are listening for global state change will all run on the main looper,
+ * but we don't enforce that so this is safer.
+ * @hide
+ */
+public class JobStatus {
+    public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
+    public static final long NO_EARLIEST_RUNTIME = 0L;
+
+    final JobInfo job;
+    final int uId;
+
+    /** At reschedule time we need to know whether to update job on disk. */
+    final boolean persisted;
+
+    // Constraints.
+    final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean timeDelayConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean deadlineConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean idleConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean unmeteredConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean connectivityConstraintSatisfied = new AtomicBoolean();
+
+    /**
+     * Earliest point in the future at which this job will be eligible to run. A value of 0
+     * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
+     */
+    private long earliestRunTimeElapsedMillis;
+    /**
+     * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE}
+     * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
+     */
+    private long latestRunTimeElapsedMillis;
+    /** How many times this job has failed, used to compute back-off. */
+    private final int numFailures;
+
+    /** Provide a handle to the service that this job will be run on. */
+    public int getServiceToken() {
+        return uId;
+    }
+
+    private JobStatus(JobInfo job, int uId, boolean persisted, int numFailures) {
+        this.job = job;
+        this.uId = uId;
+        this.numFailures = numFailures;
+        this.persisted = persisted;
+    }
+
+    /** Create a newly scheduled job. */
+    public JobStatus(JobInfo job, int uId, boolean persisted) {
+        this(job, uId, persisted, 0);
+
+        final long elapsedNow = SystemClock.elapsedRealtime();
+
+        if (job.isPeriodic()) {
+            earliestRunTimeElapsedMillis = elapsedNow;
+            latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
+        } else {
+            earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
+                    elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
+            latestRunTimeElapsedMillis = job.hasLateConstraint() ?
+                    elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
+        }
+    }
+
+    /**
+     * Create a new JobStatus that was loaded from disk. We ignore the provided
+     * {@link android.app.job.JobInfo} time criteria because we can load a persisted periodic job
+     * from the {@link com.android.server.job.JobStore} and still want to respect its
+     * wallclock runtime rather than resetting it on every boot.
+     * We consider a freshly loaded job to no longer be in back-off.
+     */
+    public JobStatus(JobInfo job, int uId, long earliestRunTimeElapsedMillis,
+                      long latestRunTimeElapsedMillis) {
+        this(job, uId, true, 0);
+
+        this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
+        this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
+    }
+
+    /** Create a new job to be rescheduled with the provided parameters. */
+    public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis,
+                      long newLatestRuntimeElapsedMillis, int backoffAttempt) {
+        this(rescheduling.job, rescheduling.getUid(), rescheduling.isPersisted(), backoffAttempt);
+
+        earliestRunTimeElapsedMillis = newEarliestRuntimeElapsedMillis;
+        latestRunTimeElapsedMillis = newLatestRuntimeElapsedMillis;
+    }
+
+    public JobInfo getJob() {
+        return job;
+    }
+
+    public int getJobId() {
+        return job.getId();
+    }
+
+    public int getNumFailures() {
+        return numFailures;
+    }
+
+    public ComponentName getServiceComponent() {
+        return job.getService();
+    }
+
+    public int getUserId() {
+        return UserHandle.getUserId(uId);
+    }
+
+    public int getUid() {
+        return uId;
+    }
+
+    public PersistableBundle getExtras() {
+        return job.getExtras();
+    }
+
+    public boolean hasConnectivityConstraint() {
+        return job.getNetworkCapabilities() == JobInfo.NetworkType.ANY;
+    }
+
+    public boolean hasUnmeteredConstraint() {
+        return job.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED;
+    }
+
+    public boolean hasChargingConstraint() {
+        return job.isRequireCharging();
+    }
+
+    public boolean hasTimingDelayConstraint() {
+        return earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME;
+    }
+
+    public boolean hasDeadlineConstraint() {
+        return latestRunTimeElapsedMillis != NO_LATEST_RUNTIME;
+    }
+
+    public boolean hasIdleConstraint() {
+        return job.isRequireDeviceIdle();
+    }
+
+    public long getEarliestRunTime() {
+        return earliestRunTimeElapsedMillis;
+    }
+
+    public long getLatestRunTimeElapsed() {
+        return latestRunTimeElapsedMillis;
+    }
+
+    public boolean isPersisted() {
+        return persisted;
+    }
+    /**
+     * @return Whether or not this job is ready to run, based on its requirements.
+     */
+    public synchronized boolean isReady() {
+        return (!hasChargingConstraint() || chargingConstraintSatisfied.get())
+                && (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get())
+                && (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get())
+                && (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get())
+                && (!hasIdleConstraint() || idleConstraintSatisfied.get())
+                // Also ready if the deadline has expired - special case.
+                || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get());
+    }
+
+    public boolean matches(int uid, int jobId) {
+        return this.job.getId() == jobId && this.uId == uid;
+    }
+
+    @Override
+    public String toString() {
+        return String.valueOf(hashCode()).substring(0, 3) + ".."
+                + ":[" + job.getService().getPackageName() + ",jId=" + job.getId()
+                + ",R=(" + earliestRunTimeElapsedMillis + "," + latestRunTimeElapsedMillis + ")"
+                + ",N=" + job.getNetworkCapabilities() + ",C=" + job.isRequireCharging()
+                + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
+                + (isReady() ? "(READY)" : "")
+                + "]";
+    }
+    // Dumpsys infrastructure
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(this.toString());
+    }
+}
diff --git a/services/core/java/com/android/server/task/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
similarity index 70%
rename from services/core/java/com/android/server/task/controllers/StateController.java
rename to services/core/java/com/android/server/job/controllers/StateController.java
index a7f52f5..81658bf 100644
--- a/services/core/java/com/android/server/task/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -14,18 +14,18 @@
  * limitations under the License
  */
 
-package com.android.server.task.controllers;
+package com.android.server.job.controllers;
 
 import android.content.Context;
 
-import com.android.server.task.StateChangedListener;
-import com.android.server.task.TaskManagerService;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
 
 import java.io.PrintWriter;
 
 /**
- * Incorporates shared controller logic between the various controllers of the TaskManager.
- * These are solely responsible for tracking a list of tasks, and notifying the TM when these
+ * Incorporates shared controller logic between the various controllers of the JobManager.
+ * These are solely responsible for tracking a list of jobs, and notifying the JM when these
  * are ready to run, or whether they must be stopped.
  */
 public abstract class StateController {
@@ -39,16 +39,16 @@
     }
 
     /**
-     * Implement the logic here to decide whether a task should be tracked by this controller.
-     * This logic is put here so the TaskManger can be completely agnostic of Controller logic.
+     * Implement the logic here to decide whether a job should be tracked by this controller.
+     * This logic is put here so the JobManger can be completely agnostic of Controller logic.
      * Also called when updating a task, so implementing controllers have to be aware of
      * preexisting tasks.
      */
-    public abstract void maybeStartTrackingTask(TaskStatus taskStatus);
+    public abstract void maybeStartTrackingJob(JobStatus jobStatus);
     /**
      * Remove task - this will happen if the task is cancelled, completed, etc.
      */
-    public abstract void maybeStopTrackingTask(TaskStatus taskStatus);
+    public abstract void maybeStopTrackingJob(JobStatus jobStatus);
 
     public abstract void dumpControllerState(PrintWriter pw);
 
diff --git a/services/core/java/com/android/server/task/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
similarity index 61%
rename from services/core/java/com/android/server/task/controllers/TimeController.java
rename to services/core/java/com/android/server/job/controllers/TimeController.java
index b75036c..e46226c 100644
--- a/services/core/java/com/android/server/task/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.task.controllers;
+package com.android.server.job.controllers;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -25,8 +25,8 @@
 import android.os.SystemClock;
 import android.util.Slog;
 
-import com.android.server.task.StateChangedListener;
-import com.android.server.task.TaskManagerService;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
 
 import java.io.PrintWriter;
 import java.util.Iterator;
@@ -35,35 +35,35 @@
 import java.util.ListIterator;
 
 /**
- * This class sets an alarm for the next expiring task, and determines whether a task's minimum
+ * This class sets an alarm for the next expiring job, and determines whether a job's minimum
  * delay has been satisfied.
  */
 public class TimeController extends StateController {
-    private static final String TAG = "TaskManager.Time";
-    private static final String ACTION_TASK_EXPIRED =
-            "android.content.taskmanager.TASK_DEADLINE_EXPIRED";
-    private static final String ACTION_TASK_DELAY_EXPIRED =
-            "android.content.taskmanager.TASK_DELAY_EXPIRED";
+    private static final String TAG = "JobScheduler.Time";
+    private static final String ACTION_JOB_EXPIRED =
+            "android.content.jobscheduler.JOB_DEADLINE_EXPIRED";
+    private static final String ACTION_JOB_DELAY_EXPIRED =
+            "android.content.jobscheduler.JOB_DELAY_EXPIRED";
 
-    /** Set an alarm for the next task expiry. */
+    /** Set an alarm for the next job expiry. */
     private final PendingIntent mDeadlineExpiredAlarmIntent;
-    /** Set an alarm for the next task delay expiry. This*/
+    /** Set an alarm for the next job delay expiry. This*/
     private final PendingIntent mNextDelayExpiredAlarmIntent;
     /** Constant time determining how near in the future we'll set an alarm for. */
     private static final long MIN_WAKEUP_INTERVAL_MILLIS = 15 * 1000;
 
-    private long mNextTaskExpiredElapsedMillis;
+    private long mNextJobExpiredElapsedMillis;
     private long mNextDelayExpiredElapsedMillis;
 
     private AlarmManager mAlarmService = null;
-    /** List of tracked tasks, sorted asc. by deadline */
-    private final List<TaskStatus> mTrackedTasks = new LinkedList<TaskStatus>();
+    /** List of tracked jobs, sorted asc. by deadline */
+    private final List<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();
     /** Singleton. */
     private static TimeController mSingleton;
 
-    public static synchronized TimeController get(TaskManagerService taskManager) {
+    public static synchronized TimeController get(JobSchedulerService jms) {
         if (mSingleton == null) {
-            mSingleton = new TimeController(taskManager, taskManager.getContext());
+            mSingleton = new TimeController(jms, jms.getContext());
         }
         return mSingleton;
     }
@@ -72,66 +72,66 @@
         super(stateChangedListener, context);
         mDeadlineExpiredAlarmIntent =
                 PendingIntent.getBroadcast(mContext, 0 /* ignored */,
-                        new Intent(ACTION_TASK_EXPIRED), 0);
+                        new Intent(ACTION_JOB_EXPIRED), 0);
         mNextDelayExpiredAlarmIntent =
                 PendingIntent.getBroadcast(mContext, 0 /* ignored */,
-                        new Intent(ACTION_TASK_DELAY_EXPIRED), 0);
-        mNextTaskExpiredElapsedMillis = Long.MAX_VALUE;
+                        new Intent(ACTION_JOB_DELAY_EXPIRED), 0);
+        mNextJobExpiredElapsedMillis = Long.MAX_VALUE;
         mNextDelayExpiredElapsedMillis = Long.MAX_VALUE;
 
         // Register BR for these intents.
-        IntentFilter intentFilter = new IntentFilter(ACTION_TASK_EXPIRED);
-        intentFilter.addAction(ACTION_TASK_DELAY_EXPIRED);
+        IntentFilter intentFilter = new IntentFilter(ACTION_JOB_EXPIRED);
+        intentFilter.addAction(ACTION_JOB_DELAY_EXPIRED);
         mContext.registerReceiver(mAlarmExpiredReceiver, intentFilter);
     }
 
     /**
-     * Check if the task has a timing constraint, and if so determine where to insert it in our
+     * Check if the job has a timing constraint, and if so determine where to insert it in our
      * list.
      */
     @Override
-    public synchronized void maybeStartTrackingTask(TaskStatus task) {
-        if (task.hasTimingDelayConstraint() || task.hasDeadlineConstraint()) {
-            maybeStopTrackingTask(task);
-            ListIterator<TaskStatus> it = mTrackedTasks.listIterator(mTrackedTasks.size());
+    public synchronized void maybeStartTrackingJob(JobStatus job) {
+        if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
+            maybeStopTrackingJob(job);
+            ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
             while (it.hasPrevious()) {
-                TaskStatus ts = it.previous();
-                if (ts.getLatestRunTimeElapsed() < task.getLatestRunTimeElapsed()) {
+                JobStatus ts = it.previous();
+                if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
                     // Insert
                     break;
                 }
             }
-            it.add(task);
+            it.add(job);
             maybeUpdateAlarms(
-                    task.hasTimingDelayConstraint() ? task.getEarliestRunTime() : Long.MAX_VALUE,
-                    task.hasDeadlineConstraint() ? task.getLatestRunTimeElapsed() : Long.MAX_VALUE);
+                    job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE,
+                    job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE);
         }
     }
 
     /**
-     * When we stop tracking a task, we only need to update our alarms if the task we're no longer
+     * When we stop tracking a job, we only need to update our alarms if the job we're no longer
      * tracking was the one our alarms were based off of.
      * Really an == comparison should be enough, but why play with fate? We'll do <=.
      */
     @Override
-    public synchronized void maybeStopTrackingTask(TaskStatus taskStatus) {
-        if (mTrackedTasks.remove(taskStatus)) {
+    public synchronized void maybeStopTrackingJob(JobStatus job) {
+        if (mTrackedJobs.remove(job)) {
             checkExpiredDelaysAndResetAlarm();
             checkExpiredDeadlinesAndResetAlarm();
         }
     }
 
     /**
-     * Determines whether this controller can stop tracking the given task.
-     * The controller is no longer interested in a task once its time constraint is satisfied, and
-     * the task's deadline is fulfilled - unlike other controllers a time constraint can't toggle
+     * Determines whether this controller can stop tracking the given job.
+     * The controller is no longer interested in a job once its time constraint is satisfied, and
+     * the job's deadline is fulfilled - unlike other controllers a time constraint can't toggle
      * back and forth.
      */
-    private boolean canStopTrackingTask(TaskStatus taskStatus) {
-        return (!taskStatus.hasTimingDelayConstraint() ||
-                taskStatus.timeDelayConstraintSatisfied.get()) &&
-                (!taskStatus.hasDeadlineConstraint() ||
-                        taskStatus.deadlineConstraintSatisfied.get());
+    private boolean canStopTrackingJob(JobStatus job) {
+        return (!job.hasTimingDelayConstraint() ||
+                job.timeDelayConstraintSatisfied.get()) &&
+                (!job.hasDeadlineConstraint() ||
+                        job.deadlineConstraintSatisfied.get());
     }
 
     private void ensureAlarmService() {
@@ -141,27 +141,27 @@
     }
 
     /**
-     * Checks list of tasks for ones that have an expired deadline, sending them to the TaskManager
+     * Checks list of jobs for ones that have an expired deadline, sending them to the JobScheduler
      * if so, removing them from this list, and updating the alarm for the next expiry time.
      */
     private synchronized void checkExpiredDeadlinesAndResetAlarm() {
         long nextExpiryTime = Long.MAX_VALUE;
         final long nowElapsedMillis = SystemClock.elapsedRealtime();
 
-        Iterator<TaskStatus> it = mTrackedTasks.iterator();
+        Iterator<JobStatus> it = mTrackedJobs.iterator();
         while (it.hasNext()) {
-            TaskStatus ts = it.next();
-            if (!ts.hasDeadlineConstraint()) {
+            JobStatus job = it.next();
+            if (!job.hasDeadlineConstraint()) {
                 continue;
             }
-            final long taskDeadline = ts.getLatestRunTimeElapsed();
+            final long jobDeadline = job.getLatestRunTimeElapsed();
 
-            if (taskDeadline <= nowElapsedMillis) {
-                ts.deadlineConstraintSatisfied.set(true);
-                mStateChangedListener.onRunTaskNow(ts);
+            if (jobDeadline <= nowElapsedMillis) {
+                job.deadlineConstraintSatisfied.set(true);
+                mStateChangedListener.onRunJobNow(job);
                 it.remove();
             } else {  // Sorted by expiry time, so take the next one and stop.
-                nextExpiryTime = taskDeadline;
+                nextExpiryTime = jobDeadline;
                 break;
             }
         }
@@ -169,31 +169,31 @@
     }
 
     /**
-     * Handles alarm that notifies us that a task's delay has expired. Iterates through the list of
-     * tracked tasks and marks them as ready as appropriate.
+     * Handles alarm that notifies us that a job's delay has expired. Iterates through the list of
+     * tracked jobs and marks them as ready as appropriate.
      */
     private synchronized void checkExpiredDelaysAndResetAlarm() {
         final long nowElapsedMillis = SystemClock.elapsedRealtime();
         long nextDelayTime = Long.MAX_VALUE;
         boolean ready = false;
-        Iterator<TaskStatus> it = mTrackedTasks.iterator();
+        Iterator<JobStatus> it = mTrackedJobs.iterator();
         while (it.hasNext()) {
-            final TaskStatus ts = it.next();
-            if (!ts.hasTimingDelayConstraint()) {
+            final JobStatus job = it.next();
+            if (!job.hasTimingDelayConstraint()) {
                 continue;
             }
-            final long taskDelayTime = ts.getEarliestRunTime();
-            if (taskDelayTime <= nowElapsedMillis) {
-                ts.timeDelayConstraintSatisfied.set(true);
-                if (canStopTrackingTask(ts)) {
+            final long jobDelayTime = job.getEarliestRunTime();
+            if (jobDelayTime <= nowElapsedMillis) {
+                job.timeDelayConstraintSatisfied.set(true);
+                if (canStopTrackingJob(job)) {
                     it.remove();
                 }
-                if (ts.isReady()) {
+                if (job.isReady()) {
                     ready = true;
                 }
             } else {  // Keep going through list to get next delay time.
-                if (nextDelayTime > taskDelayTime) {
-                    nextDelayTime = taskDelayTime;
+                if (nextDelayTime > jobDelayTime) {
+                    nextDelayTime = jobDelayTime;
                 }
             }
         }
@@ -207,13 +207,13 @@
         if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {
             setDelayExpiredAlarm(delayExpiredElapsed);
         }
-        if (deadlineExpiredElapsed < mNextTaskExpiredElapsedMillis) {
+        if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {
             setDeadlineExpiredAlarm(deadlineExpiredElapsed);
         }
     }
 
     /**
-     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a task's
+     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
      * delay will expire.
      * This alarm <b>will not</b> wake up the phone.
      */
@@ -228,7 +228,7 @@
     }
 
     /**
-     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a task's
+     * Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
      * deadline will expire.
      * This alarm <b>will</b> wake up the phone.
      */
@@ -238,8 +238,8 @@
         if (alarmTimeElapsedMillis < earliestWakeupTimeElapsed) {
             alarmTimeElapsedMillis = earliestWakeupTimeElapsed;
         }
-        mNextTaskExpiredElapsedMillis = alarmTimeElapsedMillis;
-        updateAlarmWithPendingIntent(mDeadlineExpiredAlarmIntent, mNextTaskExpiredElapsedMillis);
+        mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
+        updateAlarmWithPendingIntent(mDeadlineExpiredAlarmIntent, mNextJobExpiredElapsedMillis);
     }
 
     private void updateAlarmWithPendingIntent(PendingIntent pi, long alarmTimeElapsed) {
@@ -260,11 +260,11 @@
             if (DEBUG) {
                 Slog.d(TAG, "Just received alarm: " + intent.getAction());
             }
-            // An task has just expired, so we run through the list of tasks that we have and
+            // A job has just expired, so we run through the list of jobs that we have and
             // notify our StateChangedListener.
-            if (ACTION_TASK_EXPIRED.equals(intent.getAction())) {
+            if (ACTION_JOB_EXPIRED.equals(intent.getAction())) {
                 checkExpiredDeadlinesAndResetAlarm();
-            } else if (ACTION_TASK_DELAY_EXPIRED.equals(intent.getAction())) {
+            } else if (ACTION_JOB_DELAY_EXPIRED.equals(intent.getAction())) {
                 checkExpiredDelaysAndResetAlarm();
             }
         }
@@ -276,10 +276,10 @@
         pw.println("Alarms (" + SystemClock.elapsedRealtime() + ")");
         pw.println(
                 "Next delay alarm in " + (mNextDelayExpiredElapsedMillis - nowElapsed)/1000 + "s");
-        pw.println("Next deadline alarm in " + (mNextTaskExpiredElapsedMillis - nowElapsed)/1000
+        pw.println("Next deadline alarm in " + (mNextJobExpiredElapsedMillis - nowElapsed)/1000
                 + "s");
         pw.println("Tracking:");
-        for (TaskStatus ts : mTrackedTasks) {
+        for (JobStatus ts : mTrackedJobs) {
             pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".."
                     + ": (" + (ts.hasTimingDelayConstraint() ? ts.getEarliestRunTime() : "N/A")
                     + ", " + (ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A")
diff --git a/services/core/java/com/android/server/task/StateChangedListener.java b/services/core/java/com/android/server/task/StateChangedListener.java
deleted file mode 100644
index ab5cc7c..0000000
--- a/services/core/java/com/android/server/task/StateChangedListener.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.task;
-
-import com.android.server.task.controllers.TaskStatus;
-
-/**
- * Interface through which a {@link com.android.server.task.controllers.StateController} informs
- * the {@link com.android.server.task.TaskManagerService} that there are some tasks potentially
- * ready to be run.
- */
-public interface StateChangedListener {
-    /**
-     * Called by the controller to notify the TaskManager that it should check on the state of a
-     * task.
-     */
-    public void onControllerStateChanged();
-
-    /**
-     * Called by the controller to notify the TaskManager that regardless of the state of the task,
-     * it must be run immediately.
-     * @param taskStatus The state of the task which is to be run immediately.
-     */
-    public void onRunTaskNow(TaskStatus taskStatus);
-}
diff --git a/services/core/java/com/android/server/task/TaskManagerService.java b/services/core/java/com/android/server/task/TaskManagerService.java
deleted file mode 100644
index 0c55a1d..0000000
--- a/services/core/java/com/android/server/task/TaskManagerService.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * 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.task;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import android.app.task.ITaskManager;
-import android.app.task.Task;
-import android.app.task.TaskManager;
-import android.content.BroadcastReceiver;
-import android.app.task.TaskService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ServiceInfo;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.server.task.controllers.BatteryController;
-import com.android.server.task.controllers.ConnectivityController;
-import com.android.server.task.controllers.IdleController;
-import com.android.server.task.controllers.StateController;
-import com.android.server.task.controllers.TaskStatus;
-import com.android.server.task.controllers.TimeController;
-
-import java.util.LinkedList;
-
-/**
- * Responsible for taking tasks representing work to be performed by a client app, and determining
- * based on the criteria specified when that task should be run against the client application's
- * endpoint.
- * Implements logic for scheduling, and rescheduling tasks. The TaskManagerService knows nothing
- * about constraints, or the state of active tasks. It receives callbacks from the various
- * controllers and completed tasks and operates accordingly.
- *
- * Note on locking: Any operations that manipulate {@link #mTasks} need to lock on that object.
- * Any function with the suffix 'Locked' also needs to lock on {@link #mTasks}.
- * @hide
- */
-public class TaskManagerService extends com.android.server.SystemService
-        implements StateChangedListener, TaskCompletedListener, TaskMapReadFinishedListener {
-    // TODO: Switch this off for final version.
-    static final boolean DEBUG = true;
-    /** The number of concurrent tasks we run at one time. */
-    private static final int MAX_TASK_CONTEXTS_COUNT = 3;
-    static final String TAG = "TaskManager";
-    /** Master list of tasks. */
-    private final TaskStore mTasks;
-
-    static final int MSG_TASK_EXPIRED = 0;
-    static final int MSG_CHECK_TASKS = 1;
-
-    // Policy constants
-    /**
-     * Minimum # of idle tasks that must be ready in order to force the TM to schedule things
-     * early.
-     */
-    private static final int MIN_IDLE_COUNT = 1;
-    /**
-     * Minimum # of connectivity tasks that must be ready in order to force the TM to schedule
-     * things early.
-     */
-    private static final int MIN_CONNECTIVITY_COUNT = 2;
-    /**
-     * Minimum # of tasks (with no particular constraints) for which the TM will be happy running
-     * some work early.
-     */
-    private static final int MIN_READY_TASKS_COUNT = 4;
-
-    /**
-     * Track Services that have currently active or pending tasks. The index is provided by
-     * {@link TaskStatus#getServiceToken()}
-     */
-    private final List<TaskServiceContext> mActiveServices = new LinkedList<TaskServiceContext>();
-    /** List of controllers that will notify this service of updates to tasks. */
-    private List<StateController> mControllers;
-    /**
-     * Queue of pending tasks. The TaskServiceContext class will receive tasks from this list
-     * when ready to execute them.
-     */
-    private final LinkedList<TaskStatus> mPendingTasks = new LinkedList<TaskStatus>();
-
-    private final TaskHandler mHandler;
-    private final TaskManagerStub mTaskManagerStub;
-    /**
-     * Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
-     * still clean up. On reinstall the package will have a new uid.
-     */
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Slog.d(TAG, "Receieved: " + intent.getAction());
-            if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
-                int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1);
-                if (DEBUG) {
-                    Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
-                }
-                cancelTasksForUid(uidRemoved);
-            } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
-                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
-                if (DEBUG) {
-                    Slog.d(TAG, "Removing jobs for user: " + userId);
-                }
-                cancelTasksForUser(userId);
-            }
-        }
-    };
-
-    /**
-     * Entry point from client to schedule the provided task.
-     * This cancels the task if it's already been scheduled, and replaces it with the one provided.
-     * @param task Task object containing execution parameters
-     * @param uId The package identifier of the application this task is for.
-     * @param canPersistTask Whether or not the client has the appropriate permissions for
-     *                       persisting this task.
-     * @return Result of this operation. See <code>TaskManager#RESULT_*</code> return codes.
-     */
-    public int schedule(Task task, int uId, boolean canPersistTask) {
-        TaskStatus taskStatus = new TaskStatus(task, uId, canPersistTask);
-        cancelTask(uId, task.getId());
-        startTrackingTask(taskStatus);
-        return TaskManager.RESULT_SUCCESS;
-    }
-
-    public List<Task> getPendingTasks(int uid) {
-        ArrayList<Task> outList = new ArrayList<Task>();
-        synchronized (mTasks) {
-            for (TaskStatus ts : mTasks.getTasks()) {
-                if (ts.getUid() == uid) {
-                    outList.add(ts.getTask());
-                }
-            }
-        }
-        return outList;
-    }
-
-    private void cancelTasksForUser(int userHandle) {
-        synchronized (mTasks) {
-            List<TaskStatus> tasksForUser = mTasks.getTasksByUser(userHandle);
-            for (TaskStatus toRemove : tasksForUser) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
-                cancelTaskLocked(toRemove);
-            }
-        }
-    }
-
-    /**
-     * Entry point from client to cancel all tasks originating from their uid.
-     * This will remove the task from the master list, and cancel the task if it was staged for
-     * execution or being executed.
-     * @param uid To check against for removal of a task.
-     */
-    public void cancelTasksForUid(int uid) {
-        // Remove from master list.
-        synchronized (mTasks) {
-            List<TaskStatus> tasksForUid = mTasks.getTasksByUid(uid);
-            for (TaskStatus toRemove : tasksForUid) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
-                cancelTaskLocked(toRemove);
-            }
-        }
-    }
-
-    /**
-     * Entry point from client to cancel the task corresponding to the taskId provided.
-     * This will remove the task from the master list, and cancel the task if it was staged for
-     * execution or being executed.
-     * @param uid Uid of the calling client.
-     * @param taskId Id of the task, provided at schedule-time.
-     */
-    public void cancelTask(int uid, int taskId) {
-        TaskStatus toCancel;
-        synchronized (mTasks) {
-            toCancel = mTasks.getTaskByUidAndTaskId(uid, taskId);
-            if (toCancel != null) {
-                cancelTaskLocked(toCancel);
-            }
-        }
-    }
-
-    private void cancelTaskLocked(TaskStatus cancelled) {
-        // Remove from store.
-        stopTrackingTask(cancelled);
-        // Remove from pending queue.
-        mPendingTasks.remove(cancelled);
-        // Cancel if running.
-        stopTaskOnServiceContextLocked(cancelled);
-    }
-
-    /**
-     * Initializes the system service.
-     * <p>
-     * Subclasses must define a single argument constructor that accepts the context
-     * and passes it to super.
-     * </p>
-     *
-     * @param context The system server context.
-     */
-    public TaskManagerService(Context context) {
-        super(context);
-        // Create the controllers.
-        mControllers = new LinkedList<StateController>();
-        mControllers.add(ConnectivityController.get(this));
-        mControllers.add(TimeController.get(this));
-        mControllers.add(IdleController.get(this));
-        mControllers.add(BatteryController.get(this));
-
-        mHandler = new TaskHandler(context.getMainLooper());
-        mTaskManagerStub = new TaskManagerStub();
-        // Create the "runners".
-        for (int i = 0; i < MAX_TASK_CONTEXTS_COUNT; i++) {
-            mActiveServices.add(
-                    new TaskServiceContext(this, context.getMainLooper()));
-        }
-        mTasks = TaskStore.initAndGet(this);
-    }
-
-    @Override
-    public void onStart() {
-        publishBinderService(Context.TASK_SERVICE, mTaskManagerStub);
-    }
-
-    @Override
-    public void onBootPhase(int phase) {
-        if (PHASE_SYSTEM_SERVICES_READY == phase) {
-            // Register br for package removals and user removals.
-            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
-            filter.addDataScheme("package");
-            getContext().registerReceiverAsUser(
-                    mBroadcastReceiver, UserHandle.ALL, filter, null, null);
-            final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
-            getContext().registerReceiverAsUser(
-                    mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
-        }
-    }
-
-    /**
-     * Called when we have a task status object that we need to insert in our
-     * {@link com.android.server.task.TaskStore}, and make sure all the relevant controllers know
-     * about.
-     */
-    private void startTrackingTask(TaskStatus taskStatus) {
-        boolean update;
-        synchronized (mTasks) {
-            update = mTasks.add(taskStatus);
-        }
-        for (StateController controller : mControllers) {
-            if (update) {
-                controller.maybeStopTrackingTask(taskStatus);
-            }
-            controller.maybeStartTrackingTask(taskStatus);
-        }
-    }
-
-    /**
-     * Called when we want to remove a TaskStatus object that we've finished executing. Returns the
-     * object removed.
-     */
-    private boolean stopTrackingTask(TaskStatus taskStatus) {
-        boolean removed;
-        synchronized (mTasks) {
-            // Remove from store as well as controllers.
-            removed = mTasks.remove(taskStatus);
-        }
-        if (removed) {
-            for (StateController controller : mControllers) {
-                controller.maybeStopTrackingTask(taskStatus);
-            }
-        }
-        return removed;
-    }
-
-    private boolean stopTaskOnServiceContextLocked(TaskStatus ts) {
-        for (TaskServiceContext tsc : mActiveServices) {
-            final TaskStatus executing = tsc.getRunningTask();
-            if (executing != null && executing.matches(ts.getUid(), ts.getTaskId())) {
-                tsc.cancelExecutingTask();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @param ts TaskStatus we are querying against.
-     * @return Whether or not the task represented by the status object is currently being run or
-     * is pending.
-     */
-    private boolean isCurrentlyActiveLocked(TaskStatus ts) {
-        for (TaskServiceContext serviceContext : mActiveServices) {
-            final TaskStatus running = serviceContext.getRunningTask();
-            if (running != null && running.matches(ts.getUid(), ts.getTaskId())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * A task is rescheduled with exponential back-off if the client requests this from their
-     * execution logic.
-     * A caveat is for idle-mode tasks, for which the idle-mode constraint will usurp the
-     * timeliness of the reschedule. For an idle-mode task, no deadline is given.
-     * @param failureToReschedule Provided task status that we will reschedule.
-     * @return A newly instantiated TaskStatus with the same constraints as the last task except
-     * with adjusted timing constraints.
-     */
-    private TaskStatus getRescheduleTaskForFailure(TaskStatus failureToReschedule) {
-        final long elapsedNowMillis = SystemClock.elapsedRealtime();
-        final Task task = failureToReschedule.getTask();
-
-        final long initialBackoffMillis = task.getInitialBackoffMillis();
-        final int backoffAttempt = failureToReschedule.getNumFailures() + 1;
-        long newEarliestRuntimeElapsed = elapsedNowMillis;
-
-        switch (task.getBackoffPolicy()) {
-            case Task.BackoffPolicy.LINEAR:
-                newEarliestRuntimeElapsed += initialBackoffMillis * backoffAttempt;
-                break;
-            default:
-                if (DEBUG) {
-                    Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
-                }
-            case Task.BackoffPolicy.EXPONENTIAL:
-                newEarliestRuntimeElapsed +=
-                        Math.pow(initialBackoffMillis * 0.001, backoffAttempt) * 1000;
-                break;
-        }
-        newEarliestRuntimeElapsed =
-                Math.min(newEarliestRuntimeElapsed, Task.MAX_BACKOFF_DELAY_MILLIS);
-        return new TaskStatus(failureToReschedule, newEarliestRuntimeElapsed,
-                TaskStatus.NO_LATEST_RUNTIME, backoffAttempt);
-    }
-
-    /**
-     * Called after a periodic has executed so we can to re-add it. We take the last execution time
-     * of the task to be the time of completion (i.e. the time at which this function is called).
-     * This could be inaccurate b/c the task can run for as long as
-     * {@link com.android.server.task.TaskServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
-     * to underscheduling at least, rather than if we had taken the last execution time to be the
-     * start of the execution.
-     * @return A new task representing the execution criteria for this instantiation of the
-     * recurring task.
-     */
-    private TaskStatus getRescheduleTaskForPeriodic(TaskStatus periodicToReschedule) {
-        final long elapsedNow = SystemClock.elapsedRealtime();
-        // Compute how much of the period is remaining.
-        long runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0);
-        long newEarliestRunTimeElapsed = elapsedNow + runEarly;
-        long period = periodicToReschedule.getTask().getIntervalMillis();
-        long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period;
-
-        if (DEBUG) {
-            Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
-                    newEarliestRunTimeElapsed/1000 + ", " + newLatestRuntimeElapsed/1000 + "]s");
-        }
-        return new TaskStatus(periodicToReschedule, newEarliestRunTimeElapsed,
-                newLatestRuntimeElapsed, 0 /* backoffAttempt */);
-    }
-
-    // TaskCompletedListener implementations.
-
-    /**
-     * A task just finished executing. We fetch the
-     * {@link com.android.server.task.controllers.TaskStatus} from the store and depending on
-     * whether we want to reschedule we readd it to the controllers.
-     * @param taskStatus Completed task.
-     * @param needsReschedule Whether the implementing class should reschedule this task.
-     */
-    @Override
-    public void onTaskCompleted(TaskStatus taskStatus, boolean needsReschedule) {
-        if (DEBUG) {
-            Slog.d(TAG, "Completed " + taskStatus + ", reschedule=" + needsReschedule);
-        }
-        if (!stopTrackingTask(taskStatus)) {
-            if (DEBUG) {
-                Slog.e(TAG, "Error removing task: could not find task to remove. Was task " +
-                        "removed while executing?");
-            }
-            return;
-        }
-        if (needsReschedule) {
-            TaskStatus rescheduled = getRescheduleTaskForFailure(taskStatus);
-            startTrackingTask(rescheduled);
-        } else if (taskStatus.getTask().isPeriodic()) {
-            TaskStatus rescheduledPeriodic = getRescheduleTaskForPeriodic(taskStatus);
-            startTrackingTask(rescheduledPeriodic);
-        }
-        mHandler.obtainMessage(MSG_CHECK_TASKS).sendToTarget();
-    }
-
-    // StateChangedListener implementations.
-
-    /**
-     * Off-board work to our handler thread as quickly as possible, b/c this call is probably being
-     * made on the main thread.
-     * For now this takes the task and if it's ready to run it will run it. In future we might not
-     * provide the task, so that the StateChangedListener has to run through its list of tasks to
-     * see which are ready. This will further decouple the controllers from the execution logic.
-     */
-    @Override
-    public void onControllerStateChanged() {
-        // Post a message to to run through the list of tasks and start/stop any that are eligible.
-        mHandler.obtainMessage(MSG_CHECK_TASKS).sendToTarget();
-    }
-
-    @Override
-    public void onRunTaskNow(TaskStatus taskStatus) {
-        mHandler.obtainMessage(MSG_TASK_EXPIRED, taskStatus).sendToTarget();
-    }
-
-    /**
-     * Disk I/O is finished, take the list of tasks we read from disk and add them to our
-     * {@link TaskStore}.
-     * This is run on the {@link com.android.server.IoThread} instance, which is a separate thread,
-     * and is called once at boot.
-     */
-    @Override
-    public void onTaskMapReadFinished(List<TaskStatus> tasks) {
-        synchronized (mTasks) {
-            for (TaskStatus ts : tasks) {
-                if (mTasks.containsTaskIdForUid(ts.getTaskId(), ts.getUid())) {
-                    // An app with BOOT_COMPLETED *might* have decided to reschedule their task, in
-                    // the same amount of time it took us to read it from disk. If this is the case
-                    // we leave it be.
-                    continue;
-                }
-                startTrackingTask(ts);
-            }
-        }
-    }
-
-    private class TaskHandler extends Handler {
-
-        public TaskHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message message) {
-            switch (message.what) {
-                case MSG_TASK_EXPIRED:
-                    synchronized (mTasks) {
-                        TaskStatus runNow = (TaskStatus) message.obj;
-                        if (!mPendingTasks.contains(runNow)) {
-                            mPendingTasks.add(runNow);
-                        }
-                    }
-                    queueReadyTasksForExecutionH();
-                    break;
-                case MSG_CHECK_TASKS:
-                    // Check the list of tasks and run some of them if we feel inclined.
-                    maybeQueueReadyTasksForExecutionH();
-                    break;
-            }
-            maybeRunPendingTasksH();
-            // Don't remove TASK_EXPIRED in case one came along while processing the queue.
-            removeMessages(MSG_CHECK_TASKS);
-        }
-
-        /**
-         * Run through list of tasks and execute all possible - at least one is expired so we do
-         * as many as we can.
-         */
-        private void queueReadyTasksForExecutionH() {
-            synchronized (mTasks) {
-                for (TaskStatus ts : mTasks.getTasks()) {
-                    if (isReadyToBeExecutedLocked(ts)) {
-                        mPendingTasks.add(ts);
-                    } else if (isReadyToBeCancelledLocked(ts)) {
-                        stopTaskOnServiceContextLocked(ts);
-                    }
-                }
-            }
-        }
-
-        /**
-         * The state of at least one task has changed. Here is where we could enforce various
-         * policies on when we want to execute tasks.
-         * Right now the policy is such:
-         * If >1 of the ready tasks is idle mode we send all of them off
-         * if more than 2 network connectivity tasks are ready we send them all off.
-         * If more than 4 tasks total are ready we send them all off.
-         * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
-         */
-        private void maybeQueueReadyTasksForExecutionH() {
-            synchronized (mTasks) {
-                int idleCount = 0;
-                int backoffCount = 0;
-                int connectivityCount = 0;
-                List<TaskStatus> runnableTasks = new ArrayList<TaskStatus>();
-                for (TaskStatus ts : mTasks.getTasks()) {
-                    if (isReadyToBeExecutedLocked(ts)) {
-                        if (ts.getNumFailures() > 0) {
-                            backoffCount++;
-                        }
-                        if (ts.hasIdleConstraint()) {
-                            idleCount++;
-                        }
-                        if (ts.hasConnectivityConstraint() || ts.hasUnmeteredConstraint()) {
-                            connectivityCount++;
-                        }
-                        runnableTasks.add(ts);
-                    } else if (isReadyToBeCancelledLocked(ts)) {
-                        stopTaskOnServiceContextLocked(ts);
-                    }
-                }
-                if (backoffCount > 0 || idleCount >= MIN_IDLE_COUNT ||
-                        connectivityCount >= MIN_CONNECTIVITY_COUNT ||
-                        runnableTasks.size() >= MIN_READY_TASKS_COUNT) {
-                    for (TaskStatus ts : runnableTasks) {
-                        mPendingTasks.add(ts);
-                    }
-                }
-            }
-        }
-
-        /**
-         * Criteria for moving a job into the pending queue:
-         *      - It's ready.
-         *      - It's not pending.
-         *      - It's not already running on a TSC.
-         */
-        private boolean isReadyToBeExecutedLocked(TaskStatus ts) {
-              return ts.isReady() && !mPendingTasks.contains(ts) && !isCurrentlyActiveLocked(ts);
-        }
-
-        /**
-         * Criteria for cancelling an active job:
-         *      - It's not ready
-         *      - It's running on a TSC.
-         */
-        private boolean isReadyToBeCancelledLocked(TaskStatus ts) {
-            return !ts.isReady() && isCurrentlyActiveLocked(ts);
-        }
-
-        /**
-         * Reconcile jobs in the pending queue against available execution contexts.
-         * A controller can force a task into the pending queue even if it's already running, but
-         * here is where we decide whether to actually execute it.
-         */
-        private void maybeRunPendingTasksH() {
-            synchronized (mTasks) {
-                Iterator<TaskStatus> it = mPendingTasks.iterator();
-                while (it.hasNext()) {
-                    TaskStatus nextPending = it.next();
-                    TaskServiceContext availableContext = null;
-                    for (TaskServiceContext tsc : mActiveServices) {
-                        final TaskStatus running = tsc.getRunningTask();
-                        if (running != null && running.matches(nextPending.getUid(),
-                                nextPending.getTaskId())) {
-                            // Already running this tId for this uId, skip.
-                            availableContext = null;
-                            break;
-                        }
-                        if (tsc.isAvailable()) {
-                            availableContext = tsc;
-                        }
-                    }
-                    if (availableContext != null) {
-                        if (!availableContext.executeRunnableTask(nextPending)) {
-                            if (DEBUG) {
-                                Slog.d(TAG, "Error executing " + nextPending);
-                            }
-                            mTasks.remove(nextPending);
-                        }
-                        it.remove();
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Binder stub trampoline implementation
-     */
-    final class TaskManagerStub extends ITaskManager.Stub {
-        /** Cache determination of whether a given app can persist tasks
-         * key is uid of the calling app; value is undetermined/true/false
-         */
-        private final SparseArray<Boolean> mPersistCache = new SparseArray<Boolean>();
-
-        // Enforce that only the app itself (or shared uid participant) can schedule a
-        // task that runs one of the app's services, as well as verifying that the
-        // named service properly requires the BIND_TASK_SERVICE permission
-        private void enforceValidJobRequest(int uid, Task job) {
-            final PackageManager pm = getContext().getPackageManager();
-            final ComponentName service = job.getService();
-            try {
-                ServiceInfo si = pm.getServiceInfo(service, 0);
-                if (si.applicationInfo.uid != uid) {
-                    throw new IllegalArgumentException("uid " + uid +
-                            " cannot schedule job in " + service.getPackageName());
-                }
-                if (!TaskService.PERMISSION_BIND.equals(si.permission)) {
-                    throw new IllegalArgumentException("Scheduled service " + service
-                            + " does not require android.permission.BIND_TASK_SERVICE permission");
-                }
-            } catch (NameNotFoundException e) {
-                throw new IllegalArgumentException("No such service: " + service);
-            }
-        }
-
-        private boolean canPersistJobs(int pid, int uid) {
-            // If we get this far we're good to go; all we need to do now is check
-            // whether the app is allowed to persist its scheduled work.
-            final boolean canPersist;
-            synchronized (mPersistCache) {
-                Boolean cached = mPersistCache.get(uid);
-                if (cached != null) {
-                    canPersist = cached.booleanValue();
-                } else {
-                    // Persisting tasks is tantamount to running at boot, so we permit
-                    // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
-                    // permission
-                    int result = getContext().checkPermission(
-                            android.Manifest.permission.RECEIVE_BOOT_COMPLETED, pid, uid);
-                    canPersist = (result == PackageManager.PERMISSION_GRANTED);
-                    mPersistCache.put(uid, canPersist);
-                }
-            }
-            return canPersist;
-        }
-
-        // ITaskManager implementation
-        @Override
-        public int schedule(Task task) throws RemoteException {
-            if (DEBUG) {
-                Slog.d(TAG, "Scheduling task: " + task);
-            }
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-
-            enforceValidJobRequest(uid, task);
-            final boolean canPersist = canPersistJobs(pid, uid);
-
-            long ident = Binder.clearCallingIdentity();
-            try {
-                return TaskManagerService.this.schedule(task, uid, canPersist);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override
-        public List<Task> getAllPendingTasks() throws RemoteException {
-            final int uid = Binder.getCallingUid();
-
-            long ident = Binder.clearCallingIdentity();
-            try {
-                return TaskManagerService.this.getPendingTasks(uid);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override
-        public void cancelAll() throws RemoteException {
-            final int uid = Binder.getCallingUid();
-
-            long ident = Binder.clearCallingIdentity();
-            try {
-                TaskManagerService.this.cancelTasksForUid(uid);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override
-        public void cancel(int taskId) throws RemoteException {
-            final int uid = Binder.getCallingUid();
-
-            long ident = Binder.clearCallingIdentity();
-            try {
-                TaskManagerService.this.cancelTask(uid, taskId);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        /**
-         * "dumpsys" infrastructure
-         */
-        @Override
-        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
-
-            long identityToken = Binder.clearCallingIdentity();
-            try {
-                TaskManagerService.this.dumpInternal(pw);
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-    };
-
-    void dumpInternal(PrintWriter pw) {
-        synchronized (mTasks) {
-            pw.println("Registered tasks:");
-            if (mTasks.size() > 0) {
-                for (TaskStatus ts : mTasks.getTasks()) {
-                    ts.dump(pw, "  ");
-                }
-            } else {
-                pw.println();
-                pw.println("No tasks scheduled.");
-            }
-            for (StateController controller : mControllers) {
-                pw.println();
-                controller.dumpControllerState(pw);
-            }
-            pw.println();
-            pw.println("Pending");
-            for (TaskStatus taskStatus : mPendingTasks) {
-                pw.println(taskStatus.hashCode());
-            }
-            pw.println();
-            pw.println("Active jobs:");
-            for (TaskServiceContext tsc : mActiveServices) {
-                if (tsc.isAvailable()) {
-                    continue;
-                } else {
-                    pw.println(tsc.getRunningTask().hashCode() + " for: " +
-                            (SystemClock.elapsedRealtime()
-                                    - tsc.getExecutionStartTimeElapsed())/1000 + "s " +
-                            "timeout: " + tsc.getTimeoutElapsed());
-                }
-            }
-        }
-        pw.println();
-    }
-}
diff --git a/services/core/java/com/android/server/task/TaskStore.java b/services/core/java/com/android/server/task/TaskStore.java
deleted file mode 100644
index 9e095e7..0000000
--- a/services/core/java/com/android/server/task/TaskStore.java
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * 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.task;
-
-import android.content.ComponentName;
-import android.app.task.Task;
-import android.content.Context;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.AtomicFile;
-import android.util.ArraySet;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.Xml;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.server.IoThread;
-import com.android.server.task.controllers.TaskStatus;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-/**
- * Maintain a list of classes, and accessor methods/logic for these tasks.
- * This class offers the following functionality:
- *     - When a task is added, it will determine if the task requirements have changed (update) and
- *       whether the controllers need to be updated.
- *     - Persists Tasks, figures out when to to rewrite the Task to disk.
- *     - Handles rescheduling of tasks.
- *       - When a periodic task is executed and must be re-added.
- *       - When a task fails and the client requests that it be retried with backoff.
- *       - This class <strong>is not</strong> thread-safe.
- *
- * Note on locking:
- *      All callers to this class must <strong>lock on the class object they are calling</strong>.
- *      This is important b/c {@link com.android.server.task.TaskStore.WriteTasksMapToDiskRunnable}
- *      and {@link com.android.server.task.TaskStore.ReadTaskMapFromDiskRunnable} lock on that
- *      object.
- */
-public class TaskStore {
-    private static final String TAG = "TaskManagerStore";
-    private static final boolean DEBUG = TaskManagerService.DEBUG;
-
-    /** Threshold to adjust how often we want to write to the db. */
-    private static final int MAX_OPS_BEFORE_WRITE = 1;
-    final ArraySet<TaskStatus> mTasksSet;
-    final Context mContext;
-
-    private int mDirtyOperations;
-
-    private static final Object sSingletonLock = new Object();
-    private final AtomicFile mTasksFile;
-    /** Handler backed by IoThread for writing to disk. */
-    private final Handler mIoHandler = IoThread.getHandler();
-    private static TaskStore sSingleton;
-
-    /** Used by the {@Link TaskManagerService} to instantiate the TaskStore. */
-    static TaskStore initAndGet(TaskManagerService taskManagerService) {
-        synchronized (sSingletonLock) {
-            if (sSingleton == null) {
-                sSingleton = new TaskStore(taskManagerService.getContext(),
-                        Environment.getDataDirectory(), taskManagerService);
-            }
-            return sSingleton;
-        }
-    }
-
-    @VisibleForTesting
-    public static TaskStore initAndGetForTesting(Context context, File dataDir,
-                                                 TaskMapReadFinishedListener callback) {
-        return new TaskStore(context, dataDir, callback);
-    }
-
-    private TaskStore(Context context, File dataDir, TaskMapReadFinishedListener callback) {
-        mContext = context;
-        mDirtyOperations = 0;
-
-        File systemDir = new File(dataDir, "system");
-        File taskDir = new File(systemDir, "task");
-        taskDir.mkdirs();
-        mTasksFile = new AtomicFile(new File(taskDir, "tasks.xml"));
-
-        mTasksSet = new ArraySet<TaskStatus>();
-
-        readTaskMapFromDiskAsync(callback);
-    }
-
-    /**
-     * Add a task to the master list, persisting it if necessary. If the TaskStatus already exists,
-     * it will be replaced.
-     * @param taskStatus Task to add.
-     * @return Whether or not an equivalent TaskStatus was replaced by this operation.
-     */
-    public boolean add(TaskStatus taskStatus) {
-        boolean replaced = mTasksSet.remove(taskStatus);
-        mTasksSet.add(taskStatus);
-        if (taskStatus.isPersisted()) {
-            maybeWriteStatusToDiskAsync();
-        }
-        if (DEBUG) {
-            Slog.d(TAG, "Added task status to store: " + taskStatus);
-        }
-        return replaced;
-    }
-
-    /**
-     * Whether this taskStatus object already exists in the TaskStore.
-     */
-    public boolean containsTaskIdForUid(int taskId, int uId) {
-        for (TaskStatus ts : mTasksSet) {
-            if (ts.getUid() == uId && ts.getTaskId() == taskId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public int size() {
-        return mTasksSet.size();
-    }
-
-    /**
-     * Remove the provided task. Will also delete the task if it was persisted.
-     * @return Whether or not the task existed to be removed.
-     */
-    public boolean remove(TaskStatus taskStatus) {
-        boolean removed = mTasksSet.remove(taskStatus);
-        if (!removed) {
-            if (DEBUG) {
-                Slog.d(TAG, "Couldn't remove task: didn't exist: " + taskStatus);
-            }
-            return false;
-        }
-        maybeWriteStatusToDiskAsync();
-        return removed;
-    }
-
-    @VisibleForTesting
-    public void clear() {
-        mTasksSet.clear();
-        maybeWriteStatusToDiskAsync();
-    }
-
-    public List<TaskStatus> getTasksByUser(int userHandle) {
-        List<TaskStatus> matchingTasks = new ArrayList<TaskStatus>();
-        Iterator<TaskStatus> it = mTasksSet.iterator();
-        while (it.hasNext()) {
-            TaskStatus ts = it.next();
-            if (UserHandle.getUserId(ts.getUid()) == userHandle) {
-                matchingTasks.add(ts);
-            }
-        }
-        return matchingTasks;
-    }
-
-    /**
-     * @param uid Uid of the requesting app.
-     * @return All TaskStatus objects for a given uid from the master list.
-     */
-    public List<TaskStatus> getTasksByUid(int uid) {
-        List<TaskStatus> matchingTasks = new ArrayList<TaskStatus>();
-        Iterator<TaskStatus> it = mTasksSet.iterator();
-        while (it.hasNext()) {
-            TaskStatus ts = it.next();
-            if (ts.getUid() == uid) {
-                matchingTasks.add(ts);
-            }
-        }
-        return matchingTasks;
-    }
-
-    /**
-     * @param uid Uid of the requesting app.
-     * @param taskId Task id, specified at schedule-time.
-     * @return the TaskStatus that matches the provided uId and taskId, or null if none found.
-     */
-    public TaskStatus getTaskByUidAndTaskId(int uid, int taskId) {
-        Iterator<TaskStatus> it = mTasksSet.iterator();
-        while (it.hasNext()) {
-            TaskStatus ts = it.next();
-            if (ts.getUid() == uid && ts.getTaskId() == taskId) {
-                return ts;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @return The live array of TaskStatus objects.
-     */
-    public ArraySet<TaskStatus> getTasks() {
-        return mTasksSet;
-    }
-
-    /** Version of the db schema. */
-    private static final int TASKS_FILE_VERSION = 0;
-    /** Tag corresponds to constraints this task needs. */
-    private static final String XML_TAG_PARAMS_CONSTRAINTS = "constraints";
-    /** Tag corresponds to execution parameters. */
-    private static final String XML_TAG_PERIODIC = "periodic";
-    private static final String XML_TAG_ONEOFF = "one-off";
-    private static final String XML_TAG_EXTRAS = "extras";
-
-    /**
-     * Every time the state changes we write all the tasks in one swathe, instead of trying to
-     * track incremental changes.
-     * @return Whether the operation was successful. This will only fail for e.g. if the system is
-     * low on storage. If this happens, we continue as normal
-     */
-    private void maybeWriteStatusToDiskAsync() {
-        mDirtyOperations++;
-        if (mDirtyOperations >= MAX_OPS_BEFORE_WRITE) {
-            if (DEBUG) {
-                Slog.v(TAG, "Writing tasks to disk.");
-            }
-            mIoHandler.post(new WriteTasksMapToDiskRunnable());
-        }
-    }
-
-    private void readTaskMapFromDiskAsync(TaskMapReadFinishedListener callback) {
-        mIoHandler.post(new ReadTaskMapFromDiskRunnable(callback));
-    }
-
-    public void readTaskMapFromDisk(TaskMapReadFinishedListener callback) {
-        new ReadTaskMapFromDiskRunnable(callback).run();
-    }
-
-    /**
-     * Runnable that writes {@link #mTasksSet} out to xml.
-     * NOTE: This Runnable locks on TaskStore.this
-     */
-    private class WriteTasksMapToDiskRunnable implements Runnable {
-        @Override
-        public void run() {
-            final long startElapsed = SystemClock.elapsedRealtime();
-            synchronized (TaskStore.this) {
-                writeTasksMapImpl();
-            }
-            if (TaskManagerService.DEBUG) {
-                Slog.v(TAG, "Finished writing, took " + (SystemClock.elapsedRealtime()
-                        - startElapsed) + "ms");
-            }
-        }
-
-        private void writeTasksMapImpl() {
-            try {
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                XmlSerializer out = new FastXmlSerializer();
-                out.setOutput(baos, "utf-8");
-                out.startDocument(null, true);
-                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-                out.startTag(null, "task-info");
-                out.attribute(null, "version", Integer.toString(TASKS_FILE_VERSION));
-                for (int i = 0; i < mTasksSet.size(); i++) {
-                    final TaskStatus taskStatus = mTasksSet.valueAt(i);
-                    if (DEBUG) {
-                        Slog.d(TAG, "Saving task " + taskStatus.getTaskId());
-                    }
-                    out.startTag(null, "task");
-                    addIdentifierAttributesToTaskTag(out, taskStatus);
-                    writeConstraintsToXml(out, taskStatus);
-                    writeExecutionCriteriaToXml(out, taskStatus);
-                    writeBundleToXml(taskStatus.getExtras(), out);
-                    out.endTag(null, "task");
-                }
-                out.endTag(null, "task-info");
-                out.endDocument();
-
-                // Write out to disk in one fell sweep.
-                FileOutputStream fos = mTasksFile.startWrite();
-                fos.write(baos.toByteArray());
-                mTasksFile.finishWrite(fos);
-                mDirtyOperations = 0;
-            } catch (IOException e) {
-                if (DEBUG) {
-                    Slog.v(TAG, "Error writing out task data.", e);
-                }
-            } catch (XmlPullParserException e) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Error persisting bundle.", e);
-                }
-            }
-        }
-
-        /** Write out a tag with data comprising the required fields of this task and its client. */
-        private void addIdentifierAttributesToTaskTag(XmlSerializer out, TaskStatus taskStatus)
-                throws IOException {
-            out.attribute(null, "taskid", Integer.toString(taskStatus.getTaskId()));
-            out.attribute(null, "package", taskStatus.getServiceComponent().getPackageName());
-            out.attribute(null, "class", taskStatus.getServiceComponent().getClassName());
-            out.attribute(null, "uid", Integer.toString(taskStatus.getUid()));
-        }
-
-        private void writeBundleToXml(PersistableBundle extras, XmlSerializer out)
-                throws IOException, XmlPullParserException {
-            out.startTag(null, XML_TAG_EXTRAS);
-            extras.saveToXml(out);
-            out.endTag(null, XML_TAG_EXTRAS);
-        }
-        /**
-         * Write out a tag with data identifying this tasks constraints. If the constraint isn't here
-         * it doesn't apply.
-         */
-        private void writeConstraintsToXml(XmlSerializer out, TaskStatus taskStatus) throws IOException {
-            out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
-            if (taskStatus.hasUnmeteredConstraint()) {
-                out.attribute(null, "unmetered", Boolean.toString(true));
-            }
-            if (taskStatus.hasConnectivityConstraint()) {
-                out.attribute(null, "connectivity", Boolean.toString(true));
-            }
-            if (taskStatus.hasIdleConstraint()) {
-                out.attribute(null, "idle", Boolean.toString(true));
-            }
-            if (taskStatus.hasChargingConstraint()) {
-                out.attribute(null, "charging", Boolean.toString(true));
-            }
-            out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
-        }
-
-        private void writeExecutionCriteriaToXml(XmlSerializer out, TaskStatus taskStatus)
-                throws IOException {
-            final Task task = taskStatus.getTask();
-            if (taskStatus.getTask().isPeriodic()) {
-                out.startTag(null, XML_TAG_PERIODIC);
-                out.attribute(null, "period", Long.toString(task.getIntervalMillis()));
-            } else {
-                out.startTag(null, XML_TAG_ONEOFF);
-            }
-
-            if (taskStatus.hasDeadlineConstraint()) {
-                // Wall clock deadline.
-                final long deadlineWallclock =  System.currentTimeMillis() +
-                        (taskStatus.getLatestRunTimeElapsed() - SystemClock.elapsedRealtime());
-                out.attribute(null, "deadline", Long.toString(deadlineWallclock));
-            }
-            if (taskStatus.hasTimingDelayConstraint()) {
-                final long delayWallclock = System.currentTimeMillis() +
-                        (taskStatus.getEarliestRunTime() - SystemClock.elapsedRealtime());
-                out.attribute(null, "delay", Long.toString(delayWallclock));
-            }
-
-            // Only write out back-off policy if it differs from the default.
-            // This also helps the case where the task is idle -> these aren't allowed to specify
-            // back-off.
-            if (taskStatus.getTask().getInitialBackoffMillis() != Task.DEFAULT_INITIAL_BACKOFF_MILLIS
-                    || taskStatus.getTask().getBackoffPolicy() != Task.DEFAULT_BACKOFF_POLICY) {
-                out.attribute(null, "backoff-policy", Integer.toString(task.getBackoffPolicy()));
-                out.attribute(null, "initial-backoff", Long.toString(task.getInitialBackoffMillis()));
-            }
-            if (task.isPeriodic()) {
-                out.endTag(null, XML_TAG_PERIODIC);
-            } else {
-                out.endTag(null, XML_TAG_ONEOFF);
-            }
-        }
-    }
-
-    /**
-     * Runnable that reads list of persisted task from xml.
-     * NOTE: This Runnable locks on TaskStore.this
-     */
-    private class ReadTaskMapFromDiskRunnable implements Runnable {
-        private TaskMapReadFinishedListener mCallback;
-        public ReadTaskMapFromDiskRunnable(TaskMapReadFinishedListener callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void run() {
-            try {
-                List<TaskStatus> tasks;
-                FileInputStream fis = mTasksFile.openRead();
-                synchronized (TaskStore.this) {
-                    tasks = readTaskMapImpl(fis);
-                }
-                fis.close();
-                if (tasks != null) {
-                    mCallback.onTaskMapReadFinished(tasks);
-                }
-            } catch (FileNotFoundException e) {
-                if (TaskManagerService.DEBUG) {
-                    Slog.d(TAG, "Could not find tasks file, probably there was nothing to load.");
-                }
-            } catch (XmlPullParserException e) {
-                if (TaskManagerService.DEBUG) {
-                    Slog.d(TAG, "Error parsing xml.", e);
-                }
-            } catch (IOException e) {
-                if (TaskManagerService.DEBUG) {
-                    Slog.d(TAG, "Error parsing xml.", e);
-                }
-            }
-        }
-
-        private List<TaskStatus> readTaskMapImpl(FileInputStream fis) throws XmlPullParserException, IOException {
-            XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
-
-            int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.START_TAG &&
-                    eventType != XmlPullParser.END_DOCUMENT) {
-                eventType = parser.next();
-                Slog.d(TAG, parser.getName());
-            }
-            if (eventType == XmlPullParser.END_DOCUMENT) {
-                if (DEBUG) {
-                    Slog.d(TAG, "No persisted tasks.");
-                }
-                return null;
-            }
-
-            String tagName = parser.getName();
-            if ("task-info".equals(tagName)) {
-                final List<TaskStatus> tasks = new ArrayList<TaskStatus>();
-                // Read in version info.
-                try {
-                    int version = Integer.valueOf(parser.getAttributeValue(null, "version"));
-                    if (version != TASKS_FILE_VERSION) {
-                        Slog.d(TAG, "Invalid version number, aborting tasks file read.");
-                        return null;
-                    }
-                } catch (NumberFormatException e) {
-                    Slog.e(TAG, "Invalid version number, aborting tasks file read.");
-                    return null;
-                }
-                eventType = parser.next();
-                do {
-                    // Read each <task/>
-                    if (eventType == XmlPullParser.START_TAG) {
-                        tagName = parser.getName();
-                        // Start reading task.
-                        if ("task".equals(tagName)) {
-                            TaskStatus persistedTask = restoreTaskFromXml(parser);
-                            if (persistedTask != null) {
-                                if (DEBUG) {
-                                    Slog.d(TAG, "Read out " + persistedTask);
-                                }
-                                tasks.add(persistedTask);
-                            } else {
-                                Slog.d(TAG, "Error reading task from file.");
-                            }
-                        }
-                    }
-                    eventType = parser.next();
-                } while (eventType != XmlPullParser.END_DOCUMENT);
-                return tasks;
-            }
-            return null;
-        }
-
-        /**
-         * @param parser Xml parser at the beginning of a "<task/>" tag. The next "parser.next()" call
-         *               will take the parser into the body of the task tag.
-         * @return Newly instantiated task holding all the information we just read out of the xml tag.
-         */
-        private TaskStatus restoreTaskFromXml(XmlPullParser parser) throws XmlPullParserException,
-                IOException {
-            Task.Builder taskBuilder;
-            int uid;
-
-            // Read out task identifier attributes.
-            try {
-                taskBuilder = buildBuilderFromXml(parser);
-                uid = Integer.valueOf(parser.getAttributeValue(null, "uid"));
-            } catch (NumberFormatException e) {
-                Slog.e(TAG, "Error parsing task's required fields, skipping");
-                return null;
-            }
-
-            int eventType;
-            // Read out constraints tag.
-            do {
-                eventType = parser.next();
-            } while (eventType == XmlPullParser.TEXT);  // Push through to next START_TAG.
-
-            if (!(eventType == XmlPullParser.START_TAG &&
-                    XML_TAG_PARAMS_CONSTRAINTS.equals(parser.getName()))) {
-                // Expecting a <constraints> start tag.
-                return null;
-            }
-            try {
-                buildConstraintsFromXml(taskBuilder, parser);
-            } catch (NumberFormatException e) {
-                Slog.d(TAG, "Error reading constraints, skipping.");
-                return null;
-            }
-            parser.next(); // Consume </constraints>
-
-            // Read out execution parameters tag.
-            do {
-                eventType = parser.next();
-            } while (eventType == XmlPullParser.TEXT);
-            if (eventType != XmlPullParser.START_TAG) {
-                return null;
-            }
-
-            Pair<Long, Long> runtimes;
-            try {
-                runtimes = buildExecutionTimesFromXml(parser);
-            } catch (NumberFormatException e) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Error parsing execution time parameters, skipping.");
-                }
-                return null;
-            }
-
-            if (XML_TAG_PERIODIC.equals(parser.getName())) {
-                try {
-                    String val = parser.getAttributeValue(null, "period");
-                    taskBuilder.setPeriodic(Long.valueOf(val));
-                } catch (NumberFormatException e) {
-                    Slog.d(TAG, "Error reading periodic execution criteria, skipping.");
-                    return null;
-                }
-            } else if (XML_TAG_ONEOFF.equals(parser.getName())) {
-                try {
-                    if (runtimes.first != TaskStatus.NO_EARLIEST_RUNTIME) {
-                        taskBuilder.setMinimumLatency(runtimes.first - SystemClock.elapsedRealtime());
-                    }
-                    if (runtimes.second != TaskStatus.NO_LATEST_RUNTIME) {
-                        taskBuilder.setOverrideDeadline(
-                                runtimes.second - SystemClock.elapsedRealtime());
-                    }
-                } catch (NumberFormatException e) {
-                    Slog.d(TAG, "Error reading task execution criteria, skipping.");
-                    return null;
-                }
-            } else {
-                if (DEBUG) {
-                    Slog.d(TAG, "Invalid parameter tag, skipping - " + parser.getName());
-                }
-                // Expecting a parameters start tag.
-                return null;
-            }
-            maybeBuildBackoffPolicyFromXml(taskBuilder, parser);
-
-            parser.nextTag(); // Consume parameters end tag.
-
-            // Read out extras Bundle.
-            do {
-                eventType = parser.next();
-            } while (eventType == XmlPullParser.TEXT);
-            if (!(eventType == XmlPullParser.START_TAG && XML_TAG_EXTRAS.equals(parser.getName()))) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Error reading extras, skipping.");
-                }
-                return null;
-            }
-
-            PersistableBundle extras = PersistableBundle.restoreFromXml(parser);
-            taskBuilder.setExtras(extras);
-            parser.nextTag(); // Consume </extras>
-
-            return new TaskStatus(taskBuilder.build(), uid, runtimes.first, runtimes.second);
-        }
-
-        private Task.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException {
-            // Pull out required fields from <task> attributes.
-            int taskId = Integer.valueOf(parser.getAttributeValue(null, "taskid"));
-            String packageName = parser.getAttributeValue(null, "package");
-            String className = parser.getAttributeValue(null, "class");
-            ComponentName cname = new ComponentName(packageName, className);
-
-            return new Task.Builder(taskId, cname);
-        }
-
-        private void buildConstraintsFromXml(Task.Builder taskBuilder, XmlPullParser parser) {
-            String val = parser.getAttributeValue(null, "unmetered");
-            if (val != null) {
-                taskBuilder.setRequiredNetworkCapabilities(Task.NetworkType.UNMETERED);
-            }
-            val = parser.getAttributeValue(null, "connectivity");
-            if (val != null) {
-                taskBuilder.setRequiredNetworkCapabilities(Task.NetworkType.ANY);
-            }
-            val = parser.getAttributeValue(null, "idle");
-            if (val != null) {
-                taskBuilder.setRequiresDeviceIdle(true);
-            }
-            val = parser.getAttributeValue(null, "charging");
-            if (val != null) {
-                taskBuilder.setRequiresCharging(true);
-            }
-        }
-
-        /**
-         * Builds the back-off policy out of the params tag. These attributes may not exist, depending
-         * on whether the back-off was set when the task was first scheduled.
-         */
-        private void maybeBuildBackoffPolicyFromXml(Task.Builder taskBuilder, XmlPullParser parser) {
-            String val = parser.getAttributeValue(null, "initial-backoff");
-            if (val != null) {
-                long initialBackoff = Long.valueOf(val);
-                val = parser.getAttributeValue(null, "backoff-policy");
-                int backoffPolicy = Integer.valueOf(val);  // Will throw NFE which we catch higher up.
-                taskBuilder.setBackoffCriteria(initialBackoff, backoffPolicy);
-            }
-        }
-
-        /**
-         * Convenience function to read out and convert deadline and delay from xml into elapsed real
-         * time.
-         * @return A {@link android.util.Pair}, where the first value is the earliest elapsed runtime
-         * and the second is the latest elapsed runtime.
-         */
-        private Pair<Long, Long> buildExecutionTimesFromXml(XmlPullParser parser)
-                throws NumberFormatException {
-            // Pull out execution time data.
-            final long nowWallclock = System.currentTimeMillis();
-            final long nowElapsed = SystemClock.elapsedRealtime();
-
-            long earliestRunTimeElapsed = TaskStatus.NO_EARLIEST_RUNTIME;
-            long latestRunTimeElapsed = TaskStatus.NO_LATEST_RUNTIME;
-            String val = parser.getAttributeValue(null, "deadline");
-            if (val != null) {
-                long latestRuntimeWallclock = Long.valueOf(val);
-                long maxDelayElapsed =
-                        Math.max(latestRuntimeWallclock - nowWallclock, 0);
-                latestRunTimeElapsed = nowElapsed + maxDelayElapsed;
-            }
-            val = parser.getAttributeValue(null, "delay");
-            if (val != null) {
-                long earliestRuntimeWallclock = Long.valueOf(val);
-                long minDelayElapsed =
-                        Math.max(earliestRuntimeWallclock - nowWallclock, 0);
-                earliestRunTimeElapsed = nowElapsed + minDelayElapsed;
-
-            }
-            return Pair.create(earliestRunTimeElapsed, latestRunTimeElapsed);
-        }
-    }
-}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/task/controllers/TaskStatus.java b/services/core/java/com/android/server/task/controllers/TaskStatus.java
deleted file mode 100644
index a286737..0000000
--- a/services/core/java/com/android/server/task/controllers/TaskStatus.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.task.controllers;
-
-import android.app.task.Task;
-import android.content.ComponentName;
-import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.os.UserHandle;
-
-import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Uniquely identifies a task internally.
- * Created from the public {@link android.app.task.Task} object when it lands on the scheduler.
- * Contains current state of the requirements of the task, as well as a function to evaluate
- * whether it's ready to run.
- * This object is shared among the various controllers - hence why the different fields are atomic.
- * This isn't strictly necessary because each controller is only interested in a specific field,
- * and the receivers that are listening for global state change will all run on the main looper,
- * but we don't enforce that so this is safer.
- * @hide
- */
-public class TaskStatus {
-    public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
-    public static final long NO_EARLIEST_RUNTIME = 0L;
-
-    final Task task;
-    final int uId;
-
-    /** At reschedule time we need to know whether to update task on disk. */
-    final boolean persisted;
-
-    // Constraints.
-    final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean();
-    final AtomicBoolean timeDelayConstraintSatisfied = new AtomicBoolean();
-    final AtomicBoolean deadlineConstraintSatisfied = new AtomicBoolean();
-    final AtomicBoolean idleConstraintSatisfied = new AtomicBoolean();
-    final AtomicBoolean unmeteredConstraintSatisfied = new AtomicBoolean();
-    final AtomicBoolean connectivityConstraintSatisfied = new AtomicBoolean();
-
-    /**
-     * Earliest point in the future at which this task will be eligible to run. A value of 0
-     * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
-     */
-    private long earliestRunTimeElapsedMillis;
-    /**
-     * Latest point in the future at which this task must be run. A value of {@link Long#MAX_VALUE}
-     * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
-     */
-    private long latestRunTimeElapsedMillis;
-    /** How many times this task has failed, used to compute back-off. */
-    private final int numFailures;
-
-    /** Provide a handle to the service that this task will be run on. */
-    public int getServiceToken() {
-        return uId;
-    }
-
-    private TaskStatus(Task task, int uId, boolean persisted, int numFailures) {
-        this.task = task;
-        this.uId = uId;
-        this.numFailures = numFailures;
-        this.persisted = persisted;
-    }
-
-    /** Create a newly scheduled task. */
-    public TaskStatus(Task task, int uId, boolean persisted) {
-        this(task, uId, persisted, 0);
-
-        final long elapsedNow = SystemClock.elapsedRealtime();
-
-        if (task.isPeriodic()) {
-            earliestRunTimeElapsedMillis = elapsedNow;
-            latestRunTimeElapsedMillis = elapsedNow + task.getIntervalMillis();
-        } else {
-            earliestRunTimeElapsedMillis = task.hasEarlyConstraint() ?
-                    elapsedNow + task.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
-            latestRunTimeElapsedMillis = task.hasLateConstraint() ?
-                    elapsedNow + task.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
-        }
-    }
-
-    /**
-     * Create a new TaskStatus that was loaded from disk. We ignore the provided
-     * {@link android.app.task.Task} time criteria because we can load a persisted periodic task
-     * from the {@link com.android.server.task.TaskStore} and still want to respect its
-     * wallclock runtime rather than resetting it on every boot.
-     * We consider a freshly loaded task to no longer be in back-off.
-     */
-    public TaskStatus(Task task, int uId, long earliestRunTimeElapsedMillis,
-                      long latestRunTimeElapsedMillis) {
-        this(task, uId, true, 0);
-
-        this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
-        this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
-    }
-
-    /** Create a new task to be rescheduled with the provided parameters. */
-    public TaskStatus(TaskStatus rescheduling, long newEarliestRuntimeElapsedMillis,
-                      long newLatestRuntimeElapsedMillis, int backoffAttempt) {
-        this(rescheduling.task, rescheduling.getUid(), rescheduling.isPersisted(), backoffAttempt);
-
-        earliestRunTimeElapsedMillis = newEarliestRuntimeElapsedMillis;
-        latestRunTimeElapsedMillis = newLatestRuntimeElapsedMillis;
-    }
-
-    public Task getTask() {
-        return task;
-    }
-
-    public int getTaskId() {
-        return task.getId();
-    }
-
-    public int getNumFailures() {
-        return numFailures;
-    }
-
-    public ComponentName getServiceComponent() {
-        return task.getService();
-    }
-
-    public int getUserId() {
-        return UserHandle.getUserId(uId);
-    }
-
-    public int getUid() {
-        return uId;
-    }
-
-    public PersistableBundle getExtras() {
-        return task.getExtras();
-    }
-
-    public boolean hasConnectivityConstraint() {
-        return task.getNetworkCapabilities() == Task.NetworkType.ANY;
-    }
-
-    public boolean hasUnmeteredConstraint() {
-        return task.getNetworkCapabilities() == Task.NetworkType.UNMETERED;
-    }
-
-    public boolean hasChargingConstraint() {
-        return task.isRequireCharging();
-    }
-
-    public boolean hasTimingDelayConstraint() {
-        return earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME;
-    }
-
-    public boolean hasDeadlineConstraint() {
-        return latestRunTimeElapsedMillis != NO_LATEST_RUNTIME;
-    }
-
-    public boolean hasIdleConstraint() {
-        return task.isRequireDeviceIdle();
-    }
-
-    public long getEarliestRunTime() {
-        return earliestRunTimeElapsedMillis;
-    }
-
-    public long getLatestRunTimeElapsed() {
-        return latestRunTimeElapsedMillis;
-    }
-
-    public boolean isPersisted() {
-        return persisted;
-    }
-    /**
-     * @return Whether or not this task is ready to run, based on its requirements.
-     */
-    public synchronized boolean isReady() {
-        return (!hasChargingConstraint() || chargingConstraintSatisfied.get())
-                && (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get())
-                && (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get())
-                && (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get())
-                && (!hasIdleConstraint() || idleConstraintSatisfied.get())
-                // Also ready if the deadline has expired - special case.
-                || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get());
-    }
-
-    /*@Override
-    public int hashCode() {
-        int result = getServiceComponent().hashCode();
-        result = 31 * result + task.getId();
-        result = 31 * result + uId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof TaskStatus)) return false;
-
-        TaskStatus that = (TaskStatus) o;
-        return ((task.getId() == that.task.getId())
-                && (uId == that.uId)
-                && (getServiceComponent().equals(that.getServiceComponent())));
-    }*/
-
-    public boolean matches(int uid, int taskId) {
-        return this.task.getId() == taskId && this.uId == uid;
-    }
-
-    @Override
-    public String toString() {
-        return String.valueOf(hashCode()).substring(0, 3) + ".."
-                + ":[" + task.getService().getPackageName() + ",tId=" + task.getId()
-                + ",R=(" + earliestRunTimeElapsedMillis + "," + latestRunTimeElapsedMillis + ")"
-                + ",N=" + task.getNetworkCapabilities() + ",C=" + task.isRequireCharging()
-                + ",I=" + task.isRequireDeviceIdle() + ",F=" + numFailures
-                + (isReady() ? "(READY)" : "")
-                + "]";
-    }
-    // Dumpsys infrastructure
-    public void dump(PrintWriter pw, String prefix) {
-        pw.println(this.toString());
-    }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2aa1220..54be537 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -65,6 +65,7 @@
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
+import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaRouterService;
@@ -83,7 +84,6 @@
 import com.android.server.search.SearchManagerService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.storage.DeviceStorageMonitorService;
-import com.android.server.task.TaskManagerService;
 import com.android.server.trust.TrustManagerService;
 import com.android.server.tv.TvInputManagerService;
 import com.android.server.twilight.TwilightService;
@@ -131,8 +131,8 @@
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String ETHERNET_SERVICE_CLASS =
             "com.android.server.ethernet.EthernetService";
-    private static final String TASK_SERVICE_CLASS =
-            "com.android.server.task.TaskManagerService";
+    private static final String JOB_SCHEDULER_SERVICE_CLASS =
+            "com.android.server.job.JobSchedulerService";
 
     private final int mFactoryTestMode;
     private Timer mProfilerSnapshotTimer;
@@ -349,6 +349,7 @@
         boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
         boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
         boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
+        boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
 
         try {
             Slog.i(TAG, "Telephony Registry");
@@ -461,7 +462,7 @@
             // Skip Bluetooth if we have an emulator kernel
             // TODO: Use a more reliable check to see if this product should
             // support Bluetooth - see bug 988521
-            if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
+            if (isEmulator) {
                 Slog.i(TAG, "No Bluetooh Service (emulator)");
             } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
@@ -662,10 +663,17 @@
                     reportWtf("starting Wi-Fi Scanning Service", e);
                 }
 
-                try {
-                    mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
-                } catch (Throwable e) {
-                    reportWtf("starting Ethernet Service", e);
+                if (!isEmulator) {
+                    try {
+                        mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
+                    } catch (Throwable e) {
+                        reportWtf("starting Ethernet Service", e);
+                    }
+                } else {
+                    // Don't start the Ethernet service on the emulator because
+                    // it interferes with qemu's SLIRP emulation, which uses
+                    // IPv4 over eth0. http://b/15341003 .
+                    Slog.i(TAG, "Not starting Ethernet service (emulator)");
                 }
 
                 try {
@@ -832,7 +840,7 @@
 
             mSystemServiceManager.startService(UiModeManagerService.class);
 
-            mSystemServiceManager.startService(TaskManagerService.class);
+            mSystemServiceManager.startService(JobSchedulerService.class);
 
             if (!disableNonCoreServices) {
                 try {
diff --git a/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java b/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java
index e7f9ca0..7a7fa07 100644
--- a/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java
@@ -3,18 +3,19 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.app.task.Task;
-import android.app.task.Task.Builder;
+import android.app.job.JobInfo;
+import android.app.job.JobInfo.Builder;
 import android.os.PersistableBundle;
 import android.test.AndroidTestCase;
 import android.test.RenamingDelegatingContext;
 import android.util.Log;
 
-import com.android.server.task.controllers.TaskStatus;
+import com.android.server.job.JobMapReadFinishedListener;
+import com.android.server.job.JobStore;
+import com.android.server.job.controllers.JobStatus;
 
 import java.util.List;
 
-import static com.android.server.task.TaskStore.initAndGet;
 /**
  * Test reading and writing correctly from file.
  */
@@ -26,12 +27,12 @@
     private ComponentName mComponent;
     private static final long IO_WAIT = 600L;
 
-    TaskStore mTaskStoreUnderTest;
+    JobStore mTaskStoreUnderTest;
     Context mTestContext;
-    TaskMapReadFinishedListener mTaskMapReadFinishedListenerStub =
-            new TaskMapReadFinishedListener() {
+    JobMapReadFinishedListener mTaskMapReadFinishedListenerStub =
+            new JobMapReadFinishedListener() {
         @Override
-        public void onTaskMapReadFinished(List<TaskStatus> tasks) {
+        public void onJobMapReadFinished(List<JobStatus> tasks) {
             // do nothing.
         }
     };
@@ -40,7 +41,7 @@
     public void setUp() throws Exception {
         mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX);
         Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'");
-        mTaskStoreUnderTest = TaskStore.initAndGetForTesting(mTestContext,
+        mTaskStoreUnderTest = JobStore.initAndGetForTesting(mTestContext,
                 mTestContext.getFilesDir(), mTaskMapReadFinishedListenerStub);
         mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName());
     }
@@ -56,23 +57,23 @@
         long runFromMillis = 2000L; // 2s
         long initialBackoff = 10000L; // 10s
 
-        final Task task = new Builder(taskId, mComponent)
+        final JobInfo task = new Builder(taskId, mComponent)
                 .setRequiresCharging(true)
-                .setRequiredNetworkCapabilities(Task.NetworkType.ANY)
-                .setBackoffCriteria(initialBackoff, Task.BackoffPolicy.EXPONENTIAL)
+                .setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY)
+                .setBackoffCriteria(initialBackoff, JobInfo.BackoffPolicy.EXPONENTIAL)
                 .setOverrideDeadline(runByMillis)
                 .setMinimumLatency(runFromMillis)
                 .build();
-        final TaskStatus ts = new TaskStatus(task, SOME_UID, true /* persisted */);
+        final JobStatus ts = new JobStatus(task, SOME_UID, true /* persisted */);
         mTaskStoreUnderTest.add(ts);
         Thread.sleep(IO_WAIT);
         // Manually load tasks from xml file.
-        mTaskStoreUnderTest.readTaskMapFromDisk(new TaskMapReadFinishedListener() {
+        mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
             @Override
-            public void onTaskMapReadFinished(List<TaskStatus> tasks) {
+            public void onJobMapReadFinished(List<JobStatus> tasks) {
                 assertEquals("Didn't get expected number of persisted tasks.", 1, tasks.size());
-                TaskStatus loadedTaskStatus = tasks.get(0);
-                assertTasksEqual(task, loadedTaskStatus.getTask());
+                JobStatus loadedTaskStatus = tasks.get(0);
+                assertTasksEqual(task, loadedTaskStatus.getJob());
                 assertEquals("Different uids.", SOME_UID, tasks.get(0).getUid());
                 compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                         ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
@@ -84,30 +85,30 @@
     }
 
     public void testWritingTwoFilesToDisk() throws Exception {
-        final Task task1 = new Builder(8, mComponent)
+        final JobInfo task1 = new Builder(8, mComponent)
                 .setRequiresDeviceIdle(true)
                 .setPeriodic(10000L)
                 .setRequiresCharging(true)
                 .build();
-        final Task task2 = new Builder(12, mComponent)
+        final JobInfo task2 = new Builder(12, mComponent)
                 .setMinimumLatency(5000L)
-                .setBackoffCriteria(15000L, Task.BackoffPolicy.LINEAR)
+                .setBackoffCriteria(15000L, JobInfo.BackoffPolicy.LINEAR)
                 .setOverrideDeadline(30000L)
-                .setRequiredNetworkCapabilities(Task.NetworkType.UNMETERED)
+                .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
                 .build();
-        final TaskStatus taskStatus1 = new TaskStatus(task1, SOME_UID, true /* persisted */);
-        final TaskStatus taskStatus2 = new TaskStatus(task2, SOME_UID, true /* persisted */);
+        final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID, true /* persisted */);
+        final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID, true /* persisted */);
         mTaskStoreUnderTest.add(taskStatus1);
         mTaskStoreUnderTest.add(taskStatus2);
         Thread.sleep(IO_WAIT);
-        mTaskStoreUnderTest.readTaskMapFromDisk(new TaskMapReadFinishedListener() {
+        mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
             @Override
-            public void onTaskMapReadFinished(List<TaskStatus> tasks) {
+            public void onJobMapReadFinished(List<JobStatus> tasks) {
                 assertEquals("Incorrect # of persisted tasks.", 2, tasks.size());
-                TaskStatus loaded1 = tasks.get(0);
-                TaskStatus loaded2 = tasks.get(1);
-                assertTasksEqual(task1, loaded1.getTask());
-                assertTasksEqual(task2, loaded2.getTask());
+                JobStatus loaded1 = tasks.get(0);
+                JobStatus loaded2 = tasks.get(1);
+                assertTasksEqual(task1, loaded1.getJob());
+                assertTasksEqual(task2, loaded2.getJob());
 
                 // Check that the loaded task has the correct runtimes.
                 compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
@@ -124,7 +125,7 @@
     }
 
     public void testWritingTaskWithExtras() throws Exception {
-        Task.Builder b = new Builder(8, mComponent)
+        JobInfo.Builder b = new Builder(8, mComponent)
                 .setRequiresDeviceIdle(true)
                 .setPeriodic(10000L)
                 .setRequiresCharging(true);
@@ -134,17 +135,17 @@
         extras.putString("hi", "there");
         extras.putInt("into", 3);
         b.setExtras(extras);
-        final Task task = b.build();
-        TaskStatus taskStatus = new TaskStatus(task, SOME_UID, true /* persisted */);
+        final JobInfo task = b.build();
+        JobStatus taskStatus = new JobStatus(task, SOME_UID, true /* persisted */);
 
         mTaskStoreUnderTest.add(taskStatus);
         Thread.sleep(IO_WAIT);
-        mTaskStoreUnderTest.readTaskMapFromDisk(new TaskMapReadFinishedListener() {
+        mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
             @Override
-            public void onTaskMapReadFinished(List<TaskStatus> tasks) {
+            public void onJobMapReadFinished(List<JobStatus> tasks) {
                 assertEquals("Incorrect # of persisted tasks.", 1, tasks.size());
-                TaskStatus loaded = tasks.get(0);
-                assertTasksEqual(task, loaded.getTask());
+                JobStatus loaded = tasks.get(0);
+                assertTasksEqual(task, loaded.getJob());
             }
         });
 
@@ -153,7 +154,7 @@
     /**
      * Helper function to throw an error if the provided task and TaskStatus objects are not equal.
      */
-    private void assertTasksEqual(Task first, Task second) {
+    private void assertTasksEqual(JobInfo first, JobInfo second) {
         assertEquals("Different task ids.", first.getId(), second.getId());
         assertEquals("Different components.", first.getService(), second.getService());
         assertEquals("Different periodic status.", first.isPeriodic(), second.isPeriodic());
@@ -168,11 +169,11 @@
         assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
                 second.isRequireDeviceIdle());
         assertEquals("Invalid unmetered constraint.",
-                first.getNetworkCapabilities() == Task.NetworkType.UNMETERED,
-                second.getNetworkCapabilities() == Task.NetworkType.UNMETERED);
+                first.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED,
+                second.getNetworkCapabilities() == JobInfo.NetworkType.UNMETERED);
         assertEquals("Invalid connectivity constraint.",
-                first.getNetworkCapabilities() == Task.NetworkType.ANY,
-                second.getNetworkCapabilities() == Task.NetworkType.ANY);
+                first.getNetworkCapabilities() == JobInfo.NetworkType.ANY,
+                second.getNetworkCapabilities() == JobInfo.NetworkType.ANY);
         assertEquals("Invalid deadline constraint.",
                 first.hasLateConstraint(),
                 second.hasLateConstraint());
diff --git a/services/tests/servicestests/src/com/android/server/task/controllers/BatteryControllerTest.java b/services/tests/servicestests/src/com/android/server/task/controllers/BatteryControllerTest.java
deleted file mode 100644
index 6617a05..0000000
--- a/services/tests/servicestests/src/com/android/server/task/controllers/BatteryControllerTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.task.controllers;
-
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.test.AndroidTestCase;
-
-import com.android.server.task.StateChangedListener;
-
-import static com.android.server.task.controllers.BatteryController.getForTesting;
-
-import static org.mockito.Mockito.*;
-
-/**
- *
- */
-public class BatteryControllerTest extends AndroidTestCase {
-    BatteryController mBatteryControllerUnderTest;
-
-    StateChangedListener mStateChangedListenerStub = new StateChangedListener() {
-        @Override
-        public void onControllerStateChanged() {
-
-        }
-
-        @Override
-        public void onRunTaskNow(TaskStatus taskStatus) {
-
-        }
-    };
-    BatteryController.ChargingTracker mTrackerUnderTest;
-
-    public void setUp() throws Exception {
-        mBatteryControllerUnderTest = getForTesting(mStateChangedListenerStub, getTestContext());
-        mTrackerUnderTest = mBatteryControllerUnderTest.getTracker();
-    }
-
-    public void testSendBatteryChargingIntent() throws Exception {
-        Intent batteryConnectedIntent = new Intent(Intent.ACTION_POWER_CONNECTED)
-                .setComponent(new ComponentName(getContext(), mTrackerUnderTest.getClass()));
-        Intent batteryHealthyIntent = new Intent(Intent.ACTION_BATTERY_OKAY)
-                .setComponent(new ComponentName(getContext(), mTrackerUnderTest.getClass()));
-
-        mTrackerUnderTest.onReceiveInternal(batteryConnectedIntent);
-        mTrackerUnderTest.onReceiveInternal(batteryHealthyIntent);
-
-        assertTrue(mTrackerUnderTest.isOnStablePower());
-    }
-
-}
\ No newline at end of file
diff --git a/tests/JobSchedulerTestApp/AndroidManifest.xml b/tests/JobSchedulerTestApp/AndroidManifest.xml
index 7431737..9654197 100644
--- a/tests/JobSchedulerTestApp/AndroidManifest.xml
+++ b/tests/JobSchedulerTestApp/AndroidManifest.xml
@@ -25,6 +25,7 @@
 
         <service
             android:name=".service.TestJobService"
+            android:permission="android.permission.BIND_JOB_SERVICE"
             android:exported="true"/>
     </application>
 
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
index 393c594..15050ef 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
@@ -17,8 +17,8 @@
 package com.android.demo.jobSchedulerApp;
 
 import android.app.Activity;
-import android.app.task.Task;
-import android.app.task.TaskParams;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -80,10 +80,10 @@
     RadioButton mWiFiConnectivityRadioButton;
     RadioButton mAnyConnectivityRadioButton;
     ComponentName mServiceComponent;
-    /** Service object to interact scheduled tasks. */
+    /** Service object to interact scheduled jobs. */
     TestJobService mTestService;
 
-    private static int kTaskId = 0;
+    private static int kJobId = 0;
 
     Handler mHandler = new Handler(/* default looper */) {
         @Override
@@ -112,7 +112,7 @@
     }
 
     /**
-     * UI onclick listener to schedule a task. What this task is is defined in
+     * UI onclick listener to schedule a job. What this job is is defined in
      * TestJobService#scheduleJob()
      */
     public void scheduleJob(View v) {
@@ -120,7 +120,7 @@
             return;
         }
 
-        Task.Builder builder = new Task.Builder(kTaskId++, mServiceComponent);
+        JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent);
 
         String delay = mDelayEditText.getText().toString();
         if (delay != null && !TextUtils.isEmpty(delay)) {
@@ -133,9 +133,9 @@
         boolean requiresUnmetered = mWiFiConnectivityRadioButton.isSelected();
         boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isSelected();
         if (requiresUnmetered) {
-            builder.setRequiredNetworkCapabilities(Task.NetworkType.UNMETERED);
+            builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED);
         } else if (requiresAnyConnectivity) {
-            builder.setRequiredNetworkCapabilities(Task.NetworkType.ANY);
+            builder.setRequiredNetworkCapabilities(JobInfo.NetworkType.ANY);
         }
 
         mTestService.scheduleJob(builder.build());
@@ -143,24 +143,24 @@
     }
 
     /**
-     * UI onclick listener to call taskFinished() in our service.
+     * UI onclick listener to call jobFinished() in our service.
      */
     public void finishJob(View v) {
         if (!ensureTestService()) {
             return;
         }
-        mTestService.callTaskFinished();
+        mTestService.callJobFinished();
         mParamsTextView.setText("");
     }
 
-    public void onReceivedStartTask(TaskParams params) {
+    public void onReceivedStartJob(JobParameters params) {
         mShowStartView.setBackgroundColor(startJobColor);
         Message m = Message.obtain(mHandler, MSG_UNCOLOUR_START);
         mHandler.sendMessageDelayed(m, 1000L); // uncolour in 1 second.
-        mParamsTextView.setText("Executing: " + params.getTaskId() + " " + params.getExtras());
+        mParamsTextView.setText("Executing: " + params.getJobId() + " " + params.getExtras());
     }
 
-    public void onReceivedStopTask() {
+    public void onReceivedStopJob() {
         mShowStopView.setBackgroundColor(stopJobColor);
         Message m = Message.obtain(mHandler, MSG_UNCOLOUR_STOP);
         mHandler.sendMessageDelayed(m, 2000L); // uncolour in 1 second.
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
index 7dd3cf1..bf8e887 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java
@@ -16,28 +16,20 @@
 
 package com.android.demo.jobSchedulerApp.service;
 
-import android.app.Service;
-import android.app.task.Task;
-import android.app.task.TaskManager;
-import android.app.task.TaskParams;
-import android.app.task.TaskService;
-import android.content.ComponentName;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.app.job.JobParameters;
+import android.app.job.JobService;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
-import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.demo.jobSchedulerApp.MainActivity;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.LinkedList;
-import java.util.List;
 
 
 /**
@@ -52,7 +44,7 @@
  * lifecycle of our and provide a handle to said SyncAdapter to the OS on
  * request.
  */
-public class TestJobService extends TaskService {
+public class TestJobService extends JobService {
     private static final String TAG = "SyncService";
 
     @Override
@@ -82,44 +74,44 @@
     }
 
     @Override
-    public boolean onStartTask(TaskParams params) {
-        taskParamsMap.add(params);
+    public boolean onStartJob(JobParameters params) {
+        jobParamsMap.add(params);
         if (mActivity != null) {
-            mActivity.onReceivedStartTask(params);
+            mActivity.onReceivedStartJob(params);
         }
-        Log.i(TAG, "on start task: " + params.getTaskId());
+        Log.i(TAG, "on start job: " + params.getJobId());
         return true;
     }
 
     @Override
-    public boolean onStopTask(TaskParams params) {
-        taskParamsMap.remove(params);
-        mActivity.onReceivedStopTask();
-        Log.i(TAG, "on stop task: " + params.getTaskId());
+    public boolean onStopJob(JobParameters params) {
+        jobParamsMap.remove(params);
+        mActivity.onReceivedStopJob();
+        Log.i(TAG, "on stop job: " + params.getJobId());
         return true;
     }
 
     MainActivity mActivity;
-    private final LinkedList<TaskParams> taskParamsMap = new LinkedList<TaskParams>();
+    private final LinkedList<JobParameters> jobParamsMap = new LinkedList<JobParameters>();
 
     public void setUiCallback(MainActivity activity) {
         mActivity = activity;
     }
 
     /** Send job to the JobScheduler. */
-    public void scheduleJob(Task t) {
+    public void scheduleJob(JobInfo t) {
         Log.d(TAG, "Scheduling job");
-        TaskManager tm =
-                (TaskManager) getSystemService(Context.TASK_SERVICE);
+        JobScheduler tm =
+                (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
         tm.schedule(t);
     }
 
-    public boolean callTaskFinished() {
-        TaskParams params = taskParamsMap.poll();
+    public boolean callJobFinished() {
+        JobParameters params = jobParamsMap.poll();
         if (params == null) {
             return false;
         } else {
-            taskFinished(params, false);
+            jobFinished(params, false);
             return true;
         }
     }
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index af22f44..36102f1 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -151,7 +151,7 @@
     @Override
     public View inflate(int resource, ViewGroup root) {
         Context context = getContext();
-        if (context instanceof ContextThemeWrapper) {
+        while (context instanceof ContextThemeWrapper) {
             context = ((ContextThemeWrapper) context).getBaseContext();
         }
         if (context instanceof BridgeContext) {
@@ -217,7 +217,7 @@
 
     private void setupViewInContext(View view, AttributeSet attrs) {
         Context context = getContext();
-        if (context instanceof ContextThemeWrapper) {
+        while (context instanceof ContextThemeWrapper) {
             context = ((ContextThemeWrapper) context).getBaseContext();
         }
         if (context instanceof BridgeContext) {
diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
index 0dddf3d..dafc96b 100644
--- a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
@@ -48,7 +48,7 @@
             AttributeSet attrs) {
         if (menuItem instanceof BridgeMenuItemImpl) {
             Context context = thisInflater.getContext();
-            if (context instanceof ContextThemeWrapper) {
+            while (context instanceof ContextThemeWrapper) {
                 context = ((ContextThemeWrapper) context).getBaseContext();
             }
             if (context instanceof BridgeContext) {
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
index cdb839a..8d1d0c1 100644
--- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
@@ -42,7 +42,7 @@
             CharSequence title, int showAsAction) {
         super(menu, group, id, categoryOrder, ordering, title, showAsAction);
         Context context = menu.getContext();
-        if (context instanceof ContextThemeWrapper) {
+        while (context instanceof ContextThemeWrapper) {
             context = ((ContextThemeWrapper) context).getBaseContext();
         }
         if (context instanceof BridgeContext) {
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 6e0a300..32625ae 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -119,8 +119,8 @@
 
 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
+were added in the Dalvik VM but are not a part of the Desktop VM. The existing classes are
+modified to update all references to these non-desktop classes. An alternate implementation of
 these (com.android.tools.layoutlib.java.*) is injected.
 
 RenameClassAdapter and RefactorClassAdapter both inherit from AbstractClassAdapter which changes the
@@ -130,11 +130,15 @@
 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.
 
+ReplaceMethodCallsAdapter replaces calls to certain methods. Currently, it only rewrites calls to
+java.lang.System.arraycopy([CI[CII)V, which is not part of the Desktop VM to call the more general
+method java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V.
+
 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
+RefactorClassAdapter -> [ReplaceMethodCallsAdapter] -> ClassWriter
 
 - Method stubs
 --------------
@@ -169,7 +173,7 @@
 - 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
+- Charsets, IntegralToString and UnsafeByteSequence are not part of the Desktop 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
@@ -209,7 +213,7 @@
 
 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.
+not present in the Desktop VM. An implementation for these classes is also injected.
 
 
 5- Method erasure based on return type
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 3e75c9e..8373e30 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
@@ -32,6 +32,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -63,7 +64,8 @@
     private final Set<String> mExcludedClasses;
     /** Glob patterns of files to keep as is. */
     private final String[] mIncludeFileGlobs;
-    /** Copy these files into the output as is. */
+    /** Internal names of classes that contain method calls that need to be rewritten. */
+    private final Set<String> mReplaceMethodCallClasses = new HashSet<String>();
 
     /**
      * Creates a new analyzer.
@@ -109,6 +111,7 @@
             mGen.setKeep(found);
             mGen.setDeps(deps);
             mGen.setCopyFiles(filesFound);
+            mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses);
         }
     }
 
@@ -118,7 +121,7 @@
      *
      * @param classes The map of class name => ASM ClassReader. Class names are
      *                in the form "android.view.View".
-     * @param fileFound The map of file name => InputStream. The file name is
+     * @param filesFound The map of file name => InputStream. The file name is
      *                  in the form "android/data/dataFile".
      */
     void parseZip(List<String> jarPathList, Map<String, ClassReader> classes,
@@ -143,8 +146,8 @@
                     String className = classReaderToClassName(cr);
                     classes.put(className, cr);
                 } else {
-                    for (int i = 0; i < includeFilePatterns.length; ++i) {
-                        if (includeFilePatterns[i].matcher(entry.getName()).matches()) {
+                    for (Pattern includeFilePattern : includeFilePatterns) {
+                        if (includeFilePattern.matcher(entry.getName()).matches()) {
                             filesFound.put(entry.getName(), zip.getInputStream(entry));
                             break;
                         }
@@ -321,6 +324,7 @@
                 deps, new_deps);
 
         for (ClassReader cr : inOutKeepClasses.values()) {
+            visitor.setClassName(cr.getClassName());
             cr.accept(visitor, 0 /* flags */);
         }
 
@@ -367,6 +371,8 @@
         /** New classes to keep as-is found by this visitor. */
         private final Map<String, ClassReader> mOutKeep;
 
+        private String mClassName;
+
         /**
          * Creates a new visitor that will find all the dependencies for the visited class.
          * Types which are already in the zipClasses, keepClasses or inDeps are not marked.
@@ -390,6 +396,10 @@
             mOutDeps = outDeps;
         }
 
+        private void setClassName(String className) {
+            mClassName = className;
+        }
+
         /**
          * Considers the given class name as a dependency.
          * If it does, add to the mOutDeps map.
@@ -429,7 +439,7 @@
             // - android classes are added to dependencies
             // - non-android classes are added to the list of classes to keep as-is (they don't need
             //   to be stubbed).
-            if (className.indexOf("android") >= 0) {  // TODO make configurable
+            if (className.contains("android")) {  // TODO make configurable
                 mOutDeps.put(className, cr);
             } else {
                 mOutKeep.put(className, cr);
@@ -594,7 +604,7 @@
             // type and exceptions do not use generic types.
             considerSignature(signature);
 
-            return new MyMethodVisitor();
+            return new MyMethodVisitor(mClassName);
         }
 
         @Override
@@ -614,8 +624,11 @@
 
         private class MyMethodVisitor extends MethodVisitor {
 
-            public MyMethodVisitor() {
+            private String mOwnerClass;
+
+            public MyMethodVisitor(String ownerClass) {
                 super(Opcodes.ASM4);
+                mOwnerClass = ownerClass;
             }
 
 
@@ -709,6 +722,13 @@
                 considerName(owner);
                 // desc is the method's descriptor (see Type).
                 considerDesc(desc);
+
+
+                // Check if method is java.lang.System.arrayCopy([CI[CII)V
+                if (owner.equals("java/lang/System") && name.equals("arraycopy")
+                        && desc.equals("([CI[CII)V")) {
+                    mReplaceMethodCallClasses.add(mOwnerClass);
+                }
             }
 
             // instruction multianewarray, whatever that is
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 207d8ae..c96a143 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -21,7 +21,6 @@
 import org.objectweb.asm.ClassWriter;
 
 import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -55,6 +54,8 @@
     private Map<String, ClassReader> mDeps;
     /** All files that are to be copied as-is. */
     private Map<String, InputStream> mCopyFiles;
+    /** All classes where certain method calls need to be rewritten. */
+    private Set<String> mReplaceMethodCallsClasses;
     /** Counter of number of classes renamed during transform. */
     private int mRenameCount;
     /** FQCN Names of the classes to rename: map old-FQCN => new-FQCN */
@@ -133,7 +134,7 @@
             assert i + 1 < n;
             String oldFqcn = binaryToInternalClassName(refactorClasses[i]);
             String newFqcn = binaryToInternalClassName(refactorClasses[i + 1]);
-            mRefactorClasses.put(oldFqcn, newFqcn);;
+            mRefactorClasses.put(oldFqcn, newFqcn);
         }
 
         // create the map of renamed class -> return type of method to delete.
@@ -203,23 +204,12 @@
         mCopyFiles = copyFiles;
     }
 
-    /** Gets the map of classes to output as-is, except if they have native methods */
-    public Map<String, ClassReader> getKeep() {
-        return mKeep;
-    }
-
-    /** Gets the map of dependencies that must be completely stubbed */
-    public Map<String, ClassReader> getDeps() {
-        return mDeps;
-    }
-
-    /** Gets the map of files to output as-is. */
-    public Map<String, InputStream> getCopyFiles() {
-        return mCopyFiles;
+    public void setRewriteMethodCallClasses(Set<String> rewriteMethodCallClasses) {
+        mReplaceMethodCallsClasses = rewriteMethodCallClasses;
     }
 
     /** Generates the final JAR */
-    public void generate() throws FileNotFoundException, IOException {
+    public void generate() throws IOException {
         TreeMap<String, byte[]> all = new TreeMap<String, byte[]>();
 
         for (Class<?> clazz : mInjectClasses) {
@@ -329,14 +319,14 @@
 
         String newName = transformName(className);
         // transformName returns its input argument if there's no need to rename the class
-        if (newName != className) {
+        if (!newName.equals(className)) {
             mRenameCount++;
             // This class is being renamed, so remove it from the list of classes not renamed.
             mClassesNotRenamed.remove(className);
         }
 
         mLog.debug("Transform %s%s%s%s", className,
-                newName == className ? "" : " (renamed to " + newName + ")",
+                newName.equals(className) ? "" : " (renamed to " + newName + ")",
                 hasNativeMethods ? " -- has natives" : "",
                 stubNativesOnly ? " -- stub natives only" : "");
 
@@ -344,8 +334,14 @@
         // original class reader.
         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
 
-        ClassVisitor cv = new RefactorClassAdapter(cw, mRefactorClasses);
-        if (newName != className) {
+        ClassVisitor cv = cw;
+
+        if (mReplaceMethodCallsClasses.contains(className)) {
+            cv = new ReplaceMethodCallsAdapter(cv);
+        }
+
+        cv = new RefactorClassAdapter(cv, mRefactorClasses);
+        if (!newName.equals(className)) {
             cv = new RenameClassAdapter(cv, className, newName);
         }
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 2e952fc..ad10656 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -193,8 +193,7 @@
     private static boolean processArgs(Log log, String[] args,
             ArrayList<String> osJarPath, String[] osDestJar) {
         boolean needs_dest = true;
-        for (int i = 0; i < args.length; i++) {
-            String s = args[i];
+        for (String s : args) {
             if (s.equals("-v")) {
                 log.setVerbose(true);
             } else if (s.equals("-p")) {
@@ -212,7 +211,7 @@
                     osJarPath.add(s);
                 }
             } else {
-                log.error("Unknow argument: %s", s);
+                log.error("Unknown argument: %s", s);
                 return false;
             }
         }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
new file mode 100644
index 0000000..e57eba1
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Replaces calls to certain methods that do not exist in the Desktop VM.
+ */
+public class ReplaceMethodCallsAdapter extends ClassVisitor {
+    public ReplaceMethodCallsAdapter(ClassVisitor cv) {
+        super(Opcodes.ASM4, cv);
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+            String[] exceptions) {
+        return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
+    }
+
+    private class MyMethodVisitor extends MethodVisitor {
+
+        public MyMethodVisitor(MethodVisitor mv) {
+            super(Opcodes.ASM4, mv);
+        }
+
+        @Override
+        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+            // Check if method is java.lang.System.arrayCopy([CI[CII)V
+            if (owner.equals("java/lang/System") && name.equals("arraycopy")
+                    && desc.equals("([CI[CII)V")) {
+                desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
+            }
+            super.visitMethodInsn(opcode, owner, name, desc);
+        }
+    }
+}