Merge "TIF: fix NPE in the case a hardware TV input is not ready to use."
diff --git a/api/current.txt b/api/current.txt
index c004b15..a469b58 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -464,8 +464,8 @@
     field public static final int datePickerMode = 16843955; // 0x10104b3
     field public static final int datePickerStyle = 16843612; // 0x101035c
     field public static final int dateTextAppearance = 16843593; // 0x1010349
-    field public static final int dayOfWeekBackground = 16843924; // 0x1010494
-    field public static final int dayOfWeekTextAppearance = 16843925; // 0x1010495
+    field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
+    field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int delay = 16843212; // 0x10101cc
@@ -587,7 +587,7 @@
     field public static final int flipInterval = 16843129; // 0x1010179
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
-    field public static final int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -651,9 +651,9 @@
     field public static final int hasCode = 16842764; // 0x101000c
     field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
-    field public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
+    field public static final deprecated int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
-    field public static final int headerMonthTextAppearance = 16843926; // 0x1010496
+    field public static final deprecated int headerMonthTextAppearance = 16843926; // 0x1010496
     field public static final int headerTimeTextAppearance = 16843935; // 0x101049f
     field public static final int headerYearTextAppearance = 16843928; // 0x1010498
     field public static final int height = 16843093; // 0x1010155
@@ -1094,8 +1094,8 @@
     field public static final int selectable = 16843238; // 0x10101e6
     field public static final int selectableItemBackground = 16843534; // 0x101030e
     field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
-    field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
-    field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+    field public static final deprecated int selectedDateVerticalBar = 16843591; // 0x1010347
+    field public static final deprecated int selectedWeekBackgroundColor = 16843586; // 0x1010342
     field public static final int sessionService = 16843837; // 0x101043d
     field public static final int settingsActivity = 16843301; // 0x1010225
     field public static final int setupActivity = 16843766; // 0x10103f6
@@ -1114,8 +1114,8 @@
     field public static final int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
-    field public static final int showWeekNumber = 16843582; // 0x101033e
-    field public static final int shownWeekCount = 16843585; // 0x1010341
+    field public static final deprecated int showWeekNumber = 16843582; // 0x101033e
+    field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
     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
@@ -1352,7 +1352,7 @@
     field public static final int typeface = 16842902; // 0x1010096
     field public static final int uiOptions = 16843672; // 0x1010398
     field public static final int uncertainGestureColor = 16843382; // 0x1010276
-    field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
+    field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
     field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -1394,8 +1394,8 @@
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
-    field public static final int weekNumberColor = 16843589; // 0x1010345
-    field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
+    field public static final deprecated int weekNumberColor = 16843589; // 0x1010345
+    field public static final deprecated int weekSeparatorLineColor = 16843590; // 0x1010346
     field public static final int weightSum = 16843048; // 0x1010128
     field public static final int widgetCategory = 16843716; // 0x10103c4
     field public static final int widgetLayout = 16843243; // 0x10101eb
@@ -1454,7 +1454,7 @@
     field public static final int xlargeScreens = 16843455; // 0x10102bf
     field public static final int y = 16842925; // 0x10100ad
     field public static final int yearListItemTextAppearance = 16843929; // 0x1010499
-    field public static final int yearListSelectorColor = 16843930; // 0x101049a
+    field public static final deprecated int yearListSelectorColor = 16843930; // 0x101049a
     field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
     field public static final int zAdjustment = 16843201; // 0x10101c1
   }
@@ -5664,11 +5664,13 @@
     field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
     field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
@@ -38152,34 +38154,34 @@
     method public long getDate();
     method public int getDateTextAppearance();
     method public int getFirstDayOfWeek();
-    method public int getFocusedMonthDateColor();
+    method public deprecated int getFocusedMonthDateColor();
     method public long getMaxDate();
     method public long getMinDate();
-    method public android.graphics.drawable.Drawable getSelectedDateVerticalBar();
-    method public int getSelectedWeekBackgroundColor();
+    method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
+    method public deprecated int getSelectedWeekBackgroundColor();
     method public boolean getShowWeekNumber();
-    method public int getShownWeekCount();
-    method public int getUnfocusedMonthDateColor();
+    method public deprecated int getShownWeekCount();
+    method public deprecated int getUnfocusedMonthDateColor();
     method public int getWeekDayTextAppearance();
-    method public int getWeekNumberColor();
-    method public int getWeekSeparatorLineColor();
+    method public deprecated int getWeekNumberColor();
+    method public deprecated int getWeekSeparatorLineColor();
     method public void setDate(long);
     method public void setDate(long, boolean, boolean);
     method public void setDateTextAppearance(int);
     method public void setFirstDayOfWeek(int);
-    method public void setFocusedMonthDateColor(int);
+    method public deprecated void setFocusedMonthDateColor(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
     method public void setOnDateChangeListener(android.widget.CalendarView.OnDateChangeListener);
-    method public void setSelectedDateVerticalBar(int);
-    method public void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
-    method public void setSelectedWeekBackgroundColor(int);
+    method public deprecated void setSelectedDateVerticalBar(int);
+    method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
+    method public deprecated void setSelectedWeekBackgroundColor(int);
     method public void setShowWeekNumber(boolean);
-    method public void setShownWeekCount(int);
-    method public void setUnfocusedMonthDateColor(int);
+    method public deprecated void setShownWeekCount(int);
+    method public deprecated void setUnfocusedMonthDateColor(int);
     method public void setWeekDayTextAppearance(int);
-    method public void setWeekNumberColor(int);
-    method public void setWeekSeparatorLineColor(int);
+    method public deprecated void setWeekNumberColor(int);
+    method public deprecated void setWeekSeparatorLineColor(int);
   }
 
   public static abstract interface CalendarView.OnDateChangeListener {
@@ -39112,7 +39114,7 @@
     method public void setTouchInterceptor(android.view.View.OnTouchListener);
     method public void setTouchable(boolean);
     method public void setWidth(int);
-    method public void setWindowLayoutMode(int, int);
+    method public deprecated void setWindowLayoutMode(int, int);
     method public void showAsDropDown(android.view.View);
     method public void showAsDropDown(android.view.View, int, int);
     method public void showAsDropDown(android.view.View, int, int, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index aa20ff1..8130dee 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -536,8 +536,8 @@
     field public static final int datePickerMode = 16843955; // 0x10104b3
     field public static final int datePickerStyle = 16843612; // 0x101035c
     field public static final int dateTextAppearance = 16843593; // 0x1010349
-    field public static final int dayOfWeekBackground = 16843924; // 0x1010494
-    field public static final int dayOfWeekTextAppearance = 16843925; // 0x1010495
+    field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
+    field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int delay = 16843212; // 0x10101cc
@@ -659,7 +659,7 @@
     field public static final int flipInterval = 16843129; // 0x1010179
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
-    field public static final int focusedMonthDateColor = 16843587; // 0x1010343
+    field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -723,9 +723,9 @@
     field public static final int hasCode = 16842764; // 0x101000c
     field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
-    field public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
+    field public static final deprecated int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
-    field public static final int headerMonthTextAppearance = 16843926; // 0x1010496
+    field public static final deprecated int headerMonthTextAppearance = 16843926; // 0x1010496
     field public static final int headerTimeTextAppearance = 16843935; // 0x101049f
     field public static final int headerYearTextAppearance = 16843928; // 0x1010498
     field public static final int height = 16843093; // 0x1010155
@@ -1170,8 +1170,8 @@
     field public static final int selectable = 16843238; // 0x10101e6
     field public static final int selectableItemBackground = 16843534; // 0x101030e
     field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
-    field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
-    field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+    field public static final deprecated int selectedDateVerticalBar = 16843591; // 0x1010347
+    field public static final deprecated int selectedWeekBackgroundColor = 16843586; // 0x1010342
     field public static final int sessionService = 16843837; // 0x101043d
     field public static final int settingsActivity = 16843301; // 0x1010225
     field public static final int setupActivity = 16843766; // 0x10103f6
@@ -1190,8 +1190,8 @@
     field public static final int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
-    field public static final int showWeekNumber = 16843582; // 0x101033e
-    field public static final int shownWeekCount = 16843585; // 0x1010341
+    field public static final deprecated int showWeekNumber = 16843582; // 0x101033e
+    field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
     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
@@ -1428,7 +1428,7 @@
     field public static final int typeface = 16842902; // 0x1010096
     field public static final int uiOptions = 16843672; // 0x1010398
     field public static final int uncertainGestureColor = 16843382; // 0x1010276
-    field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
+    field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
     field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -1470,8 +1470,8 @@
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
-    field public static final int weekNumberColor = 16843589; // 0x1010345
-    field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
+    field public static final deprecated int weekNumberColor = 16843589; // 0x1010345
+    field public static final deprecated int weekSeparatorLineColor = 16843590; // 0x1010346
     field public static final int weightSum = 16843048; // 0x1010128
     field public static final int widgetCategory = 16843716; // 0x10103c4
     field public static final int widgetLayout = 16843243; // 0x10101eb
@@ -1530,7 +1530,7 @@
     field public static final int xlargeScreens = 16843455; // 0x10102bf
     field public static final int y = 16842925; // 0x10100ad
     field public static final int yearListItemTextAppearance = 16843929; // 0x1010499
-    field public static final int yearListSelectorColor = 16843930; // 0x101049a
+    field public static final deprecated int yearListSelectorColor = 16843930; // 0x101049a
     field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
     field public static final int zAdjustment = 16843201; // 0x10101c1
   }
@@ -5768,11 +5768,13 @@
     field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
     field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
@@ -40812,34 +40814,34 @@
     method public long getDate();
     method public int getDateTextAppearance();
     method public int getFirstDayOfWeek();
-    method public int getFocusedMonthDateColor();
+    method public deprecated int getFocusedMonthDateColor();
     method public long getMaxDate();
     method public long getMinDate();
-    method public android.graphics.drawable.Drawable getSelectedDateVerticalBar();
-    method public int getSelectedWeekBackgroundColor();
+    method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
+    method public deprecated int getSelectedWeekBackgroundColor();
     method public boolean getShowWeekNumber();
-    method public int getShownWeekCount();
-    method public int getUnfocusedMonthDateColor();
+    method public deprecated int getShownWeekCount();
+    method public deprecated int getUnfocusedMonthDateColor();
     method public int getWeekDayTextAppearance();
-    method public int getWeekNumberColor();
-    method public int getWeekSeparatorLineColor();
+    method public deprecated int getWeekNumberColor();
+    method public deprecated int getWeekSeparatorLineColor();
     method public void setDate(long);
     method public void setDate(long, boolean, boolean);
     method public void setDateTextAppearance(int);
     method public void setFirstDayOfWeek(int);
-    method public void setFocusedMonthDateColor(int);
+    method public deprecated void setFocusedMonthDateColor(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
     method public void setOnDateChangeListener(android.widget.CalendarView.OnDateChangeListener);
-    method public void setSelectedDateVerticalBar(int);
-    method public void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
-    method public void setSelectedWeekBackgroundColor(int);
+    method public deprecated void setSelectedDateVerticalBar(int);
+    method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
+    method public deprecated void setSelectedWeekBackgroundColor(int);
     method public void setShowWeekNumber(boolean);
-    method public void setShownWeekCount(int);
-    method public void setUnfocusedMonthDateColor(int);
+    method public deprecated void setShownWeekCount(int);
+    method public deprecated void setUnfocusedMonthDateColor(int);
     method public void setWeekDayTextAppearance(int);
-    method public void setWeekNumberColor(int);
-    method public void setWeekSeparatorLineColor(int);
+    method public deprecated void setWeekNumberColor(int);
+    method public deprecated void setWeekSeparatorLineColor(int);
   }
 
   public static abstract interface CalendarView.OnDateChangeListener {
@@ -41772,7 +41774,7 @@
     method public void setTouchInterceptor(android.view.View.OnTouchListener);
     method public void setTouchable(boolean);
     method public void setWidth(int);
-    method public void setWindowLayoutMode(int, int);
+    method public deprecated void setWindowLayoutMode(int, int);
     method public void showAsDropDown(android.view.View);
     method public void showAsDropDown(android.view.View, int, int);
     method public void showAsDropDown(android.view.View, int, int, int);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 682a468..2797bf0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -341,6 +341,18 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
 
     /**
+     * An int extra holding a minimum required version code for the device admin package. If the
+     * device admin is already installed on the device, it will only be re-downloaded from
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION} if the version of the
+     * installed package is less than this version code.
+     *
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * provisioning via an NFC bump.
+     */
+    public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE
+        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
+
+    /**
      * A String extra holding a http cookie header which should be used in the http request to the
      * url specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
@@ -411,6 +423,18 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
 
     /**
+     * An int extra holding a minimum required version code for the device initializer package.
+     * If the initializer is already installed on the device, it will only be re-downloaded from
+     * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION} if the version of
+     * the installed package is less than this version code.
+     *
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * provisioning via an NFC bump.
+     */
+    public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE
+        = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE";
+
+    /**
      * A String extra holding a http cookie header which should be used in the http request to the
      * url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c443ff3..eaad9aca 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3116,8 +3116,7 @@
             }
 
             a.info.resizeable = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_resizeableActivity,
-                    owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.MNC);
+                    R.styleable.AndroidManifestActivity_resizeableActivity, false);
             if (a.info.resizeable) {
                 // Fixed screen orientation isn't supported with resizeable activities.
                 a.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 841b09d..7d8dff3 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -464,6 +464,33 @@
         return mColors;
     }
 
+    /**
+     * Returns whether the specified state is referenced in any of the state
+     * specs contained within this ColorStateList.
+     * <p>
+     * Any reference, either positive or negative {ex. ~R.attr.state_enabled},
+     * will cause this method to return {@code true}. Wildcards are not counted
+     * as references.
+     *
+     * @param state the state to search for
+     * @return {@code true} if the state if referenced, {@code false} otherwise
+     * @hide Use only as directed. For internal use only.
+     */
+    public boolean hasState(int state) {
+        final int[][] stateSpecs = mStateSpecs;
+        final int specCount = stateSpecs.length;
+        for (int specIndex = 0; specIndex < specCount; specIndex++) {
+            final int[] states = stateSpecs[specIndex];
+            final int stateCount = states.length;
+            for (int stateIndex = 0; stateIndex < stateCount; stateIndex++) {
+                if (states[stateIndex] == state || states[stateIndex] == ~state) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     public String toString() {
         return "ColorStateList{" +
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 06862d7..74b0a1c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1516,8 +1516,14 @@
         /**
          * Build a {@link #CONTENT_LOOKUP_URI} lookup {@link Uri} using the
          * given {@link ContactsContract.Contacts#_ID} and {@link #LOOKUP_KEY}.
+         * <p>
+         * Returns null if unable to construct a valid lookup URI from the
+         * provided parameters.
          */
         public static Uri getLookupUri(long contactId, String lookupKey) {
+            if (TextUtils.isEmpty(lookupKey)) {
+                return null;
+            }
             return ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
                     lookupKey), contactId);
         }
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 1a07aee..457d6ad 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -452,9 +452,10 @@
         synchronized (mConstructorArgs) {
             Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
 
+            final Context inflaterContext = mContext;
             final AttributeSet attrs = Xml.asAttributeSet(parser);
-            Context lastContext = (Context)mConstructorArgs[0];
-            mConstructorArgs[0] = mContext;
+            Context lastContext = (Context) mConstructorArgs[0];
+            mConstructorArgs[0] = inflaterContext;
             View result = root;
 
             try {
@@ -485,10 +486,10 @@
                                 + "ViewGroup root and attachToRoot=true");
                     }
 
-                    rInflate(parser, root, attrs, false, false);
+                    rInflate(parser, root, inflaterContext, attrs, false);
                 } else {
                     // Temp is the root view that was found in the xml
-                    final View temp = createViewFromTag(root, name, attrs, false);
+                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);
 
                     ViewGroup.LayoutParams params = null;
 
@@ -509,8 +510,10 @@
                     if (DEBUG) {
                         System.out.println("-----> start inflating children");
                     }
-                    // Inflate all children under temp
-                    rInflate(parser, temp, attrs, true, true);
+
+                    // Inflate all children under temp against its context.
+                    rInflateChildren(parser, temp, attrs, true);
+
                     if (DEBUG) {
                         System.out.println("-----> done inflating children");
                     }
@@ -692,59 +695,68 @@
     }
 
     /**
+     * Convenience method for calling through to the five-arg createViewFromTag
+     * method. This method passes {@code false} for the {@code ignoreThemeAttr}
+     * argument and should be used for everything except {@code &gt;include>}
+     * tag parsing.
+     */
+    private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
+        return createViewFromTag(parent, name, context, attrs, false);
+    }
+
+    /**
      * Creates a view from a tag name using the supplied attribute set.
      * <p>
-     * If {@code inheritContext} is true and the parent is non-null, the view
-     * will be inflated in parent view's context. If the view specifies a
-     * &lt;theme&gt; attribute, the inflation context will be wrapped with the
-     * specified theme.
-     * <p>
-     * Note: Default visibility so the BridgeInflater can override it.
+     * <strong>Note:</strong> Default visibility so the BridgeInflater can
+     * override it.
+     *
+     * @param parent the parent view, used to inflate layout params
+     * @param name the name of the XML tag used to define the view
+     * @param context the inflation context for the view, typically the
+     *                {@code parent} or base layout inflater context
+     * @param attrs the attribute set for the XML tag used to define the view
+     * @param ignoreThemeAttr {@code true} to ignore the {@code android:theme}
+     *                        attribute (if set) for the view being inflated,
+     *                        {@code false} otherwise
      */
-    View createViewFromTag(View parent, String name, AttributeSet attrs, boolean inheritContext) {
+    View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
+            boolean ignoreThemeAttr) {
         if (name.equals("view")) {
             name = attrs.getAttributeValue(null, "class");
         }
 
-        Context viewContext;
-        if (parent != null && inheritContext) {
-            viewContext = parent.getContext();
-        } else {
-            viewContext = mContext;
+        // Apply a theme wrapper, if allowed and one is specified.
+        if (!ignoreThemeAttr) {
+            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
+            final int themeResId = ta.getResourceId(0, 0);
+            if (themeResId != 0) {
+                context = new ContextThemeWrapper(context, themeResId);
+            }
+            ta.recycle();
         }
 
-        // Apply a theme wrapper, if requested.
-        final TypedArray ta = viewContext.obtainStyledAttributes(attrs, ATTRS_THEME);
-        final int themeResId = ta.getResourceId(0, 0);
-        if (themeResId != 0) {
-            viewContext = new ContextThemeWrapper(viewContext, themeResId);
-        }
-        ta.recycle();
-
         if (name.equals(TAG_1995)) {
             // Let's party like it's 1995!
-            return new BlinkLayout(viewContext, attrs);
+            return new BlinkLayout(context, attrs);
         }
 
-        if (DEBUG) System.out.println("******** Creating view: " + name);
-
         try {
             View view;
             if (mFactory2 != null) {
-                view = mFactory2.onCreateView(parent, name, viewContext, attrs);
+                view = mFactory2.onCreateView(parent, name, context, attrs);
             } else if (mFactory != null) {
-                view = mFactory.onCreateView(name, viewContext, attrs);
+                view = mFactory.onCreateView(name, context, attrs);
             } else {
                 view = null;
             }
 
             if (view == null && mPrivateFactory != null) {
-                view = mPrivateFactory.onCreateView(parent, name, viewContext, attrs);
+                view = mPrivateFactory.onCreateView(parent, name, context, attrs);
             }
 
             if (view == null) {
                 final Object lastContext = mConstructorArgs[0];
-                mConstructorArgs[0] = viewContext;
+                mConstructorArgs[0] = context;
                 try {
                     if (-1 == name.indexOf('.')) {
                         view = onCreateView(parent, name, attrs);
@@ -756,20 +768,18 @@
                 }
             }
 
-            if (DEBUG) System.out.println("Created view is: " + view);
             return view;
-
         } catch (InflateException e) {
             throw e;
 
         } catch (ClassNotFoundException e) {
-            InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(attrs.getPositionDescription()
                     + ": Error inflating class " + name);
             ie.initCause(e);
             throw ie;
 
         } catch (Exception e) {
-            InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(attrs.getPositionDescription()
                     + ": Error inflating class " + name);
             ie.initCause(e);
             throw ie;
@@ -777,16 +787,26 @@
     }
 
     /**
+     * Recursive method used to inflate internal (non-root) children. This
+     * method calls through to {@link #rInflate} using the parent context as
+     * the inflation context.
+     * <strong>Note:</strong> Default visibility so the BridgeInflater can
+     * call it.
+     */
+    final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
+            boolean finishInflate) throws XmlPullParserException, IOException {
+        rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
+    }
+
+    /**
      * Recursive method used to descend down the xml hierarchy and instantiate
      * views, instantiate their children, and then call onFinishInflate().
-     *
-     * @param inheritContext Whether the root view should be inflated in its
-     *            parent's context. This should be true when called inflating
-     *            child views recursively, or false otherwise.
+     * <p>
+     * <strong>Note:</strong> Default visibility so the BridgeInflater can
+     * override it.
      */
-    void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
-            boolean finishInflate, boolean inheritContext) throws XmlPullParserException,
-            IOException {
+    void rInflate(XmlPullParser parser, View parent, Context context,
+            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
 
         final int depth = parser.getDepth();
         int type;
@@ -808,19 +828,21 @@
                 if (parser.getDepth() == 0) {
                     throw new InflateException("<include /> cannot be the root element");
                 }
-                parseInclude(parser, parent, attrs, inheritContext);
+                parseInclude(parser, context, parent, attrs);
             } else if (TAG_MERGE.equals(name)) {
                 throw new InflateException("<merge /> must be the root element");
             } else {
-                final View view = createViewFromTag(parent, name, attrs, inheritContext);
+                final View view = createViewFromTag(parent, name, context, attrs);
                 final ViewGroup viewGroup = (ViewGroup) parent;
                 final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
-                rInflate(parser, view, attrs, true, true);
+                rInflateChildren(parser, view, attrs, true);
                 viewGroup.addView(view, params);
             }
         }
 
-        if (finishInflate) parent.onFinishInflate();
+        if (finishInflate) {
+            parent.onFinishInflate();
+        }
     }
 
     /**
@@ -829,13 +851,9 @@
      */
     private void parseRequestFocus(XmlPullParser parser, View view)
             throws XmlPullParserException, IOException {
-        int type;
         view.requestFocus();
-        final int currentDepth = parser.getDepth();
-        while (((type = parser.next()) != XmlPullParser.END_TAG ||
-                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
-            // Empty
-        }
+
+        consumeChildElements(parser);
     }
 
     /**
@@ -844,33 +862,29 @@
      */
     private void parseViewTag(XmlPullParser parser, View view, AttributeSet attrs)
             throws XmlPullParserException, IOException {
-        int type;
-
-        final TypedArray ta = view.getContext().obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.ViewTag);
-        final int key = ta.getResourceId(com.android.internal.R.styleable.ViewTag_id, 0);
-        final CharSequence value = ta.getText(com.android.internal.R.styleable.ViewTag_value);
+        final Context context = view.getContext();
+        final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewTag);
+        final int key = ta.getResourceId(R.styleable.ViewTag_id, 0);
+        final CharSequence value = ta.getText(R.styleable.ViewTag_value);
         view.setTag(key, value);
         ta.recycle();
 
-        final int currentDepth = parser.getDepth();
-        while (((type = parser.next()) != XmlPullParser.END_TAG ||
-                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
-            // Empty
-        }
+        consumeChildElements(parser);
     }
 
-    private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs,
-            boolean inheritContext) throws XmlPullParserException, IOException {
+    private void parseInclude(XmlPullParser parser, Context context, View parent,
+            AttributeSet attrs) throws XmlPullParserException, IOException {
         int type;
 
         if (parent instanceof ViewGroup) {
-            Context context = inheritContext ? parent.getContext() : mContext;
-
-            // Apply a theme wrapper, if requested.
+            // Apply a theme wrapper, if requested. This is sort of a weird
+            // edge case, since developers think the <include> overwrites
+            // values in the AttributeSet of the included View. So, if the
+            // included View has a theme attribute, we'll need to ignore it.
             final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
             final int themeResId = ta.getResourceId(0, 0);
-            if (themeResId != 0) {
+            final boolean hasThemeOverride = themeResId != 0;
+            if (hasThemeOverride) {
                 context = new ContextThemeWrapper(context, themeResId);
             }
             ta.recycle();
@@ -880,11 +894,12 @@
             int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
             if (layout == 0) {
                 final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
-                if (value == null || value.length() < 1) {
+                if (value == null || value.length() <= 0) {
                     throw new InflateException("You must specify a layout in the"
                             + " include tag: <include layout=\"@layout/layoutID\" />");
                 }
 
+                // Attempt to resolve the "?attr/name" string to an identifier.
                 layout = context.getResources().getIdentifier(value.substring(1), null, null);
             }
 
@@ -901,8 +916,7 @@
                 throw new InflateException("You must specify a valid layout "
                         + "reference. The layout ID " + value + " is not valid.");
             } else {
-                final XmlResourceParser childParser =
-                        getContext().getResources().getLayout(layout);
+                final XmlResourceParser childParser = context.getResources().getLayout(layout);
 
                 try {
                     final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
@@ -920,11 +934,12 @@
                     final String childName = childParser.getName();
 
                     if (TAG_MERGE.equals(childName)) {
-                        // Inflate all children.
-                        rInflate(childParser, parent, childAttrs, false, inheritContext);
+                        // The <merge> tag doesn't support android:theme, so
+                        // nothing special to do here.
+                        rInflate(childParser, parent, context, childAttrs, false);
                     } else {
-                        final View view = createViewFromTag(parent, childName, childAttrs,
-                                inheritContext);
+                        final View view = createViewFromTag(parent, childName,
+                                context, childAttrs, hasThemeOverride);
                         final ViewGroup group = (ViewGroup) parent;
 
                         final TypedArray a = context.obtainStyledAttributes(
@@ -957,7 +972,7 @@
                         view.setLayoutParams(params);
 
                         // Inflate all children.
-                        rInflate(childParser, view, childAttrs, true, true);
+                        rInflateChildren(childParser, view, childAttrs, true);
 
                         if (id != View.NO_ID) {
                             view.setId(id);
@@ -985,6 +1000,16 @@
             throw new InflateException("<include /> can only be used inside of a ViewGroup");
         }
 
+        LayoutInflater.consumeChildElements(parser);
+    }
+
+    /**
+     * <strong>Note:</strong> default visibility so that
+     * LayoutInflater_Delegate can call it.
+     */
+    final static void consumeChildElements(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int type;
         final int currentDepth = parser.getDepth();
         while (((type = parser.next()) != XmlPullParser.END_TAG ||
                 parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
diff --git a/core/java/android/view/PhoneFallbackEventHandler.java b/core/java/android/view/PhoneFallbackEventHandler.java
index fbf5732..350650d 100644
--- a/core/java/android/view/PhoneFallbackEventHandler.java
+++ b/core/java/android/view/PhoneFallbackEventHandler.java
@@ -25,8 +25,13 @@
 import android.media.AudioManager;
 import android.media.session.MediaSessionLegacyHelper;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.telephony.TelephonyManager;
-import android.util.Slog;
+import android.util.Log;
+import android.view.View;
+import android.view.HapticFeedbackConstants;
+import android.view.FallbackEventHandler;
+import android.view.KeyEvent;
 
 /**
  * @hide
@@ -112,15 +117,20 @@
                     dispatcher.startTracking(event, this);
                 } else if (event.isLongPress() && dispatcher.isTracking(event)) {
                     dispatcher.performedLongPress(event);
-                    mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    // launch the VoiceDialer
-                    Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    try {
-                        sendCloseSystemWindows();
-                        mContext.startActivity(intent);
-                    } catch (ActivityNotFoundException e) {
-                        startCallActivity();
+                    if (isUserSetupComplete()) {
+                        mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                        // launch the VoiceDialer
+                        Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        try {
+                            sendCloseSystemWindows();
+                            mContext.startActivity(intent);
+                        } catch (ActivityNotFoundException e) {
+                            startCallActivity();
+                        }
+                    } else {
+                        Log.i(TAG, "Not starting call activity because user "
+                                + "setup is in progress.");
                     }
                 }
                 return true;
@@ -134,13 +144,18 @@
                     dispatcher.startTracking(event, this);
                 } else if (event.isLongPress() && dispatcher.isTracking(event)) {
                     dispatcher.performedLongPress(event);
-                    mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                    sendCloseSystemWindows();
-                    // Broadcast an intent that the Camera button was longpressed
-                    Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
-                    intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
-                    mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
-                            null, null, null, 0, null, null);
+                    if (isUserSetupComplete()) {
+                        mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                        sendCloseSystemWindows();
+                        // Broadcast an intent that the Camera button was longpressed
+                        Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
+                        intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
+                        mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,
+                                null, null, null, 0, null, null);
+                    } else {
+                        Log.i(TAG, "Not dispatching CAMERA long press because user "
+                                + "setup is in progress.");
+                    }
                 }
                 return true;
             }
@@ -155,21 +170,26 @@
                     Configuration config = mContext.getResources().getConfiguration();
                     if (config.keyboard == Configuration.KEYBOARD_NOKEYS
                             || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
-                        // launch the search activity
-                        Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
-                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        try {
-                            mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                            sendCloseSystemWindows();
-                            getSearchManager().stopSearch();
-                            mContext.startActivity(intent);
-                            // Only clear this if we successfully start the
-                            // activity; otherwise we will allow the normal short
-                            // press action to be performed.
-                            dispatcher.performedLongPress(event);
-                            return true;
-                        } catch (ActivityNotFoundException e) {
-                            // Ignore
+                        if (isUserSetupComplete()) {
+                            // launch the search activity
+                            Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
+                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                            try {
+                                mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                                sendCloseSystemWindows();
+                                getSearchManager().stopSearch();
+                                mContext.startActivity(intent);
+                                // Only clear this if we successfully start the
+                                // activity; otherwise we will allow the normal short
+                                // press action to be performed.
+                                dispatcher.performedLongPress(event);
+                                return true;
+                            } catch (ActivityNotFoundException e) {
+                                // Ignore
+                            }
+                        } else {
+                            Log.i(TAG, "Not dispatching SEARCH long press because user "
+                                    + "setup is in progress.");
                         }
                     }
                 }
@@ -181,7 +201,7 @@
 
     boolean onKeyUp(int keyCode, KeyEvent event) {
         if (DEBUG) {
-            Slog.d(TAG, "up " + keyCode);
+            Log.d(TAG, "up " + keyCode);
         }
         final KeyEvent.DispatcherState dispatcher = mView.getKeyDispatcherState();
         if (dispatcher != null) {
@@ -229,7 +249,12 @@
                     break;
                 }
                 if (event.isTracking() && !event.isCanceled()) {
-                    startCallActivity();
+                    if (isUserSetupComplete()) {
+                        startCallActivity();
+                    } else {
+                        Log.i(TAG, "Not starting call activity because user "
+                                + "setup is in progress.");
+                    }
                 }
                 return true;
             }
@@ -244,7 +269,7 @@
         try {
             mContext.startActivity(intent);
         } catch (ActivityNotFoundException e) {
-            Slog.w(TAG, "No activity found for android.intent.action.CALL_BUTTON.");
+            Log.w(TAG, "No activity found for android.intent.action.CALL_BUTTON.");
         }
     }
 
@@ -284,5 +309,10 @@
     private void handleMediaKeyEvent(KeyEvent keyEvent) {
         MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
     }
+
+    private boolean isUserSetupComplete() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+    }
 }
 
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 5bc16cb..2aaa356 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.StyleRes;
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -31,6 +32,7 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 
@@ -118,7 +120,9 @@
      * @param count The shown week count.
      *
      * @attr ref android.R.styleable#CalendarView_shownWeekCount
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setShownWeekCount(int count) {
         mDelegate.setShownWeekCount(count);
     }
@@ -129,7 +133,9 @@
      * @return The shown week count.
      *
      * @attr ref android.R.styleable#CalendarView_shownWeekCount
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public int getShownWeekCount() {
         return mDelegate.getShownWeekCount();
     }
@@ -140,7 +146,9 @@
      * @param color The week background color.
      *
      * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setSelectedWeekBackgroundColor(@ColorInt int color) {
         mDelegate.setSelectedWeekBackgroundColor(color);
     }
@@ -151,8 +159,10 @@
      * @return The week background color.
      *
      * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
     @ColorInt
+    @Deprecated
     public int getSelectedWeekBackgroundColor() {
         return mDelegate.getSelectedWeekBackgroundColor();
     }
@@ -163,7 +173,9 @@
      * @param color The focused month date color.
      *
      * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setFocusedMonthDateColor(@ColorInt int color) {
         mDelegate.setFocusedMonthDateColor(color);
     }
@@ -174,8 +186,10 @@
      * @return The focused month date color.
      *
      * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
     @ColorInt
+    @Deprecated
     public int getFocusedMonthDateColor() {
         return mDelegate.getFocusedMonthDateColor();
     }
@@ -186,7 +200,9 @@
      * @param color A not focused month date color.
      *
      * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setUnfocusedMonthDateColor(@ColorInt int color) {
         mDelegate.setUnfocusedMonthDateColor(color);
     }
@@ -197,8 +213,10 @@
      * @return A not focused month date color.
      *
      * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
     @ColorInt
+    @Deprecated
     public int getUnfocusedMonthDateColor() {
         return mDelegate.getUnfocusedMonthDateColor();
     }
@@ -209,7 +227,9 @@
      * @param color The week number color.
      *
      * @attr ref android.R.styleable#CalendarView_weekNumberColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setWeekNumberColor(@ColorInt int color) {
         mDelegate.setWeekNumberColor(color);
     }
@@ -220,8 +240,10 @@
      * @return The week number color.
      *
      * @attr ref android.R.styleable#CalendarView_weekNumberColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
     @ColorInt
+    @Deprecated
     public int getWeekNumberColor() {
         return mDelegate.getWeekNumberColor();
     }
@@ -232,7 +254,9 @@
      * @param color The week separator color.
      *
      * @attr ref android.R.styleable#CalendarView_weekSeparatorLineColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setWeekSeparatorLineColor(@ColorInt int color) {
         mDelegate.setWeekSeparatorLineColor(color);
     }
@@ -243,8 +267,10 @@
      * @return The week separator color.
      *
      * @attr ref android.R.styleable#CalendarView_weekSeparatorLineColor
+     * @deprecated No longer used by Material-style CalendarView.
      */
     @ColorInt
+    @Deprecated
     public int getWeekSeparatorLineColor() {
         return mDelegate.getWeekSeparatorLineColor();
     }
@@ -256,7 +282,9 @@
      * @param resourceId The vertical bar drawable resource id.
      *
      * @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setSelectedDateVerticalBar(@DrawableRes int resourceId) {
         mDelegate.setSelectedDateVerticalBar(resourceId);
     }
@@ -268,7 +296,9 @@
      * @param drawable The vertical bar drawable.
      *
      * @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public void setSelectedDateVerticalBar(Drawable drawable) {
         mDelegate.setSelectedDateVerticalBar(drawable);
     }
@@ -278,7 +308,9 @@
      * the end of the selected date.
      *
      * @return The vertical bar drawable.
+     * @deprecated No longer used by Material-style CalendarView.
      */
+    @Deprecated
     public Drawable getSelectedDateVerticalBar() {
         return mDelegate.getSelectedDateVerticalBar();
     }
@@ -519,29 +551,36 @@
         void setShownWeekCount(int count);
         int getShownWeekCount();
 
-        void setSelectedWeekBackgroundColor(int color);
+        void setSelectedWeekBackgroundColor(@ColorInt int color);
+        @ColorInt
         int getSelectedWeekBackgroundColor();
 
-        void setFocusedMonthDateColor(int color);
+        void setFocusedMonthDateColor(@ColorInt int color);
+        @ColorInt
         int getFocusedMonthDateColor();
 
-        void setUnfocusedMonthDateColor(int color);
+        void setUnfocusedMonthDateColor(@ColorInt int color);
+        @ColorInt
         int getUnfocusedMonthDateColor();
 
-        void setWeekNumberColor(int color);
+        void setWeekNumberColor(@ColorInt int color);
+        @ColorInt
         int getWeekNumberColor();
 
-        void setWeekSeparatorLineColor(int color);
+        void setWeekSeparatorLineColor(@ColorInt int color);
+        @ColorInt
         int getWeekSeparatorLineColor();
 
-        void setSelectedDateVerticalBar(int resourceId);
+        void setSelectedDateVerticalBar(@DrawableRes int resourceId);
         void setSelectedDateVerticalBar(Drawable drawable);
         Drawable getSelectedDateVerticalBar();
 
-        void setWeekDayTextAppearance(int resourceId);
+        void setWeekDayTextAppearance(@StyleRes int resourceId);
+        @StyleRes
         int getWeekDayTextAppearance();
 
-        void setDateTextAppearance(int resourceId);
+        void setDateTextAppearance(@StyleRes int resourceId);
+        @StyleRes
         int getDateTextAppearance();
 
         void setMinDate(long minDate);
@@ -569,18 +608,12 @@
      * An abstract class which can be used as a start for CalendarView implementations
      */
     abstract static class AbstractCalendarViewDelegate implements CalendarViewDelegate {
-        /** String for parsing dates. */
-        private static final String DATE_FORMAT = "MM/dd/yyyy";
-
         /** The default minimal date. */
         protected static final String DEFAULT_MIN_DATE = "01/01/1900";
 
         /** The default maximal date. */
         protected static final String DEFAULT_MAX_DATE = "01/01/2100";
 
-        /** Date format for parsing dates. */
-        protected static final DateFormat DATE_FORMATTER = new SimpleDateFormat(DATE_FORMAT);
-
         protected CalendarView mDelegator;
         protected Context mContext;
         protected Locale mCurrentLocale;
@@ -600,21 +633,131 @@
             mCurrentLocale = locale;
         }
 
-        /**
-         * Parses the given <code>date</code> and in case of success sets
-         * the result to the <code>outDate</code>.
-         *
-         * @return True if the date was parsed.
-         */
-        protected boolean parseDate(String date, Calendar outDate) {
-            try {
-                outDate.setTime(DATE_FORMATTER.parse(date));
-                return true;
-            } catch (ParseException e) {
-                Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
-                return false;
-            }
+        @Override
+        public void setShownWeekCount(int count) {
+            // Deprecated.
+        }
+
+        @Override
+        public int getShownWeekCount() {
+            // Deprecated.
+            return 0;
+        }
+
+        @Override
+        public void setSelectedWeekBackgroundColor(@ColorInt int color) {
+            // Deprecated.
+        }
+
+        @ColorInt
+        @Override
+        public int getSelectedWeekBackgroundColor() {
+            return 0;
+        }
+
+        @Override
+        public void setFocusedMonthDateColor(@ColorInt int color) {
+            // Deprecated.
+        }
+
+        @ColorInt
+        @Override
+        public int getFocusedMonthDateColor() {
+            return 0;
+        }
+
+        @Override
+        public void setUnfocusedMonthDateColor(@ColorInt int color) {
+            // Deprecated.
+        }
+
+        @ColorInt
+        @Override
+        public int getUnfocusedMonthDateColor() {
+            return 0;
+        }
+
+        @Override
+        public void setWeekNumberColor(@ColorInt int color) {
+            // Deprecated.
+        }
+
+        @ColorInt
+        @Override
+        public int getWeekNumberColor() {
+            // Deprecated.
+            return 0;
+        }
+
+        @Override
+        public void setWeekSeparatorLineColor(@ColorInt int color) {
+            // Deprecated.
+        }
+
+        @ColorInt
+        @Override
+        public int getWeekSeparatorLineColor() {
+            // Deprecated.
+            return 0;
+        }
+
+        @Override
+        public void setSelectedDateVerticalBar(@DrawableRes int resId) {
+            // Deprecated.
+        }
+
+        @Override
+        public void setSelectedDateVerticalBar(Drawable drawable) {
+            // Deprecated.
+        }
+
+        @Override
+        public Drawable getSelectedDateVerticalBar() {
+            // Deprecated.
+            return null;
+        }
+
+        @Override
+        public void setShowWeekNumber(boolean showWeekNumber) {
+            // Deprecated.
+        }
+
+        @Override
+        public boolean getShowWeekNumber() {
+            // Deprecated.
+            return false;
+        }
+
+        @Override
+        public void onConfigurationChanged(Configuration newConfig) {
+            // Nothing to do here, configuration changes are already propagated
+            // by ViewGroup.
         }
     }
 
+    /** String for parsing dates. */
+    private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+    /** Date format for parsing dates. */
+    private static final DateFormat DATE_FORMATTER = new SimpleDateFormat(DATE_FORMAT);
+
+    /**
+     * Utility method for the date format used by CalendarView's min/max date.
+     *
+     * @hide Use only as directed. For internal use only.
+     */
+    public static boolean parseDate(String date, Calendar outDate) {
+        if (date == null || date.isEmpty()) {
+            return false;
+        }
+
+        try {
+            final Date parsedDate = DATE_FORMATTER.parse(date);
+            outDate.setTime(parsedDate);
+            return true;
+        } catch (ParseException e) {
+            Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 2ab3548..6ab3828 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -27,7 +27,6 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -267,12 +266,12 @@
         mFirstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
                 LocaleData.get(Locale.getDefault()).firstDayOfWeek);
         final String minDate = a.getString(R.styleable.CalendarView_minDate);
-        if (TextUtils.isEmpty(minDate) || !parseDate(minDate, mMinDate)) {
-            parseDate(DEFAULT_MIN_DATE, mMinDate);
+        if (!CalendarView.parseDate(minDate, mMinDate)) {
+            CalendarView.parseDate(DEFAULT_MIN_DATE, mMinDate);
         }
         final String maxDate = a.getString(R.styleable.CalendarView_maxDate);
-        if (TextUtils.isEmpty(maxDate) || !parseDate(maxDate, mMaxDate)) {
-            parseDate(DEFAULT_MAX_DATE, mMaxDate);
+        if (!CalendarView.parseDate(maxDate, mMaxDate)) {
+            CalendarView.parseDate(DEFAULT_MAX_DATE, mMaxDate);
         }
         if (mMaxDate.before(mMinDate)) {
             throw new IllegalArgumentException("Max date cannot be before min date.");
diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java
index b0f3740..7bce756 100644
--- a/core/java/android/widget/CalendarViewMaterialDelegate.java
+++ b/core/java/android/widget/CalendarViewMaterialDelegate.java
@@ -16,20 +16,11 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
+import android.annotation.StyleRes;
 import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.MathUtils;
 
 import java.util.Calendar;
-import java.util.Locale;
-
-import libcore.icu.LocaleData;
 
 class CalendarViewMaterialDelegate extends CalendarView.AbstractCalendarViewDelegate {
     private final DayPickerView mDayPickerView;
@@ -40,142 +31,32 @@
             int defStyleAttr, int defStyleRes) {
         super(delegator, context);
 
-        final TypedArray a = context.obtainStyledAttributes(attrs,
-                R.styleable.CalendarView, defStyleAttr, defStyleRes);
-        final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
-                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
-
-        final long minDate = parseDateToMillis(a.getString(
-                R.styleable.CalendarView_minDate), DEFAULT_MIN_DATE);
-        final long maxDate = parseDateToMillis(a.getString(
-                R.styleable.CalendarView_maxDate), DEFAULT_MAX_DATE);
-        if (maxDate < minDate) {
-            throw new IllegalArgumentException("max date cannot be before min date");
-        }
-
-        final long setDate = MathUtils.constrain(System.currentTimeMillis(), minDate, maxDate);
-        final int dateTextAppearanceResId = a.getResourceId(
-                R.styleable.CalendarView_dateTextAppearance,
-                R.style.TextAppearance_DeviceDefault_Small);
-
-        a.recycle();
-
-        mDayPickerView = new DayPickerView(context);
-        mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
-        mDayPickerView.setCalendarTextAppearance(dateTextAppearanceResId);
-        mDayPickerView.setMinDate(minDate);
-        mDayPickerView.setMaxDate(maxDate);
-        mDayPickerView.setDate(setDate, false, true);
+        mDayPickerView = new DayPickerView(context, attrs, defStyleAttr, defStyleRes);
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
         delegator.addView(mDayPickerView);
     }
 
-    private long parseDateToMillis(String dateStr, String defaultDateStr) {
-        final Calendar tempCalendar = Calendar.getInstance();
-        if (TextUtils.isEmpty(dateStr) || !parseDate(dateStr, tempCalendar)) {
-            parseDate(defaultDateStr, tempCalendar);
-        }
-        return tempCalendar.getTimeInMillis();
-    }
-
     @Override
-    public void setShownWeekCount(int count) {
-        // Deprecated.
+    public void setWeekDayTextAppearance(@StyleRes int resId) {
+        mDayPickerView.setDayOfWeekTextAppearance(resId);
     }
 
-    @Override
-    public int getShownWeekCount() {
-        // Deprecated.
-        return 0;
-    }
-
-    @Override
-    public void setSelectedWeekBackgroundColor(int color) {
-        // TODO: Should use a ColorStateList. Deprecate?
-    }
-
-    @Override
-    public int getSelectedWeekBackgroundColor() {
-        return 0;
-    }
-
-    @Override
-    public void setFocusedMonthDateColor(int color) {
-        // TODO: Should use a ColorStateList. Deprecate?
-    }
-
-    @Override
-    public int getFocusedMonthDateColor() {
-        return 0;
-    }
-
-    @Override
-    public void setUnfocusedMonthDateColor(int color) {
-        // TODO: Should use a ColorStateList. Deprecate?
-    }
-
-    @Override
-    public int getUnfocusedMonthDateColor() {
-        return 0;
-    }
-
-    @Override
-    public void setWeekDayTextAppearance(int resourceId) {
-
-    }
-
+    @StyleRes
     @Override
     public int getWeekDayTextAppearance() {
-        return 0;
+        return mDayPickerView.getDayOfWeekTextAppearance();
     }
 
     @Override
-    public void setDateTextAppearance(int resourceId) {
-
+    public void setDateTextAppearance(@StyleRes int resId) {
+        mDayPickerView.setDayTextAppearance(resId);
     }
 
+    @StyleRes
     @Override
     public int getDateTextAppearance() {
-        return 0;
-    }
-
-    @Override
-    public void setWeekNumberColor(int color) {
-        // Deprecated.
-    }
-
-    @Override
-    public int getWeekNumberColor() {
-        // Deprecated.
-        return 0;
-    }
-
-    @Override
-    public void setWeekSeparatorLineColor(int color) {
-        // Deprecated.
-    }
-
-    @Override
-    public int getWeekSeparatorLineColor() {
-        // Deprecated.
-        return 0;
-    }
-
-    @Override
-    public void setSelectedDateVerticalBar(int resourceId) {
-        // Deprecated.
-    }
-
-    @Override
-    public void setSelectedDateVerticalBar(Drawable drawable) {
-        // Deprecated.
-    }
-
-    @Override
-    public Drawable getSelectedDateVerticalBar() {
-        // Deprecated.
-        return null;
+        return mDayPickerView.getDayTextAppearance();
     }
 
     @Override
@@ -199,17 +80,6 @@
     }
 
     @Override
-    public void setShowWeekNumber(boolean showWeekNumber) {
-        // Deprecated.
-    }
-
-    @Override
-    public boolean getShowWeekNumber() {
-        // Deprecated.
-        return false;
-    }
-
-    @Override
     public void setFirstDayOfWeek(int firstDayOfWeek) {
         mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
     }
@@ -221,12 +91,12 @@
 
     @Override
     public void setDate(long date) {
-        mDayPickerView.setDate(date, true, false);
+        mDayPickerView.setDate(date, true);
     }
 
     @Override
     public void setDate(long date, boolean animate, boolean center) {
-        mDayPickerView.setDate(date, animate, center);
+        mDayPickerView.setDate(date, animate);
     }
 
     @Override
@@ -239,12 +109,6 @@
         mOnDateChangeListener = listener;
     }
 
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        // Nothing to do here, configuration changes are already propagated
-        // by ViewGroup.
-    }
-
     private final DayPickerView.OnDaySelectedListener mOnDaySelectedListener =
             new DayPickerView.OnDaySelectedListener() {
         @Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 45998f7..5f5943f 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -98,7 +98,7 @@
     private final DatePickerDelegate mDelegate;
 
     /**
-     * The callback used to indicate the user changes\d the date.
+     * The callback used to indicate the user changed the date.
      */
     public interface OnDateChangedListener {
 
@@ -348,9 +348,13 @@
     }
 
     /**
-     * Gets whether the {@link CalendarView} is shown.
+     * Returns whether the {@link CalendarView} is shown.
+     * <p>
+     * <strong>Note:</strong> This method returns {@code false} when the
+     * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
+     * to {@code calendar}.
      *
-     * @return True if the calendar view is shown.
+     * @return {@code true} if the calendar view is shown
      * @see #getCalendarView()
      */
     public boolean getCalendarViewShown() {
@@ -358,13 +362,13 @@
     }
 
     /**
-     * Gets the {@link CalendarView}.
+     * Returns the {@link CalendarView} used by this picker.
      * <p>
-     * This method returns {@code null} when the
+     * <strong>Note:</strong> This method returns {@code null} when the
      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
      * to {@code calendar}.
      *
-     * @return The calendar view.
+     * @return the calendar view
      * @see #getCalendarViewShown()
      */
     public CalendarView getCalendarView() {
@@ -374,20 +378,25 @@
     /**
      * Sets whether the {@link CalendarView} is shown.
      * <p>
-     * Calling this method has no effect when the
+     * <strong>Note:</strong> Calling this method has no effect when the
      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
      * to {@code calendar}.
      *
-     * @param shown True if the calendar view is to be shown.
+     * @param shown {@code true} to show the calendar view, {@code false} to
+     *              hide it
      */
     public void setCalendarViewShown(boolean shown) {
         mDelegate.setCalendarViewShown(shown);
     }
 
     /**
-     * Gets whether the spinners are shown.
+     * Returns whether the spinners are shown.
+     * <p>
+     * <strong>Note:</strong> his method returns {@code false} when the
+     * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
+     * to {@code calendar}.
      *
-     * @return True if the spinners are shown.
+     * @return {@code true} if the spinners are shown
      */
     public boolean getSpinnersShown() {
         return mDelegate.getSpinnersShown();
@@ -395,8 +404,13 @@
 
     /**
      * Sets whether the spinners are shown.
+     * <p>
+     * Calling this method has no effect when the
+     * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
+     * to {@code calendar}.
      *
-     * @param shown True if the spinners are to be shown.
+     * @param shown {@code true} to show the spinners, {@code false} to hide
+     *              them
      */
     public void setSpinnersShown(boolean shown) {
         mDelegate.setSpinnersShown(shown);
@@ -489,15 +503,14 @@
             mDelegator = delegator;
             mContext = context;
 
-            // initialization based on locale
             setCurrentLocale(Locale.getDefault());
         }
 
         protected void setCurrentLocale(Locale locale) {
-            if (locale.equals(mCurrentLocale)) {
-                return;
+            if (!locale.equals(mCurrentLocale)) {
+                mCurrentLocale = locale;
+                onLocaleChanged(locale);
             }
-            mCurrentLocale = locale;
         }
 
         @Override
@@ -510,6 +523,10 @@
                 mValidationCallback.onValidationChanged(valid);
             }
         }
+
+        protected void onLocaleChanged(Locale locale) {
+            // Stub.
+        }
     }
 
     /**
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 0e3ec7f..7b8a979 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
@@ -26,90 +27,84 @@
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
+import android.util.StateSet;
 import android.view.HapticFeedbackConstants;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
+import android.widget.DayPickerView.OnDaySelectedListener;
+import android.widget.YearPickerView.OnYearSelectedListener;
 
 import com.android.internal.R;
-import com.android.internal.widget.AccessibleDateAnimator;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
-import java.util.HashSet;
 import java.util.Locale;
 
 /**
  * A delegate for picking up a date (day / month / year).
  */
-class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements
-        View.OnClickListener, DatePickerController {
+class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
+
     private static final int USE_LOCALE = 0;
 
     private static final int UNINITIALIZED = -1;
-    private static final int MONTH_AND_DAY_VIEW = 0;
-    private static final int YEAR_VIEW = 1;
+    private static final int VIEW_MONTH_DAY = 0;
+    private static final int VIEW_YEAR = 1;
 
     private static final int DEFAULT_START_YEAR = 1900;
     private static final int DEFAULT_END_YEAR = 2100;
 
     private static final int ANIMATION_DURATION = 300;
 
-    private static final int MONTH_INDEX = 0;
-    private static final int DAY_INDEX = 1;
-    private static final int YEAR_INDEX = 2;
+    public static final int[] ATTRS_TEXT_COLOR = new int[]{com.android.internal.R.attr.textColor};
 
-    private SimpleDateFormat mYearFormat = new SimpleDateFormat("y", Locale.getDefault());
-    private SimpleDateFormat mDayFormat = new SimpleDateFormat("d", Locale.getDefault());
+    public static final int[] ATTRS_DISABLED_ALPHA = new int[]{
+            com.android.internal.R.attr.disabledAlpha};
 
-    private TextView mDayOfWeekView;
+    private SimpleDateFormat mYearFormat;
+    private SimpleDateFormat mMonthDayFormat;
 
-    /** Layout that contains the current month, day, and year. */
-    private LinearLayout mMonthDayYearLayout;
+    // Top-level container.
+    private ViewGroup mContainer;
 
-    /** Clickable layout that contains the current day and year. */
-    private LinearLayout mMonthAndDayLayout;
+    // Header views.
+    private TextView mHeaderYear;
+    private TextView mHeaderMonthDay;
 
-    private TextView mHeaderMonthTextView;
-    private TextView mHeaderDayOfMonthTextView;
-    private TextView mHeaderYearTextView;
+    // Picker views.
+    private ViewAnimator mAnimator;
     private DayPickerView mDayPickerView;
     private YearPickerView mYearPickerView;
 
-    private boolean mIsEnabled = true;
-
     // Accessibility strings.
-    private String mDayPickerDescription;
     private String mSelectDay;
-    private String mYearPickerDescription;
     private String mSelectYear;
 
-    private AccessibleDateAnimator mAnimator;
-
     private DatePicker.OnDateChangedListener mDateChangedListener;
 
     private int mCurrentView = UNINITIALIZED;
 
-    private Calendar mCurrentDate;
-    private Calendar mTempDate;
-    private Calendar mMinDate;
-    private Calendar mMaxDate;
+    private final Calendar mCurrentDate;
+    private final Calendar mTempDate;
+    private final Calendar mMinDate;
+    private final Calendar mMaxDate;
 
     private int mFirstDayOfWeek = USE_LOCALE;
 
-    private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
-
     public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(delegator, context);
 
-        final Locale locale = Locale.getDefault();
-        mMinDate = getCalendarForLocale(mMinDate, locale);
-        mMaxDate = getCalendarForLocale(mMaxDate, locale);
-        mTempDate = getCalendarForLocale(mMaxDate, locale);
-        mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+        final Locale locale = mCurrentLocale;
+        mCurrentDate = Calendar.getInstance(locale);
+        mTempDate = Calendar.getInstance(locale);
+        mMinDate = Calendar.getInstance(locale);
+        mMaxDate = Calendar.getInstance(locale);
 
         mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
         mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
@@ -120,71 +115,64 @@
         final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         final int layoutResourceId = a.getResourceId(
-                R.styleable.DatePicker_internalLayout, R.layout.date_picker_holo);
-        final View mainView = inflater.inflate(layoutResourceId, null);
-        mDelegator.addView(mainView);
+                R.styleable.DatePicker_internalLayout, R.layout.date_picker_material);
 
-        mDayOfWeekView = (TextView) mainView.findViewById(R.id.date_picker_header);
+        // Set up and attach container.
+        mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator);
 
-        // Layout that contains the current date and day name header.
-        final LinearLayout dateLayout = (LinearLayout) mainView.findViewById(
-                R.id.day_picker_selector_layout);
-        mMonthDayYearLayout = (LinearLayout) mainView.findViewById(
-                R.id.date_picker_month_day_year_layout);
-        mMonthAndDayLayout = (LinearLayout) mainView.findViewById(
-                R.id.date_picker_month_and_day_layout);
-        mMonthAndDayLayout.setOnClickListener(this);
-        mHeaderMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_month);
-        mHeaderDayOfMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_day);
-        mHeaderYearTextView = (TextView) mainView.findViewById(R.id.date_picker_year);
-        mHeaderYearTextView.setOnClickListener(this);
+        // Set up header views.
+        final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
+        mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
+        mHeaderYear.setOnClickListener(mOnHeaderClickListener);
+        mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
+        mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
 
-        // Obtain default highlight color from the theme.
-        final int defaultHighlightColor = mHeaderYearTextView.getHighlightColor();
+        // For the sake of backwards compatibility, attempt to extract the text
+        // color from the header month text appearance. If it's set, we'll let
+        // that override the "real" header text color.
+        ColorStateList headerTextColor = null;
 
-        // Use Theme attributes if possible
-        final int dayOfWeekTextAppearanceResId = a.getResourceId(
-                R.styleable.DatePicker_dayOfWeekTextAppearance, 0);
-        if (dayOfWeekTextAppearanceResId != 0) {
-            mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId);
-        }
-
-        mDayOfWeekView.setBackground(a.getDrawable(R.styleable.DatePicker_dayOfWeekBackground));
-
-        dateLayout.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
-
-        final int monthTextAppearanceResId = a.getResourceId(
+        @SuppressWarnings("deprecation")
+        final int monthHeaderTextAppearance = a.getResourceId(
                 R.styleable.DatePicker_headerMonthTextAppearance, 0);
-        if (monthTextAppearanceResId != 0) {
-            mHeaderMonthTextView.setTextAppearance(context, monthTextAppearanceResId);
+        if (monthHeaderTextAppearance != 0) {
+            final TypedArray textAppearance = mContext.obtainStyledAttributes(null,
+                    ATTRS_TEXT_COLOR, 0, monthHeaderTextAppearance);
+            final ColorStateList legacyHeaderTextColor = textAppearance.getColorStateList(0);
+            headerTextColor = applyLegacyColorFixes(legacyHeaderTextColor);
+            textAppearance.recycle();
         }
 
-        final int dayOfMonthTextAppearanceResId = a.getResourceId(
-                R.styleable.DatePicker_headerDayOfMonthTextAppearance, 0);
-        if (dayOfMonthTextAppearanceResId != 0) {
-            mHeaderDayOfMonthTextView.setTextAppearance(context, dayOfMonthTextAppearanceResId);
+        if (headerTextColor == null) {
+            headerTextColor = a.getColorStateList(R.styleable.DatePicker_headerTextColor);
         }
 
-        final int headerYearTextAppearanceResId = a.getResourceId(
-                R.styleable.DatePicker_headerYearTextAppearance, 0);
-        if (headerYearTextAppearanceResId != 0) {
-            mHeaderYearTextView.setTextAppearance(context, headerYearTextAppearanceResId);
+        if (headerTextColor != null) {
+            mHeaderYear.setTextColor(headerTextColor);
+            mHeaderMonthDay.setTextColor(headerTextColor);
         }
 
-        mDayPickerView = new DayPickerView(mContext);
+        // Set up header background, if available.
+        if (a.hasValueOrEmpty(R.styleable.DatePicker_headerBackground)) {
+            header.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
+        }
+
+        // Set up picker container.
+        mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
+
+        // Set up day picker view.
+        mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
         mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
         mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
         mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
         mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
-        mYearPickerView = new YearPickerView(mContext);
-        mYearPickerView.init(this);
+        // Set up year picker view.
+        mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
         mYearPickerView.setRange(mMinDate, mMaxDate);
-
-        final ColorStateList yearBackgroundColor = a.getColorStateList(
-                R.styleable.DatePicker_yearListSelectorColor);
-        mYearPickerView.setYearBackgroundColor(yearBackgroundColor);
+        mYearPickerView.setDate(mCurrentDate.getTimeInMillis());
+        mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
 
         final int yearTextAppearanceResId = a.getResourceId(
                 R.styleable.DatePicker_yearListItemTextAppearance, 0);
@@ -192,170 +180,201 @@
             mYearPickerView.setYearTextAppearance(yearTextAppearanceResId);
         }
 
-        final ColorStateList calendarTextColor = a.getColorStateList(
-                R.styleable.DatePicker_calendarTextColor);
-        mDayPickerView.setCalendarTextColor(calendarTextColor);
+        final int yearActivatedTextAppearanceResId = a.getResourceId(
+                R.styleable.DatePicker_yearListItemActivatedTextAppearance, 0);
+        if (yearActivatedTextAppearanceResId != 0) {
+            mYearPickerView.setYearActivatedTextAppearance(yearActivatedTextAppearanceResId);
+        }
 
-        final ColorStateList calendarDayBackgroundColor = a.getColorStateList(
-                R.styleable.DatePicker_calendarDayBackgroundColor);
-        mDayPickerView.setCalendarDayBackgroundColor(calendarDayBackgroundColor);
+        a.recycle();
 
-        mDayPickerDescription = res.getString(R.string.day_picker_description);
+        // Set up content descriptions.
         mSelectDay = res.getString(R.string.select_day);
-        mYearPickerDescription = res.getString(R.string.year_picker_description);
         mSelectYear = res.getString(R.string.select_year);
 
-        mAnimator = (AccessibleDateAnimator) mainView.findViewById(R.id.animator);
-        mAnimator.addView(mDayPickerView);
-        mAnimator.addView(mYearPickerView);
-        mAnimator.setDateMillis(mCurrentDate.getTimeInMillis());
+        final Animation inAnim = new AlphaAnimation(0, 1);
+        inAnim.setDuration(ANIMATION_DURATION);
+        mAnimator.setInAnimation(inAnim);
 
-        final Animation animation = new AlphaAnimation(0.0f, 1.0f);
-        animation.setDuration(ANIMATION_DURATION);
-        mAnimator.setInAnimation(animation);
+        final Animation outAnim = new AlphaAnimation(1, 0);
+        outAnim.setDuration(ANIMATION_DURATION);
+        mAnimator.setOutAnimation(outAnim);
 
-        final Animation animation2 = new AlphaAnimation(1.0f, 0.0f);
-        animation2.setDuration(ANIMATION_DURATION);
-        mAnimator.setOutAnimation(animation2);
+        // Initialize for current locale. This also initializes the date, so no
+        // need to call onDateChanged.
+        onLocaleChanged(mCurrentLocale);
 
-        updateDisplay(false);
-        setCurrentView(MONTH_AND_DAY_VIEW);
+        setCurrentView(VIEW_MONTH_DAY);
     }
 
     /**
-     * Gets a calendar for locale bootstrapped with the value of a given calendar.
+     * The legacy text color might have been poorly defined. Ensures that it
+     * has an appropriate activated state, using the selected state if one
+     * exists or modifying the default text color otherwise.
      *
-     * @param oldCalendar The old calendar.
-     * @param locale The locale.
+     * @param color a legacy text color, or {@code null}
+     * @return a color state list with an appropriate activated state, or
+     *         {@code null} if a valid activated state could not be generated
      */
-    private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
-        if (oldCalendar == null) {
-            return Calendar.getInstance(locale);
-        } else {
-            final long currentTimeMillis = oldCalendar.getTimeInMillis();
-            Calendar newCalendar = Calendar.getInstance(locale);
-            newCalendar.setTimeInMillis(currentTimeMillis);
-            return newCalendar;
+    @Nullable
+    private ColorStateList applyLegacyColorFixes(@Nullable ColorStateList color) {
+        if (color == null || color.hasState(R.attr.state_activated)) {
+            return color;
         }
+
+        final int activatedColor;
+        final int defaultColor;
+        if (color.hasState(R.attr.state_selected)) {
+            activatedColor = color.getColorForState(StateSet.get(
+                    StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_SELECTED), 0);
+            defaultColor = color.getColorForState(StateSet.get(
+                    StateSet.VIEW_STATE_ENABLED), 0);
+        } else {
+            activatedColor = color.getDefaultColor();
+
+            // Generate a non-activated color using the disabled alpha.
+            final TypedArray ta = mContext.obtainStyledAttributes(ATTRS_DISABLED_ALPHA);
+            final float disabledAlpha = ta.getFloat(0, 0.30f);
+            defaultColor = multiplyAlphaComponent(activatedColor, disabledAlpha);
+        }
+
+        if (activatedColor == 0 || defaultColor == 0) {
+            // We somehow failed to obtain the colors.
+            return null;
+        }
+
+        final int[][] stateSet = new int[][] {{ R.attr.state_activated }, {}};
+        final int[] colors = new int[] { activatedColor, defaultColor };
+        return new ColorStateList(stateSet, colors);
+    }
+
+    private int multiplyAlphaComponent(int color, float alphaMod) {
+        final int srcRgb = color & 0xFFFFFF;
+        final int srcAlpha = (color >> 24) & 0xFF;
+        final int dstAlpha = (int) (srcAlpha * alphaMod + 0.5f);
+        return srcRgb | (dstAlpha << 24);
     }
 
     /**
-     * Compute the array representing the order of Month / Day / Year views in their layout.
-     * Will be used for I18N purpose as the order of them depends on the Locale.
+     * Listener called when the user selects a day in the day picker view.
      */
-    private int[] getMonthDayYearIndexes(String pattern) {
-        int[] result = new int[3];
+    private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() {
+        @Override
+        public void onDaySelected(DayPickerView view, Calendar day) {
+            mCurrentDate.setTimeInMillis(day.getTimeInMillis());
+            onDateChanged(true, true);
+        }
+    };
 
-        final String filteredPattern = pattern.replaceAll("'.*?'", "");
-
-        final int dayIndex = filteredPattern.indexOf('d');
-        final int monthMIndex = filteredPattern.indexOf("M");
-        final int monthIndex = (monthMIndex != -1) ? monthMIndex : filteredPattern.indexOf("L");
-        final int yearIndex = filteredPattern.indexOf("y");
-
-        if (yearIndex < monthIndex) {
-            result[YEAR_INDEX] = 0;
-
-            if (monthIndex < dayIndex) {
-                result[MONTH_INDEX] = 1;
-                result[DAY_INDEX] = 2;
-            } else {
-                result[MONTH_INDEX] = 2;
-                result[DAY_INDEX] = 1;
+    /**
+     * Listener called when the user selects a year in the year picker view.
+     */
+    private final OnYearSelectedListener mOnYearSelectedListener = new OnYearSelectedListener() {
+        @Override
+        public void onYearChanged(YearPickerView view, int year) {
+            // If the newly selected month / year does not contain the
+            // currently selected day number, change the selected day number
+            // to the last day of the selected month or year.
+            // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
+            // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
+            final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
+            final int month = mCurrentDate.get(Calendar.MONTH);
+            final int daysInMonth = getDaysInMonth(month, year);
+            if (day > daysInMonth) {
+                mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth);
             }
-        } else {
-            result[YEAR_INDEX] = 2;
 
-            if (monthIndex < dayIndex) {
-                result[MONTH_INDEX] = 0;
-                result[DAY_INDEX] = 1;
-            } else {
-                result[MONTH_INDEX] = 1;
-                result[DAY_INDEX] = 0;
+            mCurrentDate.set(Calendar.YEAR, year);
+            onDateChanged(true, true);
+
+            // Automatically switch to day picker.
+            setCurrentView(VIEW_MONTH_DAY);
+        }
+    };
+
+    /**
+     * Listener called when the user clicks on a header item.
+     */
+    private final OnClickListener mOnHeaderClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            tryVibrate();
+
+            switch (v.getId()) {
+                case R.id.date_picker_header_year:
+                    setCurrentView(VIEW_YEAR);
+                    break;
+                case R.id.date_picker_header_date:
+                    setCurrentView(VIEW_MONTH_DAY);
+                    break;
             }
         }
-        return result;
+    };
+
+    @Override
+    protected void onLocaleChanged(Locale locale) {
+        final TextView headerYear = mHeaderYear;
+        if (headerYear == null) {
+            // Abort, we haven't initialized yet. This method will get called
+            // again later after everything has been set up.
+            return;
+        }
+
+        // Update the date formatter.
+        final String datePattern = DateFormat.getBestDateTimePattern(locale, "EMMMd");
+        mMonthDayFormat = new SimpleDateFormat(datePattern, locale);
+        mYearFormat = new SimpleDateFormat("y", locale);
+
+        // Update the header text.
+        onCurrentDateChanged(false);
     }
 
-    private void updateDisplay(boolean announce) {
-        if (mDayOfWeekView != null) {
-            mDayOfWeekView.setText(mCurrentDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG,
-                    Locale.getDefault()));
+    private void onCurrentDateChanged(boolean announce) {
+        if (mHeaderYear == null) {
+            // Abort, we haven't initialized yet. This method will get called
+            // again later after everything has been set up.
+            return;
         }
 
-        // Compute indices of Month, Day and Year views
-        final String bestDateTimePattern =
-                DateFormat.getBestDateTimePattern(mCurrentLocale, "yMMMd");
-        final int[] viewIndices = getMonthDayYearIndexes(bestDateTimePattern);
+        final String year = mYearFormat.format(mCurrentDate.getTime());
+        mHeaderYear.setText(year);
 
-        // Position the Year and MonthAndDay views within the header.
-        mMonthDayYearLayout.removeAllViews();
-        if (viewIndices[YEAR_INDEX] == 0) {
-            mMonthDayYearLayout.addView(mHeaderYearTextView);
-            mMonthDayYearLayout.addView(mMonthAndDayLayout);
-        } else {
-            mMonthDayYearLayout.addView(mMonthAndDayLayout);
-            mMonthDayYearLayout.addView(mHeaderYearTextView);
-        }
+        final String monthDay = mMonthDayFormat.format(mCurrentDate.getTime());
+        mHeaderMonthDay.setText(monthDay);
 
-        // Position Day and Month views within the MonthAndDay view.
-        mMonthAndDayLayout.removeAllViews();
-        if (viewIndices[MONTH_INDEX] > viewIndices[DAY_INDEX]) {
-            mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView);
-            mMonthAndDayLayout.addView(mHeaderMonthTextView);
-        } else {
-            mMonthAndDayLayout.addView(mHeaderMonthTextView);
-            mMonthAndDayLayout.addView(mHeaderDayOfMonthTextView);
-        }
-
-        mHeaderMonthTextView.setText(mCurrentDate.getDisplayName(Calendar.MONTH, Calendar.SHORT,
-                Locale.getDefault()).toUpperCase(Locale.getDefault()));
-        mHeaderDayOfMonthTextView.setText(mDayFormat.format(mCurrentDate.getTime()));
-        mHeaderYearTextView.setText(mYearFormat.format(mCurrentDate.getTime()));
-
-        // Accessibility.
-        long millis = mCurrentDate.getTimeInMillis();
-        mAnimator.setDateMillis(millis);
-        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
-        String monthAndDayText = DateUtils.formatDateTime(mContext, millis, flags);
-        mMonthAndDayLayout.setContentDescription(monthAndDayText);
-
+        // TODO: This should use live regions.
         if (announce) {
-            flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
-            String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
+            final long millis = mCurrentDate.getTimeInMillis();
+            final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+            final String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
             mAnimator.announceForAccessibility(fullDateText);
         }
     }
 
     private void setCurrentView(final int viewIndex) {
-        long millis = mCurrentDate.getTimeInMillis();
-
         switch (viewIndex) {
-            case MONTH_AND_DAY_VIEW:
-                mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
+            case VIEW_MONTH_DAY:
+                mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
+
                 if (mCurrentView != viewIndex) {
-                    mMonthAndDayLayout.setSelected(true);
-                    mHeaderYearTextView.setSelected(false);
-                    mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
+                    mHeaderMonthDay.setActivated(true);
+                    mHeaderYear.setActivated(false);
+                    mAnimator.setDisplayedChild(VIEW_MONTH_DAY);
                     mCurrentView = viewIndex;
                 }
 
-                final int flags = DateUtils.FORMAT_SHOW_DATE;
-                final String dayString = DateUtils.formatDateTime(mContext, millis, flags);
-                mAnimator.setContentDescription(mDayPickerDescription + ": " + dayString);
                 mAnimator.announceForAccessibility(mSelectDay);
                 break;
-            case YEAR_VIEW:
-                mYearPickerView.onDateChanged();
+            case VIEW_YEAR:
+                mYearPickerView.setDate(mCurrentDate.getTimeInMillis());
+
                 if (mCurrentView != viewIndex) {
-                    mMonthAndDayLayout.setSelected(false);
-                    mHeaderYearTextView.setSelected(true);
-                    mAnimator.setDisplayedChild(YEAR_VIEW);
+                    mHeaderMonthDay.setActivated(false);
+                    mHeaderYear.setActivated(true);
+                    mAnimator.setDisplayedChild(VIEW_YEAR);
                     mCurrentView = viewIndex;
                 }
 
-                final CharSequence yearString = mYearFormat.format(millis);
-                mAnimator.setContentDescription(mYearPickerDescription + ": " + yearString);
                 mAnimator.announceForAccessibility(mSelectYear);
                 break;
         }
@@ -383,20 +402,18 @@
     }
 
     private void onDateChanged(boolean fromUser, boolean callbackToClient) {
+        final int year = mCurrentDate.get(Calendar.YEAR);
+
         if (callbackToClient && mDateChangedListener != null) {
-            final int year = mCurrentDate.get(Calendar.YEAR);
             final int monthOfYear = mCurrentDate.get(Calendar.MONTH);
             final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
             mDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
         }
 
-        for (OnDateChangedListener listener : mListeners) {
-            listener.onDateChanged();
-        }
+        mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
+        mYearPickerView.setYear(year);
 
-        mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
-
-        updateDisplay(fromUser);
+        onCurrentDateChanged(fromUser);
 
         if (fromUser) {
             tryVibrate();
@@ -477,15 +494,12 @@
 
     @Override
     public void setEnabled(boolean enabled) {
-        mMonthAndDayLayout.setEnabled(enabled);
-        mHeaderYearTextView.setEnabled(enabled);
-        mAnimator.setEnabled(enabled);
-        mIsEnabled = enabled;
+        mContainer.setEnabled(false);
     }
 
     @Override
     public boolean isEnabled() {
-        return mIsEnabled;
+        return mContainer.isEnabled();
     }
 
     @Override
@@ -516,8 +530,7 @@
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        mYearFormat = new SimpleDateFormat("y", newConfig.locale);
-        mDayFormat = new SimpleDateFormat("d", newConfig.locale);
+        setCurrentLocale(newConfig.locale);
     }
 
     @Override
@@ -529,9 +542,9 @@
         int listPosition = -1;
         int listPositionOffset = -1;
 
-        if (mCurrentView == MONTH_AND_DAY_VIEW) {
+        if (mCurrentView == VIEW_MONTH_DAY) {
             listPosition = mDayPickerView.getMostVisiblePosition();
-        } else if (mCurrentView == YEAR_VIEW) {
+        } else if (mCurrentView == VIEW_YEAR) {
             listPosition = mYearPickerView.getFirstVisiblePosition();
             listPositionOffset = mYearPickerView.getFirstPositionOffset();
         }
@@ -544,20 +557,22 @@
     public void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
 
+        // TODO: Move instance state into DayPickerView, YearPickerView.
         mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
         mCurrentView = ss.getCurrentView();
         mMinDate.setTimeInMillis(ss.getMinDate());
         mMaxDate.setTimeInMillis(ss.getMaxDate());
 
-        updateDisplay(false);
+        onCurrentDateChanged(false);
         setCurrentView(mCurrentView);
 
         final int listPosition = ss.getListPosition();
         if (listPosition != -1) {
-            if (mCurrentView == MONTH_AND_DAY_VIEW) {
-                mDayPickerView.postSetSelection(listPosition);
-            } else if (mCurrentView == YEAR_VIEW) {
-                mYearPickerView.postSetSelectionFromTop(listPosition, ss.getListPositionOffset());
+            if (mCurrentView == VIEW_MONTH_DAY) {
+                mDayPickerView.setCurrentItem(listPosition);
+            } else if (mCurrentView == VIEW_YEAR) {
+                final int listPositionOffset = ss.getListPositionOffset();
+                mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
             }
         }
     }
@@ -577,28 +592,6 @@
         return DatePicker.class.getName();
     }
 
-    @Override
-    public void onYearSelected(int year) {
-        adjustDayInMonthIfNeeded(mCurrentDate.get(Calendar.MONTH), year);
-        mCurrentDate.set(Calendar.YEAR, year);
-        onDateChanged(true, true);
-
-        // Auto-advance to month and day view.
-        setCurrentView(MONTH_AND_DAY_VIEW);
-    }
-
-    // If the newly selected month / year does not contain the currently selected day number,
-    // change the selected day number to the last day of the selected month or year.
-    //      e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
-    //      e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
-    private void adjustDayInMonthIfNeeded(int month, int year) {
-        int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
-        int daysInMonth = getDaysInMonth(month, year);
-        if (day > daysInMonth) {
-            mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth);
-        }
-    }
-
     public static int getDaysInMonth(int month, int year) {
         switch (month) {
             case Calendar.JANUARY:
@@ -621,43 +614,10 @@
         }
     }
 
-    @Override
-    public void registerOnDateChangedListener(OnDateChangedListener listener) {
-        mListeners.add(listener);
-    }
-
-    @Override
-    public Calendar getSelectedDay() {
-        return mCurrentDate;
-    }
-
-    @Override
-    public void tryVibrate() {
+    private void tryVibrate() {
         mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
     }
 
-    @Override
-    public void onClick(View v) {
-        tryVibrate();
-        if (v.getId() == R.id.date_picker_year) {
-            setCurrentView(YEAR_VIEW);
-        } else if (v.getId() == R.id.date_picker_month_and_day_layout) {
-            setCurrentView(MONTH_AND_DAY_VIEW);
-        }
-    }
-
-    /**
-     * Listener called when the user selects a day in the day picker view.
-     */
-    private final DayPickerView.OnDaySelectedListener
-            mOnDaySelectedListener = new DayPickerView.OnDaySelectedListener() {
-        @Override
-        public void onDaySelected(DayPickerView view, Calendar day) {
-            mCurrentDate.setTimeInMillis(day.getTimeInMillis());
-            onDateChanged(true, true);
-        }
-    };
-
     /**
      * Class for managing state storing/restoring.
      */
diff --git a/core/java/android/widget/DayPickerAdapter.java b/core/java/android/widget/DayPickerAdapter.java
new file mode 100644
index 0000000..4f9f09e
--- /dev/null
+++ b/core/java/android/widget/DayPickerAdapter.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import com.android.internal.widget.PagerAdapter;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SimpleMonthView.OnDayClickListener;
+
+import java.util.Calendar;
+
+/**
+ * An adapter for a list of {@link android.widget.SimpleMonthView} items.
+ */
+class DayPickerAdapter extends PagerAdapter {
+    private static final int MONTHS_IN_YEAR = 12;
+
+    private final Calendar mMinDate = Calendar.getInstance();
+    private final Calendar mMaxDate = Calendar.getInstance();
+
+    private final SparseArray<SimpleMonthView> mItems = new SparseArray<>();
+
+    private Calendar mSelectedDay = Calendar.getInstance();
+
+    private int mMonthTextAppearance;
+    private int mDayOfWeekTextAppearance;
+    private int mDayTextAppearance;
+
+    private ColorStateList mCalendarTextColor;
+    private ColorStateList mDaySelectorColor;
+    private ColorStateList mDayHighlightColor;
+
+    private OnDaySelectedListener mOnDaySelectedListener;
+
+    private int mFirstDayOfWeek;
+
+    public DayPickerAdapter(Context context) {
+        final TypedArray ta = context.obtainStyledAttributes(new int[] {
+                com.android.internal.R.attr.colorControlHighlight});
+        mDayHighlightColor = ta.getColorStateList(0);
+        ta.recycle();
+    }
+
+    public void setRange(Calendar min, Calendar max) {
+        mMinDate.setTimeInMillis(min.getTimeInMillis());
+        mMaxDate.setTimeInMillis(max.getTimeInMillis());
+
+        // Positions are now invalid, clear everything and start over.
+        notifyDataSetChanged();
+    }
+
+    /**
+     * Sets the first day of the week.
+     *
+     * @param weekStart which day the week should start on, valid values are
+     *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
+     */
+    public void setFirstDayOfWeek(int weekStart) {
+        mFirstDayOfWeek = weekStart;
+
+        // Update displayed views.
+        final int count = mItems.size();
+        for (int i = 0; i < count; i++) {
+            final SimpleMonthView monthView = mItems.valueAt(i);
+            monthView.setFirstDayOfWeek(weekStart);
+        }
+    }
+
+    public int getFirstDayOfWeek() {
+        return mFirstDayOfWeek;
+    }
+
+    /**
+     * Sets the selected day.
+     *
+     * @param day the selected day
+     */
+    public void setSelectedDay(Calendar day) {
+        final int oldPosition = getPositionForDay(mSelectedDay);
+        final int newPosition = getPositionForDay(day);
+
+        // Clear the old position if necessary.
+        if (oldPosition != newPosition) {
+            final SimpleMonthView oldMonthView = mItems.get(oldPosition, null);
+            if (oldMonthView != null) {
+                oldMonthView.setSelectedDay(-1);
+            }
+        }
+
+        // Set the new position.
+        final SimpleMonthView newMonthView = mItems.get(newPosition, null);
+        if (newMonthView != null) {
+            final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
+            newMonthView.setSelectedDay(dayOfMonth);
+        }
+
+        mSelectedDay = day;
+    }
+
+    /**
+     * Sets the listener to call when the user selects a day.
+     *
+     * @param listener The listener to call.
+     */
+    public void setOnDaySelectedListener(OnDaySelectedListener listener) {
+        mOnDaySelectedListener = listener;
+    }
+
+    void setCalendarTextColor(ColorStateList calendarTextColor) {
+        mCalendarTextColor = calendarTextColor;
+    }
+
+    void setDaySelectorColor(ColorStateList selectorColor) {
+        mDaySelectorColor = selectorColor;
+    }
+
+    void setMonthTextAppearance(int resId) {
+        mMonthTextAppearance = resId;
+    }
+
+    void setDayOfWeekTextAppearance(int resId) {
+        mDayOfWeekTextAppearance = resId;
+    }
+
+    int getDayOfWeekTextAppearance() {
+        return mDayOfWeekTextAppearance;
+    }
+
+    void setDayTextAppearance(int resId) {
+        mDayTextAppearance = resId;
+    }
+
+    int getDayTextAppearance() {
+        return mDayTextAppearance;
+    }
+
+    @Override
+    public int getCount() {
+        final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
+        final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
+        return diffMonth + MONTHS_IN_YEAR * diffYear + 1;
+    }
+
+    @Override
+    public boolean isViewFromObject(View view, Object object) {
+        return view == object;
+    }
+
+    private int getMonthForPosition(int position) {
+        return position % MONTHS_IN_YEAR + mMinDate.get(Calendar.MONTH);
+    }
+
+    private int getYearForPosition(int position) {
+        return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR);
+    }
+
+    private int getPositionForDay(Calendar day) {
+        final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
+        final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
+        return yearOffset * MONTHS_IN_YEAR + monthOffset;
+    }
+
+    @Override
+    public Object instantiateItem(ViewGroup container, int position) {
+        final SimpleMonthView v = new SimpleMonthView(container.getContext());
+        v.setOnDayClickListener(mOnDayClickListener);
+        v.setMonthTextAppearance(mMonthTextAppearance);
+        v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
+        v.setDayTextAppearance(mDayTextAppearance);
+
+        if (mDaySelectorColor != null) {
+            v.setDaySelectorColor(mDaySelectorColor);
+        }
+
+        if (mDayHighlightColor != null) {
+            v.setDayHighlightColor(mDayHighlightColor);
+        }
+
+        if (mCalendarTextColor != null) {
+            v.setMonthTextColor(mCalendarTextColor);
+            v.setDayOfWeekTextColor(mCalendarTextColor);
+            v.setDayTextColor(mCalendarTextColor);
+        }
+
+        final int month = getMonthForPosition(position);
+        final int year = getYearForPosition(position);
+
+        final int selectedDay;
+        if (mSelectedDay.get(Calendar.MONTH) == month) {
+            selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
+        } else {
+            selectedDay = -1;
+        }
+
+        final int enabledDayRangeStart;
+        if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) {
+            enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
+        } else {
+            enabledDayRangeStart = 1;
+        }
+
+        final int enabledDayRangeEnd;
+        if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
+            enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
+        } else {
+            enabledDayRangeEnd = 31;
+        }
+
+        v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
+                enabledDayRangeStart, enabledDayRangeEnd);
+
+        mItems.put(position, v);
+
+        container.addView(v);
+
+        return v;
+    }
+
+    @Override
+    public void destroyItem(ViewGroup container, int position, Object object) {
+        container.removeView(mItems.get(position));
+
+        mItems.remove(position);
+    }
+
+    @Override
+    public int getItemPosition(Object object) {
+        final int index = mItems.indexOfValue((SimpleMonthView) object);
+        if (index < 0) {
+            return mItems.keyAt(index);
+        }
+        return -1;
+    }
+
+    @Override
+    public CharSequence getPageTitle(int position) {
+        final SimpleMonthView v = mItems.get(position);
+        if (v != null) {
+            return v.getTitle();
+        }
+        return null;
+    }
+
+    private boolean isCalendarInRange(Calendar value) {
+        return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
+    }
+
+    private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
+        @Override
+        public void onDayClick(SimpleMonthView view, Calendar day) {
+            if (day != null && isCalendarInRange(day)) {
+                setSelectedDay(day);
+
+                if (mOnDaySelectedListener != null) {
+                    mOnDaySelectedListener.onDaySelected(DayPickerAdapter.this, day);
+                }
+            }
+        }
+    };
+
+    public interface OnDaySelectedListener {
+        public void onDaySelected(DayPickerAdapter view, Calendar day);
+    }
+}
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 65af45d..a7ae926 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -16,87 +16,177 @@
 
 package android.widget;
 
+import com.android.internal.widget.ViewPager;
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.util.Log;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
 import android.util.MathUtils;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
 
-import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 
+import libcore.icu.LocaleData;
+
 /**
  * This displays a list of months in a calendar format with selectable days.
  */
-class DayPickerView extends ListView implements AbsListView.OnScrollListener {
-    private static final String TAG = "DayPickerView";
+class DayPickerView extends ViewPager {
+    private static final int DEFAULT_START_YEAR = 1900;
+    private static final int DEFAULT_END_YEAR = 2100;
 
-    // How long the GoTo fling animation should last
-    private static final int GOTO_SCROLL_DURATION = 250;
+    private final Calendar mSelectedDay = Calendar.getInstance();
+    private final Calendar mMinDate = Calendar.getInstance();
+    private final Calendar mMaxDate = Calendar.getInstance();
 
-    // How long to wait after receiving an onScrollStateChanged notification before acting on it
-    private static final int SCROLL_CHANGE_DELAY = 40;
+    private final DayPickerAdapter mAdapter;
 
-    // so that the top line will be under the separator
-    private static final int LIST_TOP_OFFSET = -1;
-
-    private final SimpleMonthAdapter mAdapter = new SimpleMonthAdapter(getContext());
-
-    private final ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(this);
-
-    private SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault());
-
-    // highlighted time
-    private Calendar mSelectedDay = Calendar.getInstance();
-    private Calendar mTempDay = Calendar.getInstance();
-    private Calendar mMinDate = Calendar.getInstance();
-    private Calendar mMaxDate = Calendar.getInstance();
-
+    /** Temporary calendar used for date calculations. */
     private Calendar mTempCalendar;
 
     private OnDaySelectedListener mOnDaySelectedListener;
 
-    // which month should be displayed/highlighted [0-11]
-    private int mCurrentMonthDisplayed;
-    // used for tracking what state listview is in
-    private int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-    // used for tracking what state listview is in
-    private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
-    private boolean mPerformingScroll;
-
     public DayPickerView(Context context) {
-        super(context);
+        this(context, null);
+    }
+
+    public DayPickerView(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.calendarViewStyle);
+    }
+
+    public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.CalendarView, defStyleAttr, defStyleRes);
+
+        final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
+                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
+
+        final String minDate = a.getString(R.styleable.CalendarView_minDate);
+        final String maxDate = a.getString(R.styleable.CalendarView_maxDate);
+
+        final int monthTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_monthTextAppearance,
+                R.style.TextAppearance_Material_Widget_Calendar_Month);
+        final int dayOfWeekTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_weekDayTextAppearance,
+                R.style.TextAppearance_Material_Widget_Calendar_DayOfWeek);
+        final int dayTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_dateTextAppearance,
+                R.style.TextAppearance_Material_Widget_Calendar_Day);
+
+        final ColorStateList daySelectorColor = a.getColorStateList(
+                R.styleable.CalendarView_daySelectorColor);
+
+        a.recycle();
+
+        // Set up adapter.
+        mAdapter = new DayPickerAdapter(context);
+        mAdapter.setMonthTextAppearance(monthTextAppearanceResId);
+        mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId);
+        mAdapter.setDayTextAppearance(dayTextAppearanceResId);
+        mAdapter.setDaySelectorColor(daySelectorColor);
 
         setAdapter(mAdapter);
-        setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-        setDrawSelectorOnTop(false);
-        setUpListView();
 
-        goTo(mSelectedDay.getTimeInMillis(), false, false, true);
+        // Set up min and max dates.
+        final Calendar tempDate = Calendar.getInstance();
+        if (!CalendarView.parseDate(minDate, tempDate)) {
+            tempDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
+        }
+        final long minDateMillis = tempDate.getTimeInMillis();
 
-        mAdapter.setOnDaySelectedListener(mProxyOnDaySelectedListener);
+        if (!CalendarView.parseDate(maxDate, tempDate)) {
+            tempDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
+        }
+        final long maxDateMillis = tempDate.getTimeInMillis();
+
+        if (maxDateMillis < minDateMillis) {
+            throw new IllegalArgumentException("maxDate must be >= minDate");
+        }
+
+        final long setDateMillis = MathUtils.constrain(
+                System.currentTimeMillis(), minDateMillis, maxDateMillis);
+
+        setFirstDayOfWeek(firstDayOfWeek);
+        setMinDate(minDateMillis);
+        setMaxDate(maxDateMillis);
+        setDate(setDateMillis, false);
+
+        // Proxy selection callbacks to our own listener.
+        mAdapter.setOnDaySelectedListener(new DayPickerAdapter.OnDaySelectedListener() {
+            @Override
+            public void onDaySelected(DayPickerAdapter adapter, Calendar day) {
+                if (mOnDaySelectedListener != null) {
+                    mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
+                }
+            }
+        });
+    }
+
+    public void setDayOfWeekTextAppearance(int resId) {
+        mAdapter.setDayOfWeekTextAppearance(resId);
+    }
+
+    public int getDayOfWeekTextAppearance() {
+        return mAdapter.getDayOfWeekTextAppearance();
+    }
+
+    public void setDayTextAppearance(int resId) {
+        mAdapter.setDayTextAppearance(resId);
+    }
+
+    public int getDayTextAppearance() {
+        return mAdapter.getDayTextAppearance();
     }
 
     /**
      * Sets the currently selected date to the specified timestamp. Jumps
      * immediately to the new date. To animate to the new date, use
-     * {@link #setDate(long, boolean, boolean)}.
+     * {@link #setDate(long, boolean)}.
      *
-     * @param timeInMillis
+     * @param timeInMillis the target day in milliseconds
      */
     public void setDate(long timeInMillis) {
-        setDate(timeInMillis, false, true);
+        setDate(timeInMillis, false);
     }
 
-    public void setDate(long timeInMillis, boolean animate, boolean forceScroll) {
-        goTo(timeInMillis, animate, true, forceScroll);
+    /**
+     * Sets the currently selected date to the specified timestamp. Jumps
+     * immediately to the new date, optionally animating the transition.
+     *
+     * @param timeInMillis the target day in milliseconds
+     * @param animate whether to smooth scroll to the new position
+     */
+    public void setDate(long timeInMillis, boolean animate) {
+        setDate(timeInMillis, animate, true);
+    }
+
+    /**
+     * Moves to the month containing the specified day, optionally setting the
+     * day as selected.
+     *
+     * @param timeInMillis the target day in milliseconds
+     * @param animate whether to smooth scroll to the new position
+     * @param setSelected whether to set the specified day as selected
+     */
+    private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
+        // Set the selected day
+        if (setSelected) {
+            mSelectedDay.setTimeInMillis(timeInMillis);
+        }
+
+        final int position = getPositionFromDay(timeInMillis);
+        if (position != getCurrentItem()) {
+            setCurrentItem(position, animate);
+        }
     }
 
     public long getDate() {
@@ -137,7 +227,7 @@
 
         // Changing the min/max date changes the selection position since we
         // don't really have stable IDs. Jumps immediately to the new position.
-        goTo(mSelectedDay.getTimeInMillis(), false, false, true);
+        setDate(mSelectedDay.getTimeInMillis(), false, false);
     }
 
     /**
@@ -149,30 +239,9 @@
         mOnDaySelectedListener = listener;
     }
 
-    /*
-     * Sets all the required fields for the list view. Override this method to
-     * set a different list view behavior.
-     */
-    private void setUpListView() {
-        // Transparent background on scroll
-        setCacheColorHint(0);
-        // No dividers
-        setDivider(null);
-        // Items are clickable
-        setItemsCanFocus(true);
-        // The thumb gets in the way, so disable it
-        setFastScrollEnabled(false);
-        setVerticalScrollBarEnabled(false);
-        setOnScrollListener(this);
-        setFadingEdgeLength(0);
-        // Make the scrolling behavior nicer
-        setFriction(ViewConfiguration.getScrollFriction());
-    }
-
     private int getDiffMonths(Calendar start, Calendar end) {
         final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
-        final int diffMonths = end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
-        return diffMonths;
+        return end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
     }
 
     private int getPositionFromDay(long timeInMillis) {
@@ -190,366 +259,13 @@
     }
 
     /**
-     * This moves to the specified time in the view. If the time is not already
-     * in range it will move the list so that the first of the month containing
-     * the time is at the top of the view. If the new time is already in view
-     * the list will not be scrolled unless forceScroll is true. This time may
-     * optionally be highlighted as selected as well.
-     *
-     * @param day The day to move to
-     * @param animate Whether to scroll to the given time or just redraw at the
-     *            new location
-     * @param setSelected Whether to set the given time as selected
-     * @param forceScroll Whether to recenter even if the time is already
-     *            visible
-     * @return Whether or not the view animated to the new location
-     */
-    private boolean goTo(long day, boolean animate, boolean setSelected, boolean forceScroll) {
-
-        // Set the selected day
-        if (setSelected) {
-            mSelectedDay.setTimeInMillis(day);
-        }
-
-        mTempDay.setTimeInMillis(day);
-        final int position = getPositionFromDay(day);
-
-        View child;
-        int i = 0;
-        int top = 0;
-        // Find a child that's completely in the view
-        do {
-            child = getChildAt(i++);
-            if (child == null) {
-                break;
-            }
-            top = child.getTop();
-        } while (top < 0);
-
-        // Compute the first and last position visible
-        int selectedPosition;
-        if (child != null) {
-            selectedPosition = getPositionForView(child);
-        } else {
-            selectedPosition = 0;
-        }
-
-        if (setSelected) {
-            mAdapter.setSelectedDay(mSelectedDay);
-        }
-
-        // Check if the selected day is now outside of our visible range
-        // and if so scroll to the month that contains it
-        if (position != selectedPosition || forceScroll) {
-            setMonthDisplayed(mTempDay);
-            mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
-            if (animate) {
-                smoothScrollToPositionFromTop(
-                        position, LIST_TOP_OFFSET, GOTO_SCROLL_DURATION);
-                return true;
-            } else {
-                postSetSelection(position);
-            }
-        } else if (setSelected) {
-            setMonthDisplayed(mSelectedDay);
-        }
-        return false;
-    }
-
-    public void postSetSelection(final int position) {
-        clearFocus();
-        post(new Runnable() {
-
-            @Override
-            public void run() {
-                setSelection(position);
-            }
-        });
-        onScrollStateChanged(this, OnScrollListener.SCROLL_STATE_IDLE);
-    }
-
-    /**
-     * Updates the title and selected month if the view has moved to a new
-     * month.
-     */
-    @Override
-    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
-                         int totalItemCount) {
-        SimpleMonthView child = (SimpleMonthView) view.getChildAt(0);
-        if (child == null) {
-            return;
-        }
-
-        mPreviousScrollState = mCurrentScrollState;
-    }
-
-    /**
-     * Sets the month displayed at the top of this view based on time. Override
-     * to add custom events when the title is changed.
-     */
-    protected void setMonthDisplayed(Calendar date) {
-        if (mCurrentMonthDisplayed != date.get(Calendar.MONTH)) {
-            mCurrentMonthDisplayed = date.get(Calendar.MONTH);
-            invalidateViews();
-        }
-    }
-
-    @Override
-    public void onScrollStateChanged(AbsListView view, int scrollState) {
-        // use a post to prevent re-entering onScrollStateChanged before it
-        // exits
-        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
-    }
-
-    void setCalendarTextColor(ColorStateList colors) {
-        mAdapter.setCalendarTextColor(colors);
-    }
-
-    void setCalendarDayBackgroundColor(ColorStateList dayBackgroundColor) {
-        mAdapter.setCalendarDayBackgroundColor(dayBackgroundColor);
-    }
-
-    void setCalendarTextAppearance(int resId) {
-        mAdapter.setCalendarTextAppearance(resId);
-    }
-
-    protected class ScrollStateRunnable implements Runnable {
-        private int mNewState;
-        private View mParent;
-
-        ScrollStateRunnable(View view) {
-            mParent = view;
-        }
-
-        /**
-         * Sets up the runnable with a short delay in case the scroll state
-         * immediately changes again.
-         *
-         * @param view The list view that changed state
-         * @param scrollState The new state it changed to
-         */
-        public void doScrollStateChange(AbsListView view, int scrollState) {
-            mParent.removeCallbacks(this);
-            mNewState = scrollState;
-            mParent.postDelayed(this, SCROLL_CHANGE_DELAY);
-        }
-
-        @Override
-        public void run() {
-            mCurrentScrollState = mNewState;
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG,
-                        "new scroll state: " + mNewState + " old state: " + mPreviousScrollState);
-            }
-            // Fix the position after a scroll or a fling ends
-            if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
-                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE
-                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
-                mPreviousScrollState = mNewState;
-                int i = 0;
-                View child = getChildAt(i);
-                while (child != null && child.getBottom() <= 0) {
-                    child = getChildAt(++i);
-                }
-                if (child == null) {
-                    // The view is no longer visible, just return
-                    return;
-                }
-                int firstPosition = getFirstVisiblePosition();
-                int lastPosition = getLastVisiblePosition();
-                boolean scroll = firstPosition != 0 && lastPosition != getCount() - 1;
-                final int top = child.getTop();
-                final int bottom = child.getBottom();
-                final int midpoint = getHeight() / 2;
-                if (scroll && top < LIST_TOP_OFFSET) {
-                    if (bottom > midpoint) {
-                        smoothScrollBy(top, GOTO_SCROLL_DURATION);
-                    } else {
-                        smoothScrollBy(bottom, GOTO_SCROLL_DURATION);
-                    }
-                }
-            } else {
-                mPreviousScrollState = mNewState;
-            }
-        }
-    }
-
-    /**
      * Gets the position of the view that is most prominently displayed within the list view.
      */
     public int getMostVisiblePosition() {
-        final int firstPosition = getFirstVisiblePosition();
-        final int height = getHeight();
-
-        int maxDisplayedHeight = 0;
-        int mostVisibleIndex = 0;
-        int i=0;
-        int bottom = 0;
-        while (bottom < height) {
-            View child = getChildAt(i);
-            if (child == null) {
-                break;
-            }
-            bottom = child.getBottom();
-            int displayedHeight = Math.min(bottom, height) - Math.max(0, child.getTop());
-            if (displayedHeight > maxDisplayedHeight) {
-                mostVisibleIndex = i;
-                maxDisplayedHeight = displayedHeight;
-            }
-            i++;
-        }
-        return firstPosition + mostVisibleIndex;
-    }
-
-    /**
-     * Attempts to return the date that has accessibility focus.
-     *
-     * @return The date that has accessibility focus, or {@code null} if no date
-     *         has focus.
-     */
-    private Calendar findAccessibilityFocus() {
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            if (child instanceof SimpleMonthView) {
-                final Calendar focus = ((SimpleMonthView) child).getAccessibilityFocus();
-                if (focus != null) {
-                    return focus;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Attempts to restore accessibility focus to a given date. No-op if
-     * {@code day} is {@code null}.
-     *
-     * @param day The date that should receive accessibility focus
-     * @return {@code true} if focus was restored
-     */
-    private boolean restoreAccessibilityFocus(Calendar day) {
-        if (day == null) {
-            return false;
-        }
-
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            if (child instanceof SimpleMonthView) {
-                if (((SimpleMonthView) child).restoreAccessibilityFocus(day)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    protected void layoutChildren() {
-        final Calendar focusedDay = findAccessibilityFocus();
-        super.layoutChildren();
-        if (mPerformingScroll) {
-            mPerformingScroll = false;
-        } else {
-            restoreAccessibilityFocus(focusedDay);
-        }
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault());
-    }
-
-    /** @hide */
-    @Override
-    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEventInternal(event);
-        event.setItemCount(-1);
-    }
-
-    private String getMonthAndYearString(Calendar day) {
-        final StringBuilder sbuf = new StringBuilder();
-        sbuf.append(day.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault()));
-        sbuf.append(" ");
-        sbuf.append(mYearFormat.format(day.getTime()));
-        return sbuf.toString();
-    }
-
-    /**
-     * Necessary for accessibility, to ensure we support "scrolling" forward and backward
-     * in the month list.
-     *
-     * @hide
-     */
-    @Override
-    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
-        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
-    }
-
-    /**
-     * When scroll forward/backward events are received, announce the newly scrolled-to month.
-     *
-     * @hide
-     */
-    @Override
-    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
-        if (action != AccessibilityNodeInfo.ACTION_SCROLL_FORWARD &&
-                action != AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
-            return super.performAccessibilityActionInternal(action, arguments);
-        }
-
-        // Figure out what month is showing.
-        final int firstVisiblePosition = getFirstVisiblePosition();
-        final int month = firstVisiblePosition % 12;
-        final int year = firstVisiblePosition / 12 + mMinDate.get(Calendar.YEAR);
-        final Calendar day = Calendar.getInstance();
-        day.set(year, month, 1);
-
-        // Scroll either forward or backward one month.
-        if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
-            day.add(Calendar.MONTH, 1);
-            if (day.get(Calendar.MONTH) == 12) {
-                day.set(Calendar.MONTH, 0);
-                day.add(Calendar.YEAR, 1);
-            }
-        } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
-            View firstVisibleView = getChildAt(0);
-            // If the view is fully visible, jump one month back. Otherwise, we'll just jump
-            // to the first day of first visible month.
-            if (firstVisibleView != null && firstVisibleView.getTop() >= -1) {
-                // There's an off-by-one somewhere, so the top of the first visible item will
-                // actually be -1 when it's at the exact top.
-                day.add(Calendar.MONTH, -1);
-                if (day.get(Calendar.MONTH) == -1) {
-                    day.set(Calendar.MONTH, 11);
-                    day.add(Calendar.YEAR, -1);
-                }
-            }
-        }
-
-        // Go to that month.
-        announceForAccessibility(getMonthAndYearString(day));
-        goTo(day.getTimeInMillis(), true, false, true);
-        mPerformingScroll = true;
-        return true;
+        return getCurrentItem();
     }
 
     public interface OnDaySelectedListener {
         public void onDaySelected(DayPickerView view, Calendar day);
     }
-
-    private final SimpleMonthAdapter.OnDaySelectedListener
-            mProxyOnDaySelectedListener = new SimpleMonthAdapter.OnDaySelectedListener() {
-        @Override
-        public void onDaySelected(SimpleMonthAdapter adapter, Calendar day) {
-            if (mOnDaySelectedListener != null) {
-                mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
-            }
-        }
-    };
 }
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index d85bbb9..310412f9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -567,13 +567,11 @@
     public void show() {
         int height = buildDropDown();
 
-        int widthSpec = 0;
-        int heightSpec = 0;
-
         boolean noInputMethod = isInputMethodNotNeeded();
         mPopup.setAllowScrollingAnchorParent(!noInputMethod);
 
         if (mPopup.isShowing()) {
+            final int widthSpec;
             if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
                 // The call to PopupWindow's update method below can accept -1 for any
                 // value you do not want to update.
@@ -584,19 +582,19 @@
                 widthSpec = mDropDownWidth;
             }
 
+            final int heightSpec;
             if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
                 // The call to PopupWindow's update method below can accept -1 for any
                 // value you do not want to update.
                 heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT;
                 if (noInputMethod) {
-                    mPopup.setWindowLayoutMode(
-                            mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
-                                    ViewGroup.LayoutParams.MATCH_PARENT : 0, 0);
+                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
+                            ViewGroup.LayoutParams.MATCH_PARENT : 0);
+                    mPopup.setHeight(0);
                 } else {
-                    mPopup.setWindowLayoutMode(
-                            mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
-                                    ViewGroup.LayoutParams.MATCH_PARENT : 0,
-                            ViewGroup.LayoutParams.MATCH_PARENT);
+                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
+                                    ViewGroup.LayoutParams.MATCH_PARENT : 0);
+                    mPopup.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
                 }
             } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
                 heightSpec = height;
@@ -604,32 +602,37 @@
                 heightSpec = mDropDownHeight;
             }
 
+            mPopup.setWidth(widthSpec);
+            mPopup.setHeight(heightSpec);
             mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
 
             mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
-                    mDropDownVerticalOffset, widthSpec, heightSpec);
+                            mDropDownVerticalOffset, -1, -1);
         } else {
+            final int widthSpec;
             if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
                 widthSpec = ViewGroup.LayoutParams.MATCH_PARENT;
             } else {
                 if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
-                    mPopup.setWidth(getAnchorView().getWidth());
+                    widthSpec = getAnchorView().getWidth();
                 } else {
-                    mPopup.setWidth(mDropDownWidth);
+                    widthSpec = mDropDownWidth;
                 }
             }
 
+            final int heightSpec;
             if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
                 heightSpec = ViewGroup.LayoutParams.MATCH_PARENT;
             } else {
                 if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
-                    mPopup.setHeight(height);
+                    heightSpec = height;
                 } else {
-                    mPopup.setHeight(mDropDownHeight);
+                    heightSpec = mDropDownHeight;
                 }
             }
 
-            mPopup.setWindowLayoutMode(widthSpec, heightSpec);
+            mPopup.setWidth(widthSpec);
+            mPopup.setHeight(heightSpec);
             mPopup.setClipToScreenEnabled(true);
             
             // use outside touchable to dismiss drop down when touching outside of it, so
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index f676254..8792323 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -46,6 +46,7 @@
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.ViewTreeObserver.OnScrollChangedListener;
 import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 
 import java.lang.ref.WeakReference;
 
@@ -126,10 +127,10 @@
     private OnTouchListener mTouchInterceptor;
 
     private int mWidthMode;
-    private int mWidth;
+    private int mWidth = LayoutParams.WRAP_CONTENT;
     private int mLastWidth;
     private int mHeightMode;
-    private int mHeight;
+    private int mHeight = LayoutParams.WRAP_CONTENT;
     private int mLastHeight;
 
     private int mPopupWidth;
@@ -907,17 +908,19 @@
      * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
      * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
      * height.
+     *
+     * @deprecated Use {@link #setWidth(int)} and {@link #setHeight(int)}.
      */
+    @Deprecated
     public void setWindowLayoutMode(int widthSpec, int heightSpec) {
         mWidthMode = widthSpec;
         mHeightMode = heightSpec;
     }
 
     /**
-     * <p>Return this popup's height MeasureSpec</p>
+     * Returns the popup's height MeasureSpec.
      *
      * @return the height MeasureSpec of the popup
-     *
      * @see #setHeight(int)
      */
     public int getHeight() {
@@ -925,13 +928,12 @@
     }
 
     /**
-     * <p>Change the popup's height MeasureSpec</p>
-     *
-     * <p>If the popup is showing, calling this method will take effect only
-     * the next time the popup is shown.</p>
+     * Sets the popup's height MeasureSpec.
+     * <p>
+     * If the popup is showing, calling this method will take effect the next
+     * time the popup is shown.
      *
      * @param height the height MeasureSpec of the popup
-     *
      * @see #getHeight()
      * @see #isShowing()
      */
@@ -940,10 +942,9 @@
     }
 
     /**
-     * <p>Return this popup's width MeasureSpec</p>
+     * Returns the popup's width MeasureSpec.
      *
      * @return the width MeasureSpec of the popup
-     *
      * @see #setWidth(int)
      */
     public int getWidth() {
@@ -951,13 +952,12 @@
     }
 
     /**
-     * <p>Change the popup's width MeasureSpec</p>
-     *
-     * <p>If the popup is showing, calling this method will take effect only
-     * the next time the popup is shown.</p>
+     * Sets the popup's width MeasureSpec.
+     * <p>
+     * If the popup is showing, calling this method will take effect the next
+     * time the popup is shown.
      *
      * @param width the width MeasureSpec of the popup
-     *
      * @see #getWidth()
      * @see #isShowing()
      */
@@ -1658,10 +1658,17 @@
 
     /**
      * Updates the state of the popup window, if it is currently being displayed,
-     * from the currently set state.  This includes:
-     * {@link #setClippingEnabled(boolean)}, {@link #setFocusable(boolean)},
-     * {@link #setIgnoreCheekPress()}, {@link #setInputMethodMode(int)},
-     * {@link #setTouchable(boolean)}, and {@link #setAnimationStyle(int)}.
+     * from the currently set state.
+     * <p>
+     * This includes:
+     * <ul>
+     *     <li>{@link #setClippingEnabled(boolean)}</li>
+     *     <li>{@link #setFocusable(boolean)}</li>
+     *     <li>{@link #setIgnoreCheekPress()}</li>
+     *     <li>{@link #setInputMethodMode(int)}</li>
+     *     <li>{@link #setTouchable(boolean)}</li>
+     *     <li>{@link #setAnimationStyle(int)}</li>
+     * </ul>
      */
     public void update() {
         if (!isShowing() || mContentView == null) {
@@ -1692,12 +1699,13 @@
     }
 
     /**
-     * <p>Updates the dimension of the popup window. Calling this function
-     * also updates the window with the current popup state as described
-     * for {@link #update()}.</p>
+     * Updates the dimension of the popup window.
+     * <p>
+     * Calling this function also updates the window with the current popup
+     * state as described for {@link #update()}.
      *
-     * @param width the new width
-     * @param height the new height
+     * @param width the new width, must be >= 0 or -1 to ignore
+     * @param height the new height, must be >= 0 or -1 to ignore
      */
     public void update(int width, int height) {
         final WindowManager.LayoutParams p =
@@ -1706,40 +1714,43 @@
     }
 
     /**
-     * <p>Updates the position and the dimension of the popup window. Width and
-     * height can be set to -1 to update location only.  Calling this function
-     * also updates the window with the current popup state as
-     * described for {@link #update()}.</p>
+     * Updates the position and the dimension of the popup window.
+     * <p>
+     * Width and height can be set to -1 to update location only. Calling this
+     * function also updates the window with the current popup state as
+     * described for {@link #update()}.
      *
      * @param x the new x location
      * @param y the new y location
-     * @param width the new width, can be -1 to ignore
-     * @param height the new height, can be -1 to ignore
+     * @param width the new width, must be >= 0 or -1 to ignore
+     * @param height the new height, must be >= 0 or -1 to ignore
      */
     public void update(int x, int y, int width, int height) {
         update(x, y, width, height, false);
     }
 
     /**
-     * <p>Updates the position and the dimension of the popup window. Width and
-     * height can be set to -1 to update location only.  Calling this function
-     * also updates the window with the current popup state as
-     * described for {@link #update()}.</p>
+     * Updates the position and the dimension of the popup window.
+     * <p>
+     * Width and height can be set to -1 to update location only. Calling this
+     * function also updates the window with the current popup state as
+     * described for {@link #update()}.
      *
      * @param x the new x location
      * @param y the new y location
-     * @param width the new width, can be -1 to ignore
-     * @param height the new height, can be -1 to ignore
-     * @param force reposition the window even if the specified position
-     *              already seems to correspond to the LayoutParams
+     * @param width the new width, must be >= 0 or -1 to ignore
+     * @param height the new height, must be >= 0 or -1 to ignore
+     * @param force {@code true} to reposition the window even if the specified
+     *              position already seems to correspond to the LayoutParams,
+     *              {@code false} to only reposition if needed
      */
     public void update(int x, int y, int width, int height, boolean force) {
-        if (width != -1) {
+        if (width >= 0) {
             mLastWidth = width;
             setWidth(width);
         }
 
-        if (height != -1) {
+        if (height >= 0) {
             mLastHeight = height;
             setHeight(height);
         }
@@ -1794,32 +1805,34 @@
     }
 
     /**
-     * <p>Updates the position and the dimension of the popup window. Calling this
-     * function also updates the window with the current popup state as described
-     * for {@link #update()}.</p>
+     * Updates the position and the dimension of the popup window.
+     * <p>
+     * Calling this function also updates the window with the current popup
+     * state as described for {@link #update()}.
      *
      * @param anchor the popup's anchor view
-     * @param width the new width, can be -1 to ignore
-     * @param height the new height, can be -1 to ignore
+     * @param width the new width, must be >= 0 or -1 to ignore
+     * @param height the new height, must be >= 0 or -1 to ignore
      */
     public void update(View anchor, int width, int height) {
         update(anchor, false, 0, 0, true, width, height);
     }
 
     /**
-     * <p>Updates the position and the dimension of the popup window. Width and
-     * height can be set to -1 to update location only.  Calling this function
-     * also updates the window with the current popup state as
-     * described for {@link #update()}.</p>
-     *
-     * <p>If the view later scrolls to move <code>anchor</code> to a different
-     * location, the popup will be moved correspondingly.</p>
+     * Updates the position and the dimension of the popup window.
+     * <p>
+     * Width and height can be set to -1 to update location only. Calling this
+     * function also updates the window with the current popup state as
+     * described for {@link #update()}.
+     * <p>
+     * If the view later scrolls to move {@code anchor} to a different
+     * location, the popup will be moved correspondingly.
      *
      * @param anchor the popup's anchor view
      * @param xoff x offset from the view's left edge
      * @param yoff y offset from the view's bottom edge
-     * @param width the new width, can be -1 to ignore
-     * @param height the new height, can be -1 to ignore
+     * @param width the new width, must be >= 0 or -1 to ignore
+     * @param height the new height, must be >= 0 or -1 to ignore
      */
     public void update(View anchor, int xoff, int yoff, int width, int height) {
         update(anchor, true, xoff, yoff, true, width, height);
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 28b4db2..20aa972 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -641,7 +641,7 @@
         mCircleRadius = Math.min(mXCenter, mYCenter);
 
         mMinHypotenuseForInnerNumber = mCircleRadius - mTextInset[HOURS_INNER] - mSelectorRadius;
-        mMaxHypotenuseForOuterNumber = mCircleRadius - mTextInset[HOURS] - mSelectorRadius;
+        mMaxHypotenuseForOuterNumber = mCircleRadius - mTextInset[HOURS] + mSelectorRadius;
         mHalfwayHypotenusePoint = mCircleRadius - (mTextInset[HOURS] + mTextInset[HOURS_INNER]) / 2;
 
         calculatePositionsHours();
@@ -1144,30 +1144,31 @@
 
         private void adjustPicker(int step) {
             final int stepSize;
-            final int initialValue;
+            final int initialStep;
             final int maxValue;
             final int minValue;
             if (mShowHours) {
-                stepSize = DEGREES_FOR_ONE_HOUR;
-                initialValue = getCurrentHour() % 12;
+                stepSize = 1;
 
+                final int currentHour24 = getCurrentHour();
                 if (mIs24HourMode) {
-                    maxValue = 23;
+                    initialStep = currentHour24;
                     minValue = 0;
+                    maxValue = 23;
                 } else {
-                    maxValue = 12;
+                    initialStep = hour24To12(currentHour24);
                     minValue = 1;
+                    maxValue = 12;
                 }
             } else {
-                stepSize = DEGREES_FOR_ONE_MINUTE;
-                initialValue = getCurrentMinute();
-
-                maxValue = 55;
+                stepSize = 5;
+                initialStep = getCurrentMinute() / stepSize;
                 minValue = 0;
+                maxValue = 55;
             }
 
-            final int steppedValue = snapOnly30s(initialValue * stepSize, step) / stepSize;
-            final int clampedValue = MathUtils.constrain(steppedValue, minValue, maxValue);
+            final int nextValue = (initialStep + step) * stepSize;
+            final int clampedValue = MathUtils.constrain(nextValue, minValue, maxValue);
             if (mShowHours) {
                 setCurrentHour(clampedValue);
             } else {
diff --git a/core/java/android/widget/SimpleMonthAdapter.java b/core/java/android/widget/SimpleMonthAdapter.java
deleted file mode 100644
index c807d56..0000000
--- a/core/java/android/widget/SimpleMonthAdapter.java
+++ /dev/null
@@ -1,220 +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.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SimpleMonthView.OnDayClickListener;
-
-import java.util.Calendar;
-
-/**
- * An adapter for a list of {@link android.widget.SimpleMonthView} items.
- */
-class SimpleMonthAdapter extends BaseAdapter {
-    private final Calendar mMinDate = Calendar.getInstance();
-    private final Calendar mMaxDate = Calendar.getInstance();
-
-    private final Context mContext;
-
-    private Calendar mSelectedDay = Calendar.getInstance();
-    private ColorStateList mCalendarTextColors = ColorStateList.valueOf(Color.BLACK);
-    private ColorStateList mCalendarDayBackgroundColor = ColorStateList.valueOf(Color.MAGENTA);
-    private OnDaySelectedListener mOnDaySelectedListener;
-
-    private int mFirstDayOfWeek;
-
-    public SimpleMonthAdapter(Context context) {
-        mContext = context;
-    }
-
-    public void setRange(Calendar min, Calendar max) {
-        mMinDate.setTimeInMillis(min.getTimeInMillis());
-        mMaxDate.setTimeInMillis(max.getTimeInMillis());
-
-        notifyDataSetInvalidated();
-    }
-
-    public void setFirstDayOfWeek(int firstDayOfWeek) {
-        mFirstDayOfWeek = firstDayOfWeek;
-
-        notifyDataSetInvalidated();
-    }
-
-    public int getFirstDayOfWeek() {
-        return mFirstDayOfWeek;
-    }
-
-    /**
-     * Updates the selected day and related parameters.
-     *
-     * @param day The day to highlight
-     */
-    public void setSelectedDay(Calendar day) {
-        mSelectedDay = day;
-
-        notifyDataSetChanged();
-    }
-
-    /**
-     * Sets the listener to call when the user selects a day.
-     *
-     * @param listener The listener to call.
-     */
-    public void setOnDaySelectedListener(OnDaySelectedListener listener) {
-        mOnDaySelectedListener = listener;
-    }
-
-    void setCalendarTextColor(ColorStateList colors) {
-        mCalendarTextColors = colors;
-    }
-
-    void setCalendarDayBackgroundColor(ColorStateList dayBackgroundColor) {
-        mCalendarDayBackgroundColor = dayBackgroundColor;
-    }
-
-    /**
-     * Sets the text color, size, style, hint color, and highlight color from
-     * the specified TextAppearance resource. This is mostly copied from
-     * {@link TextView#setTextAppearance(Context, int)}.
-     */
-    void setCalendarTextAppearance(int resId) {
-        final TypedArray a = mContext.obtainStyledAttributes(resId, R.styleable.TextAppearance);
-
-        final ColorStateList textColor = a.getColorStateList(R.styleable.TextAppearance_textColor);
-        if (textColor != null) {
-            mCalendarTextColors = textColor;
-        }
-
-        // TODO: Support font size, etc.
-
-        a.recycle();
-    }
-
-    @Override
-    public int getCount() {
-        final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
-        final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
-        return diffMonth + 12 * diffYear + 1;
-    }
-
-    @Override
-    public Object getItem(int position) {
-        return null;
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return position;
-    }
-
-    @Override
-    public boolean hasStableIds() {
-        return true;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        final SimpleMonthView v;
-        if (convertView != null) {
-            v = (SimpleMonthView) convertView;
-        } else {
-            v = new SimpleMonthView(mContext);
-
-            // Set up the new view
-            final AbsListView.LayoutParams params = new AbsListView.LayoutParams(
-                    AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT);
-            v.setLayoutParams(params);
-            v.setClickable(true);
-            v.setOnDayClickListener(mOnDayClickListener);
-
-            v.setMonthTextColor(mCalendarTextColors);
-            v.setDayOfWeekTextColor(mCalendarTextColors);
-            v.setDayTextColor(mCalendarTextColors);
-
-            v.setDayBackgroundColor(mCalendarDayBackgroundColor);
-        }
-
-        final int minMonth = mMinDate.get(Calendar.MONTH);
-        final int minYear = mMinDate.get(Calendar.YEAR);
-        final int currentMonth = position + minMonth;
-        final int month = currentMonth % 12;
-        final int year = currentMonth / 12 + minYear;
-        final int selectedDay;
-        if (isSelectedDayInMonth(year, month)) {
-            selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
-        } else {
-            selectedDay = -1;
-        }
-
-        // Invokes requestLayout() to ensure that the recycled view is set with the appropriate
-        // height/number of weeks before being displayed.
-        v.reuse();
-
-        final int enabledDayRangeStart;
-        if (minMonth == month && minYear == year) {
-            enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
-        } else {
-            enabledDayRangeStart = 1;
-        }
-
-        final int enabledDayRangeEnd;
-        if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
-            enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
-        } else {
-            enabledDayRangeEnd = 31;
-        }
-
-        v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
-                enabledDayRangeStart, enabledDayRangeEnd);
-        v.invalidate();
-
-        return v;
-    }
-
-    private boolean isSelectedDayInMonth(int year, int month) {
-        return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month;
-    }
-
-    private boolean isCalendarInRange(Calendar value) {
-        return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
-    }
-
-    private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
-        @Override
-        public void onDayClick(SimpleMonthView view, Calendar day) {
-            if (day != null && isCalendarInRange(day)) {
-                setSelectedDay(day);
-
-                if (mOnDaySelectedListener != null) {
-                    mOnDaySelectedListener.onDaySelected(SimpleMonthAdapter.this, day);
-                }
-            }
-        }
-    };
-
-    public interface OnDaySelectedListener {
-        public void onDaySelected(SimpleMonthAdapter view, Calendar day);
-    }
-}
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 58ad515..4e5a39a 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Paint.Align;
@@ -29,8 +29,6 @@
 import android.os.Bundle;
 import android.text.TextPaint;
 import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-import android.text.format.Time;
 import android.util.AttributeSet;
 import android.util.IntArray;
 import android.util.StateSet;
@@ -38,13 +36,13 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
 import com.android.internal.R;
 import com.android.internal.widget.ExploreByTouchHelper;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
-import java.util.Formatter;
 import java.util.Locale;
 
 /**
@@ -52,93 +50,80 @@
  * within the specified month.
  */
 class SimpleMonthView extends View {
-    private static final int MIN_ROW_HEIGHT = 10;
+    private static final int DAYS_IN_WEEK = 7;
+    private static final int MAX_WEEKS_IN_MONTH = 6;
 
     private static final int DEFAULT_SELECTED_DAY = -1;
     private static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
-    private static final int DEFAULT_NUM_DAYS = 7;
-    private static final int DEFAULT_NUM_ROWS = 6;
-    private static final int MAX_NUM_ROWS = 6;
 
-    private final Formatter mFormatter;
-    private final StringBuilder mStringBuilder;
-
-    private final int mMonthTextSize;
-    private final int mDayOfWeekTextSize;
-    private final int mDayTextSize;
-
-    /** Height of the header containing the month and day of week labels. */
-    private final int mMonthHeaderHeight;
+    private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
+    private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
 
     private final TextPaint mMonthPaint = new TextPaint();
     private final TextPaint mDayOfWeekPaint = new TextPaint();
     private final TextPaint mDayPaint = new TextPaint();
-
-    private final Paint mDayBackgroundPaint = new Paint();
-
-    /** Single-letter (when available) formatter for the day of week label. */
-    private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault());
-
-    // affects the padding on the sides of this view
-    private int mPadding = 0;
-
-    private String mDayOfWeekTypeface;
-    private String mMonthTypeface;
-
-    private int mMonth;
-    private int mYear;
-
-    // Quick reference to the width of this view, matches parent
-    private int mWidth;
-
-    // The height this view should draw at in pixels, set by height param
-    private final int mRowHeight;
-
-    // If this view contains the today
-    private boolean mHasToday = false;
-
-    // Which day is selected [0-6] or -1 if no day is selected
-    private int mActivatedDay = -1;
-
-    // Which day is today [0-6] or -1 if no day is today
-    private int mToday = DEFAULT_SELECTED_DAY;
-
-    // Which day of the week to start on [0-6]
-    private int mWeekStart = DEFAULT_WEEK_START;
-
-    // How many days to display
-    private int mNumDays = DEFAULT_NUM_DAYS;
-
-    // The number of days + a spot for week number if it is displayed
-    private int mNumCells = mNumDays;
-
-    private int mDayOfWeekStart = 0;
-
-    // First enabled day
-    private int mEnabledDayStart = 1;
-
-    // Last enabled day
-    private int mEnabledDayEnd = 31;
+    private final Paint mDaySelectorPaint = new Paint();
+    private final Paint mDayHighlightPaint = new Paint();
 
     private final Calendar mCalendar = Calendar.getInstance();
     private final Calendar mDayLabelCalendar = Calendar.getInstance();
 
     private final MonthViewTouchHelper mTouchHelper;
 
-    private int mNumRows = DEFAULT_NUM_ROWS;
+    private final SimpleDateFormat mTitleFormatter;
+    private final SimpleDateFormat mDayOfWeekFormatter;
 
-    // Optional listener for handling day click actions
+    private CharSequence mTitle;
+
+    private int mMonth;
+    private int mYear;
+
+    private int mPaddedWidth;
+    private int mPaddedHeight;
+
+    private final int mMonthHeight;
+    private final int mDayOfWeekHeight;
+    private final int mDayHeight;
+    private final int mCellWidth;
+    private final int mDaySelectorRadius;
+
+    /** The day of month for the selected day, or -1 if no day is selected. */
+    private int mActivatedDay = -1;
+
+    /**
+     * The day of month for today, or -1 if the today is not in the current
+     * month.
+     */
+    private int mToday = DEFAULT_SELECTED_DAY;
+
+    /** The first day of the week (ex. Calendar.SUNDAY). */
+    private int mWeekStart = DEFAULT_WEEK_START;
+
+    /** The number of days (ex. 28) in the current month. */
+    private int mDaysInMonth;
+
+    /**
+     * The day of week (ex. Calendar.SUNDAY) for the first day of the current
+     * month.
+     */
+    private int mDayOfWeekStart;
+
+    /** The day of month for the first (inclusive) enabled day. */
+    private int mEnabledDayStart = 1;
+
+    /** The day of month for the last (inclusive) enabled day. */
+    private int mEnabledDayEnd = 31;
+
+    /** The number of week rows needed to display the current month. */
+    private int mNumWeeks = MAX_WEEKS_IN_MONTH;
+
+    /** Optional listener for handling day click actions. */
     private OnDayClickListener mOnDayClickListener;
 
-    // Whether to prevent setting the accessibility delegate
-    private boolean mLockAccessibilityDelegate;
-
-    private int mNormalTextColor;
-    private int mDisabledTextColor;
-    private int mSelectedDayColor;
-
     private ColorStateList mDayTextColor;
 
+    private int mTouchedDay = -1;
+
     public SimpleMonthView(Context context) {
         this(context, null);
     }
@@ -155,64 +140,123 @@
         super(context, attrs, defStyleAttr, defStyleRes);
 
         final Resources res = context.getResources();
-        mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface);
-        mMonthTypeface = res.getString(R.string.sans_serif);
-
-        mStringBuilder = new StringBuilder(50);
-        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
-
-        mDayTextSize = res.getDimensionPixelSize(R.dimen.datepicker_day_number_size);
-        mMonthTextSize = res.getDimensionPixelSize(R.dimen.datepicker_month_label_size);
-        mDayOfWeekTextSize = res.getDimensionPixelSize(
-                R.dimen.datepicker_month_day_label_text_size);
-        mMonthHeaderHeight = res.getDimensionPixelOffset(
-                R.dimen.datepicker_month_list_item_header_height);
-
-        mRowHeight = Math.max(MIN_ROW_HEIGHT,
-                (res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height)
-                        - mMonthHeaderHeight) / MAX_NUM_ROWS);
+        mMonthHeight = res.getDimensionPixelSize(R.dimen.date_picker_month_height);
+        mDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
+        mDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
+        mCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
+        mDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
 
         // Set up accessibility components.
         mTouchHelper = new MonthViewTouchHelper(this);
         setAccessibilityDelegate(mTouchHelper);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-        mLockAccessibilityDelegate = true;
 
-        initPaints();
+        final Locale locale = res.getConfiguration().locale;
+        final String titleFormat = DateFormat.getBestDateTimePattern(locale, DEFAULT_TITLE_FORMAT);
+        mTitleFormatter = new SimpleDateFormat(titleFormat, locale);
+        mDayOfWeekFormatter = new SimpleDateFormat(DAY_OF_WEEK_FORMAT, locale);
+
+        setClickable(true);
+        initPaints(res);
+    }
+
+    /**
+     * Applies the specified text appearance resource to a paint, returning the
+     * text color if one is set in the text appearance.
+     *
+     * @param p the paint to modify
+     * @param resId the resource ID of the text appearance
+     * @return the text color, if available
+     */
+    private ColorStateList applyTextAppearance(Paint p, int resId) {
+        final TypedArray ta = mContext.obtainStyledAttributes(null,
+                R.styleable.TextAppearance, 0, resId);
+
+        final String fontFamily = ta.getString(R.styleable.TextAppearance_fontFamily);
+        if (fontFamily != null) {
+            p.setTypeface(Typeface.create(fontFamily, 0));
+        }
+
+        p.setTextSize(ta.getDimensionPixelSize(
+                R.styleable.TextAppearance_textSize, (int) p.getTextSize()));
+
+        final ColorStateList textColor = ta.getColorStateList(R.styleable.TextAppearance_textColor);
+        if (textColor != null) {
+            final int enabledColor = textColor.getColorForState(ENABLED_STATE_SET, 0);
+            p.setColor(enabledColor);
+        }
+
+        ta.recycle();
+
+        return textColor;
+    }
+
+    public void setMonthTextAppearance(int resId) {
+        applyTextAppearance(mMonthPaint, resId);
+        invalidate();
+    }
+
+    public void setDayOfWeekTextAppearance(int resId) {
+        applyTextAppearance(mDayOfWeekPaint, resId);
+        invalidate();
+    }
+
+    public void setDayTextAppearance(int resId) {
+        final ColorStateList textColor = applyTextAppearance(mDayPaint, resId);
+        if (textColor != null) {
+            mDayTextColor = textColor;
+        }
+
+        invalidate();
+    }
+
+    public CharSequence getTitle() {
+        if (mTitle == null) {
+            mTitle = mTitleFormatter.format(mCalendar.getTime());
+        }
+        return mTitle;
     }
 
     /**
      * Sets up the text and style properties for painting.
      */
-    private void initPaints() {
+    private void initPaints(Resources res) {
+        final String monthTypeface = res.getString(R.string.date_picker_month_typeface);
+        final String dayOfWeekTypeface = res.getString(R.string.date_picker_day_of_week_typeface);
+        final String dayTypeface = res.getString(R.string.date_picker_day_typeface);
+
+        final int monthTextSize = res.getDimensionPixelSize(
+                R.dimen.date_picker_month_text_size);
+        final int dayOfWeekTextSize = res.getDimensionPixelSize(
+                R.dimen.date_picker_day_of_week_text_size);
+        final int dayTextSize = res.getDimensionPixelSize(
+                R.dimen.date_picker_day_text_size);
+
         mMonthPaint.setAntiAlias(true);
-        mMonthPaint.setTextSize(mMonthTextSize);
-        mMonthPaint.setTypeface(Typeface.create(mMonthTypeface, Typeface.BOLD));
+        mMonthPaint.setTextSize(monthTextSize);
+        mMonthPaint.setTypeface(Typeface.create(monthTypeface, 0));
         mMonthPaint.setTextAlign(Align.CENTER);
         mMonthPaint.setStyle(Style.FILL);
 
         mDayOfWeekPaint.setAntiAlias(true);
-        mDayOfWeekPaint.setTextSize(mDayOfWeekTextSize);
-        mDayOfWeekPaint.setTypeface(Typeface.create(mDayOfWeekTypeface, Typeface.BOLD));
+        mDayOfWeekPaint.setTextSize(dayOfWeekTextSize);
+        mDayOfWeekPaint.setTypeface(Typeface.create(dayOfWeekTypeface, 0));
         mDayOfWeekPaint.setTextAlign(Align.CENTER);
         mDayOfWeekPaint.setStyle(Style.FILL);
 
-        mDayBackgroundPaint.setAntiAlias(true);
-        mDayBackgroundPaint.setStyle(Style.FILL);
+        mDaySelectorPaint.setAntiAlias(true);
+        mDaySelectorPaint.setStyle(Style.FILL);
+
+        mDayHighlightPaint.setAntiAlias(true);
+        mDayHighlightPaint.setStyle(Style.FILL);
 
         mDayPaint.setAntiAlias(true);
-        mDayPaint.setTextSize(mDayTextSize);
+        mDayPaint.setTextSize(dayTextSize);
+        mDayPaint.setTypeface(Typeface.create(dayTypeface, 0));
         mDayPaint.setTextAlign(Align.CENTER);
         mDayPaint.setStyle(Style.FILL);
     }
 
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-
-        mDayFormatter = new SimpleDateFormat("EEEEE", newConfig.locale);
-    }
-
     void setMonthTextColor(ColorStateList monthTextColor) {
         final int enabledColor = monthTextColor.getColorForState(ENABLED_STATE_SET, 0);
         mMonthPaint.setColor(enabledColor);
@@ -230,20 +274,18 @@
         invalidate();
     }
 
-    void setDayBackgroundColor(ColorStateList dayBackgroundColor) {
+    void setDaySelectorColor(ColorStateList dayBackgroundColor) {
         final int activatedColor = dayBackgroundColor.getColorForState(
                 StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0);
-        mDayBackgroundPaint.setColor(activatedColor);
+        mDaySelectorPaint.setColor(activatedColor);
         invalidate();
     }
 
-    @Override
-    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
-        // Workaround for a JB MR1 issue where accessibility delegates on
-        // top-level ListView items are overwritten.
-        if (!mLockAccessibilityDelegate) {
-            super.setAccessibilityDelegate(delegate);
-        }
+    void setDayHighlightColor(ColorStateList dayHighlightColor) {
+        final int pressedColor = dayHighlightColor.getColorForState(
+                StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED), 0);
+        mDayHighlightPaint.setColor(pressedColor);
+        invalidate();
     }
 
     public void setOnDayClickListener(OnDayClickListener listener) {
@@ -253,30 +295,124 @@
     @Override
     public boolean dispatchHoverEvent(MotionEvent event) {
         // First right-of-refusal goes the touch exploration helper.
-        if (mTouchHelper.dispatchHoverEvent(event)) {
-            return true;
-        }
-        return super.dispatchHoverEvent(event);
+        return mTouchHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         switch (event.getAction()) {
-            case MotionEvent.ACTION_UP:
-                final int day = getDayFromLocation(event.getX(), event.getY());
-                if (day >= 0) {
-                    onDayClick(day);
+            case MotionEvent.ACTION_DOWN:
+            case MotionEvent.ACTION_MOVE:
+                final int touchedDay = getDayAtLocation(event.getX(), event.getY());
+                if (mTouchedDay != touchedDay) {
+                    mTouchedDay = touchedDay;
+                    invalidate();
                 }
                 break;
+
+            case MotionEvent.ACTION_UP:
+                final int clickedDay = getDayAtLocation(event.getX(), event.getY());
+                onDayClicked(clickedDay);
+                // Fall through.
+            case MotionEvent.ACTION_CANCEL:
+                // Reset touched day on stream end.
+                mTouchedDay = -1;
+                invalidate();
+                break;
         }
         return true;
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
-        drawMonthTitle(canvas);
-        drawWeekDayLabels(canvas);
+        final int paddingLeft = getPaddingLeft();
+        final int paddingTop = getPaddingTop();
+        canvas.translate(paddingLeft, paddingTop);
+
+        drawMonth(canvas);
+        drawDaysOfWeek(canvas);
         drawDays(canvas);
+
+        canvas.translate(-paddingLeft, -paddingTop);
+    }
+
+    private void drawMonth(Canvas canvas) {
+        final float x = mPaddedWidth / 2f;
+
+        // Vertically centered within the month header height.
+        final float lineHeight = mMonthPaint.ascent() + mMonthPaint.descent();
+        final float y = (mMonthHeight - lineHeight) / 2f;
+
+        canvas.drawText(getTitle().toString(), x, y, mMonthPaint);
+    }
+
+    private void drawDaysOfWeek(Canvas canvas) {
+        final float cellWidthHalf = mPaddedWidth / (DAYS_IN_WEEK * 2);
+
+        // Vertically centered within the cell height.
+        final float lineHeight = mDayOfWeekPaint.ascent() + mDayOfWeekPaint.descent();
+        final float y = mMonthHeight + (mDayOfWeekHeight - lineHeight) / 2f;
+
+        for (int i = 0; i < DAYS_IN_WEEK; i++) {
+            final int calendarDay = (i + mWeekStart) % DAYS_IN_WEEK;
+            mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
+
+            final String dayLabel = mDayOfWeekFormatter.format(mDayLabelCalendar.getTime());
+            final float x = (2 * i + 1) * cellWidthHalf;
+            canvas.drawText(dayLabel, x, y, mDayOfWeekPaint);
+        }
+    }
+
+    /**
+     * Draws the month days.
+     */
+    private void drawDays(Canvas canvas) {
+        final int cellWidthHalf = mPaddedWidth / (DAYS_IN_WEEK * 2);
+
+        // Vertically centered within the cell height.
+        final float halfLineHeight = (mDayPaint.ascent() + mDayPaint.descent()) / 2;
+        float centerY = mMonthHeight + mDayOfWeekHeight + mDayHeight / 2f;
+
+        for (int day = 1, j = findDayOffset(); day <= mDaysInMonth; day++) {
+            final int x = (2 * j + 1) * cellWidthHalf;
+            int stateMask = 0;
+
+            if (day >= mEnabledDayStart && day <= mEnabledDayEnd) {
+                stateMask |= StateSet.VIEW_STATE_ENABLED;
+            }
+
+            final boolean isDayActivated = mActivatedDay == day;
+            if (isDayActivated) {
+                stateMask |= StateSet.VIEW_STATE_ACTIVATED;
+
+                // Adjust the circle to be centered on the row.
+                canvas.drawCircle(x, centerY, mDaySelectorRadius, mDaySelectorPaint);
+            } else if (mTouchedDay == day) {
+                stateMask |= StateSet.VIEW_STATE_PRESSED;
+
+                // Adjust the circle to be centered on the row.
+                canvas.drawCircle(x, centerY, mDaySelectorRadius, mDayHighlightPaint);
+            }
+
+            final boolean isDayToday = mToday == day;
+            final int dayTextColor;
+            if (isDayToday && !isDayActivated) {
+                dayTextColor = mDaySelectorPaint.getColor();
+            } else {
+                final int[] stateSet = StateSet.get(stateMask);
+                dayTextColor = mDayTextColor.getColorForState(stateSet, 0);
+            }
+            mDayPaint.setColor(dayTextColor);
+
+            canvas.drawText("" + day, x, centerY - halfLineHeight, mDayPaint);
+
+            j++;
+
+            if (j == DAYS_IN_WEEK) {
+                j = 0;
+                centerY += mDayHeight;
+            }
+        }
     }
 
     private static boolean isValidDayOfWeek(int day) {
@@ -288,18 +424,52 @@
     }
 
     /**
-     * Sets all the parameters for displaying this week. Parameters have a default value and
-     * will only update if a new value is included, except for focus month, which will always
-     * default to no focus month if no value is passed in. The only required parameter is the
-     * week start.
+     * Sets the selected day.
      *
-     * @param selectedDay the selected day of the month, or -1 for no selection.
-     * @param month the month.
-     * @param year the year.
-     * @param weekStart which day the week should start on. {@link Calendar#SUNDAY} through
-     *        {@link Calendar#SATURDAY}.
-     * @param enabledDayStart the first enabled day.
-     * @param enabledDayEnd the last enabled day.
+     * @param dayOfMonth the selected day of the month, or {@code -1} to clear
+     *                   the selection
+     */
+    public void setSelectedDay(int dayOfMonth) {
+        mActivatedDay = dayOfMonth;
+
+        // Invalidate cached accessibility information.
+        mTouchHelper.invalidateRoot();
+        invalidate();
+    }
+
+    /**
+     * Sets the first day of the week.
+     *
+     * @param weekStart which day the week should start on, valid values are
+     *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
+     */
+    public void setFirstDayOfWeek(int weekStart) {
+        if (isValidDayOfWeek(weekStart)) {
+            mWeekStart = weekStart;
+        } else {
+            mWeekStart = mCalendar.getFirstDayOfWeek();
+        }
+
+        // Invalidate cached accessibility information.
+        mTouchHelper.invalidateRoot();
+        invalidate();
+    }
+
+    /**
+     * Sets all the parameters for displaying this week.
+     * <p>
+     * Parameters have a default value and will only update if a new value is
+     * included, except for focus month, which will always default to no focus
+     * month if no value is passed in. The only required parameter is the week
+     * start.
+     *
+     * @param selectedDay the selected day of the month, or -1 for no selection
+     * @param month the month
+     * @param year the year
+     * @param weekStart which day the week should start on, valid values are
+     *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
+     * @param enabledDayStart the first enabled day
+     * @param enabledDayEnd the last enabled day
      */
     void setMonthParams(int selectedDay, int month, int year, int weekStart, int enabledDayStart,
             int enabledDayEnd) {
@@ -310,12 +480,6 @@
         }
         mYear = year;
 
-        // Figure out what day today is
-        final Time today = new Time(Time.getCurrentTimezone());
-        today.setToNow();
-        mHasToday = false;
-        mToday = -1;
-
         mCalendar.set(Calendar.MONTH, mMonth);
         mCalendar.set(Calendar.YEAR, mYear);
         mCalendar.set(Calendar.DAY_OF_MONTH, 1);
@@ -334,15 +498,20 @@
             mEnabledDayEnd = enabledDayEnd;
         }
 
-        mNumCells = getDaysInMonth(mMonth, mYear);
-        for (int i = 0; i < mNumCells; i++) {
+        // Figure out what day today is.
+        final Calendar today = Calendar.getInstance();
+        mToday = -1;
+        mDaysInMonth = getDaysInMonth(mMonth, mYear);
+        for (int i = 0; i < mDaysInMonth; i++) {
             final int day = i + 1;
             if (sameDay(day, today)) {
-                mHasToday = true;
                 mToday = day;
             }
         }
-        mNumRows = calculateNumRows();
+        mNumWeeks = calculateNumRows();
+
+        // Invalidate the old title.
+        mTitle = null;
 
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
@@ -371,154 +540,118 @@
     }
 
     public void reuse() {
-        mNumRows = DEFAULT_NUM_ROWS;
+        mNumWeeks = MAX_WEEKS_IN_MONTH;
         requestLayout();
     }
 
     private int calculateNumRows() {
-        int offset = findDayOffset();
-        int dividend = (offset + mNumCells) / mNumDays;
-        int remainder = (offset + mNumCells) % mNumDays;
-        return (dividend + (remainder > 0 ? 1 : 0));
+        final int offset = findDayOffset();
+        final int dividend = (offset + mDaysInMonth) / DAYS_IN_WEEK;
+        final int remainder = (offset + mDaysInMonth) % DAYS_IN_WEEK;
+        return dividend + (remainder > 0 ? 1 : 0);
     }
 
-    private boolean sameDay(int day, Time today) {
-        return mYear == today.year &&
-                mMonth == today.month &&
-                day == today.monthDay;
+    private boolean sameDay(int day, Calendar today) {
+        return mYear == today.get(Calendar.YEAR) && mMonth == today.get(Calendar.MONTH)
+                && day == today.get(Calendar.DAY_OF_MONTH);
     }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mRowHeight * mNumRows
-                + mMonthHeaderHeight);
+        final int preferredHeight = mDayHeight * mNumWeeks + mDayOfWeekHeight + mMonthHeight
+                + getPaddingTop() + getPaddingBottom();
+        final int preferredWidth = mCellWidth * DAYS_IN_WEEK
+                + getPaddingStart() + getPaddingEnd();
+        final int resolvedWidth = resolveSize(preferredWidth, widthMeasureSpec);
+        final int resolvedHeight = resolveSize(preferredHeight, heightMeasureSpec);
+        setMeasuredDimension(resolvedWidth, resolvedHeight);
     }
 
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mWidth = w;
+        mPaddedWidth = w - getPaddingLeft() - getPaddingRight();
+        mPaddedHeight = w - getPaddingTop() - getPaddingBottom();
 
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
     }
 
-    private String getMonthAndYearString() {
-        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR
-                | DateUtils.FORMAT_NO_MONTH_DAY;
-        mStringBuilder.setLength(0);
-        long millis = mCalendar.getTimeInMillis();
-        return DateUtils.formatDateRange(getContext(), mFormatter, millis, millis, flags,
-                Time.getCurrentTimezone()).toString();
-    }
-
-    private void drawMonthTitle(Canvas canvas) {
-        final float x = (mWidth + 2 * mPadding) / 2f;
-
-        // Centered on the upper half of the month header.
-        final float lineHeight = mMonthPaint.ascent() + mMonthPaint.descent();
-        final float y = mMonthHeaderHeight * 0.25f - lineHeight / 2f;
-
-        canvas.drawText(getMonthAndYearString(), x, y, mMonthPaint);
-    }
-
-    private void drawWeekDayLabels(Canvas canvas) {
-        final float dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
-
-        // Centered on the lower half of the month header.
-        final float lineHeight = mDayOfWeekPaint.ascent() + mDayOfWeekPaint.descent();
-        final float y = mMonthHeaderHeight * 0.75f - lineHeight / 2f;
-
-        for (int i = 0; i < mNumDays; i++) {
-            final int calendarDay = (i + mWeekStart) % mNumDays;
-            mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
-
-            final String dayLabel = mDayFormatter.format(mDayLabelCalendar.getTime());
-            final float x = (2 * i + 1) * dayWidthHalf + mPadding;
-            canvas.drawText(dayLabel, x, y, mDayOfWeekPaint);
-        }
-    }
-
-    /**
-     * Draws the month days.
-     */
-    private void drawDays(Canvas canvas) {
-        final int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
-
-        // Centered within the row.
-        final float lineHeight = mDayOfWeekPaint.ascent() + mDayOfWeekPaint.descent();
-        float y = mMonthHeaderHeight + (mRowHeight - lineHeight) / 2f;
-
-        for (int day = 1, j = findDayOffset(); day <= mNumCells; day++) {
-            final int x = (2 * j + 1) * dayWidthHalf + mPadding;
-            int stateMask = 0;
-
-            if (day >= mEnabledDayStart && day <= mEnabledDayEnd) {
-                stateMask |= StateSet.VIEW_STATE_ENABLED;
-            }
-
-            if (mActivatedDay == day) {
-                stateMask |= StateSet.VIEW_STATE_ACTIVATED;
-
-                // Adjust the circle to be centered the row.
-                final float rowCenterY = y + lineHeight / 2;
-                canvas.drawCircle(x, rowCenterY, mRowHeight / 2,
-                        mDayBackgroundPaint);
-            }
-
-            final int[] stateSet = StateSet.get(stateMask);
-            final int dayTextColor = mDayTextColor.getColorForState(stateSet, 0);
-            mDayPaint.setColor(dayTextColor);
-
-            final boolean isDayToday = mHasToday && mToday == day;
-            mDayPaint.setFakeBoldText(isDayToday);
-
-            canvas.drawText(String.format("%d", day), x, y, mDayPaint);
-
-            j++;
-
-            if (j == mNumDays) {
-                j = 0;
-                y += mRowHeight;
-            }
-        }
-    }
-
     private int findDayOffset() {
-        return (mDayOfWeekStart < mWeekStart ? (mDayOfWeekStart + mNumDays) : mDayOfWeekStart)
-                - mWeekStart;
+        final int offset = mDayOfWeekStart - mWeekStart;
+        if (mDayOfWeekStart < mWeekStart) {
+            return offset + DAYS_IN_WEEK;
+        }
+        return offset;
     }
 
     /**
-     * Calculates the day that the given x position is in, accounting for week
-     * number. Returns the day or -1 if the position wasn't in a day.
+     * Calculates the day of the month at the specified touch position. Returns
+     * the day of the month or -1 if the position wasn't in a valid day.
      *
-     * @param x The x position of the touch event
-     * @return The day number, or -1 if the position wasn't in a day
+     * @param x the x position of the touch event
+     * @param y the y position of the touch event
+     * @return the day of the month at (x, y) or -1 if the position wasn't in a
+     *         valid day
      */
-    private int getDayFromLocation(float x, float y) {
-        int dayStart = mPadding;
-        if (x < dayStart || x > mWidth - mPadding) {
+    private int getDayAtLocation(float x, float y) {
+        final int paddedX = (int) (x - getPaddingLeft() + 0.5f);
+        if (paddedX < 0 || paddedX >= mPaddedWidth) {
             return -1;
         }
-        // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
-        int row = (int) (y - mMonthHeaderHeight) / mRowHeight;
-        int column = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
 
-        int day = column - findDayOffset() + 1;
-        day += row * mNumDays;
-        if (day < 1 || day > mNumCells) {
+        final int headerHeight = mMonthHeight + mDayOfWeekHeight;
+        final int paddedY = (int) (y - getPaddingTop() + 0.5f);
+        if (paddedY < headerHeight || paddedY >= mPaddedHeight) {
             return -1;
         }
+
+        final int row = (paddedY - headerHeight) / mDayHeight;
+        final int col = (paddedX * DAYS_IN_WEEK) / mPaddedWidth;
+        final int index = col + row * DAYS_IN_WEEK;
+        final int day = index + 1 - findDayOffset();
+        if (day < 1 || day > mDaysInMonth) {
+            return -1;
+        }
+
         return day;
     }
 
     /**
+     * Calculates the bounds of the specified day.
+     *
+     * @param day the day of the month
+     * @param outBounds the rect to populate with bounds
+     */
+    private boolean getBoundsForDay(int day, Rect outBounds) {
+        if (day < 1 || day > mDaysInMonth) {
+            return false;
+        }
+
+        final int index = day - 1 + findDayOffset();
+        final int row = index / DAYS_IN_WEEK;
+        final int col = index % DAYS_IN_WEEK;
+
+        final int headerHeight = mMonthHeight + mDayOfWeekHeight;
+        final int paddedY = row * mDayHeight + headerHeight;
+        final int paddedX = col * mPaddedWidth;
+
+        final int y = paddedY + getPaddingTop();
+        final int x = paddedX + getPaddingLeft();
+
+        final int cellHeight = mDayHeight;
+        final int cellWidth = mPaddedWidth / DAYS_IN_WEEK;
+        outBounds.set(x, y, (x + cellWidth), (y + cellHeight));
+
+        return true;
+    }
+
+    /**
      * Called when the user clicks on a day. Handles callbacks to the
      * {@link OnDayClickListener} if one is set.
      *
-     * @param day The day that was clicked
+     * @param day the day that was clicked
      */
-    private void onDayClick(int day) {
+    private void onDayClicked(int day) {
         if (mOnDayClickListener != null) {
             Calendar date = Calendar.getInstance();
             date.set(mYear, mMonth, day);
@@ -530,44 +663,6 @@
     }
 
     /**
-     * @return The date that has accessibility focus, or {@code null} if no date
-     *         has focus
-     */
-    Calendar getAccessibilityFocus() {
-        final int day = mTouchHelper.getFocusedVirtualView();
-        Calendar date = null;
-        if (day >= 0) {
-            date = Calendar.getInstance();
-            date.set(mYear, mMonth, day);
-        }
-        return date;
-    }
-
-    /**
-     * Clears accessibility focus within the view. No-op if the view does not
-     * contain accessibility focus.
-     */
-    public void clearAccessibilityFocus() {
-        mTouchHelper.clearFocusedVirtualView();
-    }
-
-    /**
-     * Attempts to restore accessibility focus to the specified date.
-     *
-     * @param day The date which should receive focus
-     * @return {@code false} if the date is not valid for this month view, or
-     *         {@code true} if the date received focus
-     */
-    boolean restoreAccessibilityFocus(Calendar day) {
-        if ((day.get(Calendar.YEAR) != mYear) || (day.get(Calendar.MONTH) != mMonth) ||
-                (day.get(Calendar.DAY_OF_MONTH) > mNumCells)) {
-            return false;
-        }
-        mTouchHelper.setFocusedVirtualView(day.get(Calendar.DAY_OF_MONTH));
-        return true;
-    }
-
-    /**
      * Provides a virtual view hierarchy for interfacing with an accessibility
      * service.
      */
@@ -581,24 +676,9 @@
             super(host);
         }
 
-        public void setFocusedVirtualView(int virtualViewId) {
-            getAccessibilityNodeProvider(SimpleMonthView.this).performAction(
-                    virtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
-        }
-
-        public void clearFocusedVirtualView() {
-            final int focusedVirtualView = getFocusedVirtualView();
-            if (focusedVirtualView != ExploreByTouchHelper.INVALID_ID) {
-                getAccessibilityNodeProvider(SimpleMonthView.this).performAction(
-                        focusedVirtualView,
-                        AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
-                        null);
-            }
-        }
-
         @Override
         protected int getVirtualViewAt(float x, float y) {
-            final int day = getDayFromLocation(x, y);
+            final int day = getDayAtLocation(x, y);
             if (day >= 0) {
                 return day;
             }
@@ -607,7 +687,7 @@
 
         @Override
         protected void getVisibleVirtualViews(IntArray virtualViewIds) {
-            for (int day = 1; day <= mNumCells; day++) {
+            for (int day = 1; day <= mDaysInMonth; day++) {
                 virtualViewIds.add(day);
             }
         }
@@ -619,11 +699,20 @@
 
         @Override
         protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
-            getItemBounds(virtualViewId, mTempRect);
+            final boolean hasBounds = getBoundsForDay(virtualViewId, mTempRect);
+
+            if (!hasBounds) {
+                // The day is invalid, kill the node.
+                mTempRect.setEmpty();
+                node.setContentDescription("");
+                node.setBoundsInParent(mTempRect);
+                node.setVisibleToUser(false);
+                return;
+            }
 
             node.setContentDescription(getItemDescription(virtualViewId));
             node.setBoundsInParent(mTempRect);
-            node.addAction(AccessibilityNodeInfo.ACTION_CLICK);
+            node.addAction(AccessibilityAction.ACTION_CLICK);
 
             if (virtualViewId == mActivatedDay) {
                 node.setSelected(true);
@@ -636,7 +725,7 @@
                 Bundle arguments) {
             switch (action) {
                 case AccessibilityNodeInfo.ACTION_CLICK:
-                    onDayClick(virtualViewId);
+                    onDayClicked(virtualViewId);
                     return true;
             }
 
@@ -644,26 +733,6 @@
         }
 
         /**
-         * Calculates the bounding rectangle of a given time object.
-         *
-         * @param day The day to calculate bounds for
-         * @param rect The rectangle in which to store the bounds
-         */
-        private void getItemBounds(int day, Rect rect) {
-            final int offsetX = mPadding;
-            final int offsetY = mMonthHeaderHeight;
-            final int cellHeight = mRowHeight;
-            final int cellWidth = ((mWidth - (2 * mPadding)) / mNumDays);
-            final int index = ((day - 1) + findDayOffset());
-            final int row = (index / mNumDays);
-            final int column = (index % mNumDays);
-            final int x = (offsetX + (column * cellWidth));
-            final int y = (offsetY + (row * cellHeight));
-
-            rect.set(x, y, (x + cellWidth), (y + cellHeight));
-        }
-
-        /**
          * Generates a description for a given time object. Since this
          * description will be spoken, the components are ordered by descending
          * specificity as DAY MONTH YEAR.
diff --git a/core/java/android/widget/TextViewWithCircularIndicator.java b/core/java/android/widget/TextViewWithCircularIndicator.java
deleted file mode 100644
index d3c786c..0000000
--- a/core/java/android/widget/TextViewWithCircularIndicator.java
+++ /dev/null
@@ -1,87 +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.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.util.AttributeSet;
-
-import com.android.internal.R;
-
-class TextViewWithCircularIndicator extends TextView {
-    private final Paint mCirclePaint = new Paint();
-    private final String mItemIsSelectedText;
-
-    public TextViewWithCircularIndicator(Context context) {
-        this(context, null);
-    }
-
-    public TextViewWithCircularIndicator(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public TextViewWithCircularIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public TextViewWithCircularIndicator(Context context, AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        final Resources res = context.getResources();
-        mItemIsSelectedText = res.getString(R.string.item_is_selected);
-
-        init();
-    }
-
-    private void init() {
-        mCirclePaint.setTypeface(Typeface.create(mCirclePaint.getTypeface(), Typeface.BOLD));
-        mCirclePaint.setAntiAlias(true);
-        mCirclePaint.setTextAlign(Paint.Align.CENTER);
-        mCirclePaint.setStyle(Paint.Style.FILL);
-    }
-
-    public void setCircleColor(int color) {
-        mCirclePaint.setColor(color);
-        invalidate();
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        if (isActivated()) {
-            final int width = getWidth();
-            final int height = getHeight();
-            final int radius = Math.min(width, height) / 2;
-            canvas.drawCircle(width / 2, height / 2, radius, mCirclePaint);
-        }
-
-        super.onDraw(canvas);
-    }
-
-    @Override
-    public CharSequence getContentDescription() {
-        final CharSequence itemText = getText();
-        if (isActivated()) {
-            return String.format(mItemIsSelectedText, itemText);
-        } else {
-            return itemText;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 6f0465f..7bd502e 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -17,10 +17,9 @@
 package android.widget;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.util.AttributeSet;
-import android.util.StateSet;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
@@ -32,23 +31,14 @@
 /**
  * Displays a selectable list of years.
  */
-class YearPickerView extends ListView implements AdapterView.OnItemClickListener,
-        OnDateChangedListener {
-    private final Calendar mMinDate = Calendar.getInstance();
-    private final Calendar mMaxDate = Calendar.getInstance();
-
+class YearPickerView extends ListView {
     private final YearAdapter mAdapter;
     private final int mViewSize;
     private final int mChildSize;
 
-    private DatePickerController mController;
+    private OnYearSelectedListener mOnYearSelectedListener;
 
-    private int mSelectedPosition = -1;
-    private int mYearActivatedColor;
-
-    public YearPickerView(Context context) {
-        this(context, null);
-    }
+    private long mCurrentTimeMillis;
 
     public YearPickerView(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.listViewStyle);
@@ -69,104 +59,187 @@
         mViewSize = res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height);
         mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height);
 
-        setVerticalFadingEdgeEnabled(true);
-        setFadingEdgeLength(mChildSize / 3);
+        setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final int year = mAdapter.getYearForPosition(position);
+                mAdapter.setSelection(year);
 
-        final int paddingTop = res.getDimensionPixelSize(
-                R.dimen.datepicker_year_picker_padding_top);
-        setPadding(0, paddingTop, 0, 0);
+                if (mOnYearSelectedListener != null) {
+                    mOnYearSelectedListener.onYearChanged(YearPickerView.this, year);
+                }
+            }
+        });
 
-        setOnItemClickListener(this);
-        setDividerHeight(0);
-
-        mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view);
+        mAdapter = new YearAdapter(getContext());
         setAdapter(mAdapter);
     }
 
+    public void setOnYearSelectedListener(OnYearSelectedListener listener) {
+        mOnYearSelectedListener = listener;
+    }
+
+    public void setDate(long currentTimeMillis) {
+        mCurrentTimeMillis = currentTimeMillis;
+    }
+
+    /**
+     * Sets the currently selected year. Jumps immediately to the new year.
+     *
+     * @param year the target year
+     */
+    public void setYear(final int year) {
+        mAdapter.setSelection(year);
+
+        post(new Runnable() {
+            @Override
+            public void run() {
+                final int position = mAdapter.getPositionForYear(year);
+                if (position >= 0 && position < getCount()) {
+                    setSelectionCentered(position);
+                }
+            }
+        });
+    }
+
+    public void setSelectionCentered(int position) {
+        final int offset = mViewSize / 2 - mChildSize / 2;
+        setSelectionFromTop(position, offset);
+    }
+
     public void setRange(Calendar min, Calendar max) {
-        mMinDate.setTimeInMillis(min.getTimeInMillis());
-        mMaxDate.setTimeInMillis(max.getTimeInMillis());
-
-        updateAdapterData();
-    }
-
-    public void init(DatePickerController controller) {
-        mController = controller;
-        mController.registerOnDateChangedListener(this);
-
-        updateAdapterData();
-
-        onDateChanged();
-    }
-
-    public void setYearBackgroundColor(ColorStateList yearBackgroundColor) {
-        mYearActivatedColor = yearBackgroundColor.getColorForState(
-                StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0);
-        invalidate();
+        mAdapter.setRange(min, max);
     }
 
     public void setYearTextAppearance(int resId) {
         mAdapter.setItemTextAppearance(resId);
     }
 
-    private void updateAdapterData() {
-        mAdapter.clear();
-
-        final int maxYear = mMaxDate.get(Calendar.YEAR);
-        for (int year = mMinDate.get(Calendar.YEAR); year <= maxYear; year++) {
-            mAdapter.add(year);
-        }
+    public void setYearActivatedTextAppearance(int resId) {
+        mAdapter.setItemActivatedTextAppearance(resId);
     }
 
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        mController.tryVibrate();
-        if (position != mSelectedPosition) {
-            mSelectedPosition = position;
-            mAdapter.notifyDataSetChanged();
-        }
-        mController.onYearSelected(mAdapter.getItem(position));
-    }
+    private static class YearAdapter extends BaseAdapter {
+        private static final int ITEM_LAYOUT = R.layout.year_label_text_view;
 
-    private class YearAdapter extends ArrayAdapter<Integer> {
+        private final LayoutInflater mInflater;
+
+        private int mActivatedYear;
+        private int mMinYear;
+        private int mCount;
+
         private int mItemTextAppearanceResId;
+        private int mItemActivatedTextAppearanceResId;
 
-        public YearAdapter(Context context, int resource) {
-            super(context, resource);
+        public YearAdapter(Context context) {
+            mInflater = LayoutInflater.from(context);
         }
 
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            final TextViewWithCircularIndicator v = (TextViewWithCircularIndicator)
-                    super.getView(position, convertView, parent);
-            v.setTextAppearance(v.getContext(), mItemTextAppearanceResId);
-            v.setCircleColor(mYearActivatedColor);
+        public void setRange(Calendar minDate, Calendar maxDate) {
+            final int minYear = minDate.get(Calendar.YEAR);
+            final int count = maxDate.get(Calendar.YEAR) - minYear + 1;
 
-            final int year = getItem(position);
-            final boolean selected = mController.getSelectedDay().get(Calendar.YEAR) == year;
-            v.setActivated(selected);
+            if (mMinYear != minYear || mCount != count) {
+                mMinYear = minYear;
+                mCount = count;
+                notifyDataSetInvalidated();
+            }
+        }
 
-            return v;
+        public boolean setSelection(int year) {
+            if (mActivatedYear != year) {
+                mActivatedYear = year;
+                notifyDataSetChanged();
+                return true;
+            }
+            return false;
         }
 
         public void setItemTextAppearance(int resId) {
             mItemTextAppearanceResId = resId;
+            notifyDataSetChanged();
         }
-    }
 
-    public void postSetSelectionCentered(final int position) {
-        postSetSelectionFromTop(position, mViewSize / 2 - mChildSize / 2);
-    }
+        public void setItemActivatedTextAppearance(int resId) {
+            mItemActivatedTextAppearanceResId = resId;
+            notifyDataSetChanged();
+        }
 
-    public void postSetSelectionFromTop(final int position, final int offset) {
-        post(new Runnable() {
+        @Override
+        public int getCount() {
+            return mCount;
+        }
 
-            @Override
-            public void run() {
-                setSelectionFromTop(position, offset);
-                requestLayout();
+        @Override
+        public Integer getItem(int position) {
+            return getYearForPosition(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return getYearForPosition(position);
+        }
+
+        public int getPositionForYear(int year) {
+            return year - mMinYear;
+        }
+
+        public int getYearForPosition(int position) {
+            return mMinYear + position;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return true;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
             }
-        });
+
+            final int year = getYearForPosition(position);
+            final boolean activated = mActivatedYear == year;
+
+            final int textAppearanceResId;
+            if (activated && mItemActivatedTextAppearanceResId != 0) {
+                textAppearanceResId = mItemActivatedTextAppearanceResId;
+            } else {
+                textAppearanceResId = mItemTextAppearanceResId;
+            }
+
+            final TextView v = (TextView) convertView;
+            v.setText("" + year);
+            v.setTextAppearance(v.getContext(), textAppearanceResId);
+            v.setActivated(activated);
+            return v;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return 0;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 1;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return false;
+        }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return true;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return true;
+        }
     }
 
     public int getFirstPositionOffset() {
@@ -177,22 +250,28 @@
         return firstChild.getTop();
     }
 
-    @Override
-    public void onDateChanged() {
-        updateAdapterData();
-        mAdapter.notifyDataSetChanged();
-        postSetSelectionCentered(
-                mController.getSelectedDay().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
-    }
-
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         super.onInitializeAccessibilityEventInternal(event);
 
+        // There are a bunch of years, so don't bother.
         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
             event.setFromIndex(0);
             event.setToIndex(0);
         }
     }
+
+    /**
+     * The callback used to indicate the user changed the year.
+     */
+    public interface OnYearSelectedListener {
+        /**
+         * Called upon a year change.
+         *
+         * @param view The view associated with this listener.
+         * @param year The year that was set.
+         */
+        void onYearChanged(YearPickerView view, int year);
+    }
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/widget/AccessibleDateAnimator.java b/core/java/com/android/internal/widget/AccessibleDateAnimator.java
deleted file mode 100644
index f97a5d1..0000000
--- a/core/java/com/android/internal/widget/AccessibleDateAnimator.java
+++ /dev/null
@@ -1,56 +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.internal.widget;
-
-import android.content.Context;
-import android.text.format.DateUtils;
-import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ViewAnimator;
-
-/**
- * @hide
- */
-public class AccessibleDateAnimator extends ViewAnimator {
-    private long mDateMillis;
-
-    public AccessibleDateAnimator(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public void setDateMillis(long dateMillis) {
-        mDateMillis = dateMillis;
-    }
-
-    /**
-     * Announce the currently-selected date when launched.
-     */
-    @Override
-    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
-        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            // Clear the event's current text so that only the current date will be spoken.
-            event.getText().clear();
-            int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR |
-                    DateUtils.FORMAT_SHOW_WEEKDAY;
-
-            String dateString = DateUtils.formatDateTime(getContext(), mDateMillis, flags);
-            event.getText().add(dateString);
-            return true;
-        }
-        return super.dispatchPopulateAccessibilityEventInternal(event);
-    }
-}
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index f916e6f..8018942 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -137,7 +137,7 @@
     private int mRestoredCurItem = -1;
     private Parcelable mRestoredAdapterState = null;
     private ClassLoader mRestoredClassLoader = null;
-    private Scroller mScroller;
+    private final Scroller mScroller;
     private PagerObserver mObserver;
 
     private int mPageMargin;
@@ -162,9 +162,9 @@
 
     private boolean mIsBeingDragged;
     private boolean mIsUnableToDrag;
-    private int mDefaultGutterSize;
+    private final int mDefaultGutterSize;
     private int mGutterSize;
-    private int mTouchSlop;
+    private final int mTouchSlop;
     /**
      * Position of the last motion event.
      */
@@ -187,10 +187,10 @@
      * Determines speed during touch scrolling
      */
     private VelocityTracker mVelocityTracker;
-    private int mMinimumVelocity;
-    private int mMaximumVelocity;
-    private int mFlingDistance;
-    private int mCloseEnough;
+    private final int mMinimumVelocity;
+    private final int mMaximumVelocity;
+    private final int mFlingDistance;
+    private final int mCloseEnough;
 
     // If the pager is at least this close to its final position, complete the scroll
     // on touch down and let the user interact with the content inside instead of
@@ -200,8 +200,8 @@
     private boolean mFakeDragging;
     private long mFakeDragBeginTime;
 
-    private EdgeEffect mLeftEdge;
-    private EdgeEffect mRightEdge;
+    private final EdgeEffect mLeftEdge;
+    private final EdgeEffect mRightEdge;
 
     private boolean mFirstLayout = true;
     private boolean mNeedCalculatePageOffsets = false;
@@ -339,20 +339,24 @@
     interface Decor {}
 
     public ViewPager(Context context) {
-        super(context);
-        initViewPager();
+        this(context, null);
     }
 
     public ViewPager(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initViewPager();
+        this(context, attrs, 0);
     }
 
-    void initViewPager() {
+    public ViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public ViewPager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
         setWillNotDraw(false);
         setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
         setFocusable(true);
-        final Context context = getContext();
+
         mScroller = new Scroller(context, sInterpolator);
         final ViewConfiguration configuration = ViewConfiguration.get(context);
         final float density = context.getResources().getDisplayMetrics().density;
diff --git a/core/res/res/color/date_picker_header_text_material.xml b/core/res/res/color/date_picker_header_text_material.xml
index cda894b..baa8958 100644
--- a/core/res/res/color/date_picker_header_text_material.xml
+++ b/core/res/res/color/date_picker_header_text_material.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item
-        android:state_selected="true"
+        android:state_activated="true"
         android:color="?attr/textColorPrimaryInverse" />
     <item
         android:color="?attr/textColorSecondaryInverse" />
diff --git a/core/res/res/drawable/time_picker_header_material.xml b/core/res/res/drawable/time_picker_header_material.xml
deleted file mode 100644
index ef2068a..0000000
--- a/core/res/res/drawable/time_picker_header_material.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="?attr/colorControlHighlight">
-    <item android:drawable="?attr/colorAccent" />
-</ripple>
diff --git a/core/res/res/layout-land/date_picker_holo.xml b/core/res/res/layout-land/date_picker_holo.xml
deleted file mode 100644
index 991888c..0000000
--- a/core/res/res/layout-land/date_picker_holo.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="@dimen/datepicker_view_animator_height"
-              android:gravity="center"
-              android:orientation="horizontal"
-              android:minWidth="@dimen/datepicker_dialog_width" >
-
-    <include
-        layout="@layout/date_picker_selected_date"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_weight="1" />
-
-    <include layout="@layout/date_picker_view_animator" />
-
-</LinearLayout>
diff --git a/core/res/res/layout-land/date_picker_material.xml b/core/res/res/layout-land/date_picker_material.xml
new file mode 100644
index 0000000..1e711c5
--- /dev/null
+++ b/core/res/res/layout-land/date_picker_material.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="horizontal">
+
+    <include
+        layout="@layout/date_picker_header_material"
+        android:layout_width="168dp"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="vertical">
+
+        <include
+            layout="@layout/date_picker_view_animator_material"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+
+        <ViewStub
+            android:id="@id/buttonPanel"
+            android:layout="@layout/alert_dialog_button_bar_material"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/day_picker_button_margin_top" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml
index 891bcd5..1eea4e1 100644
--- a/core/res/res/layout/alert_dialog_button_bar_material.xml
+++ b/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -18,16 +18,16 @@
 <com.android.internal.widget.ButtonBarLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/buttonPanel"
-    style="?attr/buttonBarStyle"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layoutDirection="locale"
     android:orientation="horizontal"
     android:paddingStart="12dp"
     android:paddingEnd="12dp"
-    android:paddingTop="8dp"
-    android:paddingBottom="8dp"
-    android:gravity="bottom">
+    android:paddingTop="4dp"
+    android:paddingBottom="4dp"
+    android:gravity="bottom"
+    style="?attr/buttonBarStyle">
 
     <Button
         android:id="@+id/button3"
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
new file mode 100644
index 0000000..bda7de9
--- /dev/null
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
+              android:id="@+id/date_picker_header"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:paddingBottom="18dp"
+              android:paddingStart="?attr/dialogPreferredPadding"
+              android:paddingEnd="?attr/dialogPreferredPadding"
+              android:orientation="vertical"
+              tools:background="@color/accent_material_light"
+              tools:paddingStart="24dp"
+              tools:paddingEnd="24dp">
+
+    <!-- Top padding should stay on this view so that
+         the touch target is a bit larger. -->
+    <TextView
+        android:id="@+id/date_picker_header_year"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel"
+        tools:text="2015"
+        tools:textSize="@dimen/date_picker_year_label_size"
+        tools:textColor="@color/white" />
+
+    <TextView
+        android:id="@+id/date_picker_header_date"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="@style/TextAppearance.Material.DatePicker.DateLabel"
+        android:maxLines="2"
+        android:ellipsize="none"
+        tools:text="Thu, Sep 30"
+        tools:textSize="@dimen/date_picker_date_label_size"
+        tools:textColor="@color/white" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_material.xml
similarity index 72%
rename from core/res/res/layout/date_picker_holo.xml
rename to core/res/res/layout/date_picker_material.xml
index 72030ea..a1c97ff 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_material.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2011 The Android Open Source Project
+     Copyright (C) 2014 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="@dimen/datepicker_component_width"
+              android:layout_width="match_parent"
               android:layout_height="match_parent"
-              android:gravity="center"
               android:orientation="vertical">
 
     <include
-        layout="@layout/date_picker_selected_date"
+        layout="@layout/date_picker_header_material"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <include layout="@layout/date_picker_view_animator" />
+    <include
+        layout="@layout/date_picker_view_animator_material"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/date_picker_selected_date.xml b/core/res/res/layout/date_picker_selected_date.xml
deleted file mode 100644
index 9becb81..0000000
--- a/core/res/res/layout/date_picker_selected_date.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/day_picker_selector_layout"
-    android:layout_width="@dimen/datepicker_component_width"
-    android:layout_height="wrap_content"
-    android:gravity="center"
-    android:orientation="vertical">
-
-    <TextView
-        android:id="@+id/date_picker_header"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/datepicker_header_height"
-        android:gravity="center"
-        android:importantForAccessibility="no" />
-
-    <LinearLayout
-        android:id="@+id/date_picker_month_day_year_layout"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:paddingTop="4dp"
-        android:paddingBottom="4dp"
-        android:orientation="vertical"
-        android:gravity="center">
-
-        <LinearLayout
-            android:id="@+id/date_picker_month_and_day_layout"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:clickable="true"
-            android:orientation="vertical">
-
-            <TextView
-                android:id="@+id/date_picker_month"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:duplicateParentState="true"
-                android:gravity="center" />
-
-            <TextView
-                android:id="@+id/date_picker_day"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="-23dp"
-                android:layout_marginBottom="-20dp"
-                android:duplicateParentState="true"
-                android:gravity="center" />
-        </LinearLayout>
-
-        <TextView
-            android:id="@+id/date_picker_year"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center" />
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/core/res/res/layout/date_picker_view_animator.xml b/core/res/res/layout/date_picker_view_animator.xml
deleted file mode 100644
index 9085ed5..0000000
--- a/core/res/res/layout/date_picker_view_animator.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<com.android.internal.widget.AccessibleDateAnimator
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/animator"
-        android:layout_width="@dimen/datepicker_component_width"
-        android:layout_height="@dimen/datepicker_view_animator_height"
-        android:gravity="center" />
\ No newline at end of file
diff --git a/core/res/res/layout/date_picker_view_animator_material.xml b/core/res/res/layout/date_picker_view_animator_material.xml
new file mode 100644
index 0000000..98ef1dd
--- /dev/null
+++ b/core/res/res/layout/date_picker_view_animator_material.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+
+<ViewAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/animator"
+    android:layout_width="match_parent"
+    android:layout_height="0dp"
+    android:layout_weight="1"
+    android:gravity="center">
+
+    <android.widget.DayPickerView
+        android:id="@+id/date_picker_day_picker"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingStart="@dimen/day_picker_padding_horizontal"
+        android:paddingEnd="@dimen/day_picker_padding_horizontal"
+        android:paddingTop="@dimen/day_picker_padding_top" />
+
+    <android.widget.YearPickerView
+        android:id="@+id/date_picker_year_picker"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</ViewAnimator>
diff --git a/core/res/res/layout/year_label_text_view.xml b/core/res/res/layout/year_label_text_view.xml
index e5bd068..6240c4b 100644
--- a/core/res/res/layout/year_label_text_view.xml
+++ b/core/res/res/layout/year_label_text_view.xml
@@ -13,10 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<android.widget.TextViewWithCircularIndicator
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/month_text_view"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/datepicker_year_label_height"
-        android:layout_gravity="center"
-        android:gravity="center" />
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+         android:id="@+id/month_text_view"
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+         android:minHeight="?attr/listPreferredItemHeightSmall"
+         android:paddingTop="12dp"
+         android:paddingBottom="12dp"
+         android:gravity="center" />
diff --git a/core/res/res/values-land/dimens_material.xml b/core/res/res/values-land/dimens_material.xml
index 379ccf6..202f4a4 100644
--- a/core/res/res/values-land/dimens_material.xml
+++ b/core/res/res/values-land/dimens_material.xml
@@ -48,4 +48,14 @@
     <dimen name="timepicker_text_inset_inner">46dp</dimen>
     <dimen name="timepicker_text_size_normal">14sp</dimen>
     <dimen name="timepicker_text_size_inner">12sp</dimen>
+
+    <!-- Used by Material-style SimpleMonthView -->
+    <dimen name="date_picker_month_height">40dp</dimen>
+    <dimen name="date_picker_day_of_week_height">14dp</dimen>
+    <dimen name="date_picker_day_height">32dp</dimen>
+    <dimen name="date_picker_day_width">46dp</dimen>
+    <dimen name="date_picker_day_selector_radius">16dp</dimen>
+    <dimen name="day_picker_padding_horizontal">18dp</dimen>
+    <dimen name="day_picker_padding_top">0dp</dimen>
+    <dimen name="day_picker_button_margin_top">-8dp</dimen>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 269afba..e7c6bee 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -203,8 +203,7 @@
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"未开启飞行模式"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"设置"</string>
-    <!-- no translation found for global_action_assist (3892832961594295030) -->
-    <skip />
+    <string name="global_action_assist" msgid="3892832961594295030">"助理"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"语音助理"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 15797dd..b5576c5 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1036,7 +1036,7 @@
         <attr name="colorSwitchThumbNormal" format="color" />
 
         <!-- @hide The background used by framework controls. -->
-        <attr name="controlBackground" format="color" />
+        <attr name="controlBackground" format="reference" />
 
         <!-- The color applied to the edge effect on scrolling containers. -->
         <attr name="colorEdgeEffect" format="color" />
@@ -4443,46 +4443,42 @@
     </declare-styleable>
 
     <declare-styleable name="DatePicker">
-        <!-- The first year (inclusive), for example "1940".
-             {@deprecated Use minDate instead.} -->
+        <!-- The first year (inclusive), for example "1940". {@deprecated Use minDate instead.} -->
         <attr name="startYear" format="integer" />
-        <!-- The last year (inclusive), for example "2010".
-             {@deprecated Use maxDate instead.} -->
+        <!-- The last year (inclusive), for example "2010". {@deprecated Use maxDate instead.} -->
         <attr name="endYear" format="integer" />
-        <!-- Whether the spinners are shown. -->
-        <attr name="spinnersShown" format="boolean" />
-        <!-- Whether the calendar view is shown. -->
-        <attr name="calendarViewShown" format="boolean" />
+
+        <!-- The first day of week according to {@link java.util.Calendar}. -->
+        <attr name="firstDayOfWeek" />
         <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="minDate" format="string" />
         <!-- The maximal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="maxDate" format="string" />
-        <!-- The first day of week according to {@link java.util.Calendar}. -->
-        <attr name="firstDayOfWeek" />
+
+        <!-- Whether the spinners are shown. Only valid for "spinner" mode. -->
+        <attr name="spinnersShown" format="boolean" />
+        <!-- Whether the calendar view is shown. Only valid for "spinner" mode. -->
+        <attr name="calendarViewShown" format="boolean" />
+
         <!-- @hide The layout of the date picker. -->
         <attr name="internalLayout" format="reference"  />
         <!-- @hide The layout of the legacy DatePicker. -->
         <attr name="legacyLayout" />
-        <!-- The background color for the date selector 's day of week. -->
-        <attr name="dayOfWeekBackground" format="color|reference" />
-        <!-- The text color for the date selector's day of week. -->
-        <attr name="dayOfWeekTextAppearance" format="reference" />
-        <!-- The month's text appearance in the date selector. -->
-        <attr name="headerMonthTextAppearance" format="reference" />
-        <!-- The day of month's text appearance in the date selector. -->
-        <attr name="headerDayOfMonthTextAppearance" format="reference" />
-        <!-- The year's text appearance in the date selector. -->
-        <attr name="headerYearTextAppearance" format="reference" />
-        <!-- The background for the date selector. -->
+
+        <!-- The text color for the selected date header text, ex. "2014" or
+             "Tue, Mar 18". This should be a color state list where the
+             activated state will be used when the year picker or day picker is
+             active.-->
+        <attr name="headerTextColor" format="color" />
+        <!-- The background for the selected date header. -->
         <attr name="headerBackground" />
+
         <!-- The list year's text appearance in the list. -->
         <attr name="yearListItemTextAppearance" format="reference" />
-        <!-- The list year's selected circle color in the list. -->
-        <attr name="yearListSelectorColor" format="color" />
+        <!-- @hide The list year's text appearance in the list when activated. -->
+        <attr name="yearListItemActivatedTextAppearance" format="reference" />
         <!-- The text color list of the calendar. -->
         <attr name="calendarTextColor" format="color" />
-        <!-- @hide The activated background color for the calendar. -->
-        <attr name="calendarDayBackgroundColor" format="color" />
         <!-- Defines the look of the widget. Prior to the L release, the only choice was
              spinner. As of L, with the Material theme selected, the default layout is calendar,
              but this attribute can be used to force spinner to be used instead. -->
@@ -4492,6 +4488,19 @@
             <!-- Date picker with calendar to select the date. -->
             <enum name="calendar" value="2" />
         </attr>
+
+        <!-- @deprecated The text appearance for the month (ex. May) in the selected date header. -->
+        <attr name="headerMonthTextAppearance" format="reference" />
+        <!-- @deprecated The text appearance for the day of month (ex. 28) in the selected date header. -->
+        <attr name="headerDayOfMonthTextAppearance" format="reference" />
+        <!-- The text appearance for the year (ex. 2014) in the selected date header. -->
+        <attr name="headerYearTextAppearance" format="reference" />
+        <!-- @deprecated The background color for the header's day of week. -->
+        <attr name="dayOfWeekBackground" format="color" />
+        <!-- @deprecated The text color for the header's day of week. -->
+        <attr name="dayOfWeekTextAppearance" format="reference" />
+        <!-- @deprecated The list year's selected circle color in the list. -->
+        <attr name="yearListSelectorColor" format="color" />
     </declare-styleable>
 
     <declare-styleable name="TwoLineListItem">
@@ -4709,35 +4718,42 @@
     <declare-styleable name="CalendarView">
         <!-- The first day of week according to {@link java.util.Calendar}. -->
         <attr name="firstDayOfWeek" format="integer" />
-        <!-- Whether do show week numbers. -->
-        <attr name="showWeekNumber" format="boolean" />
         <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="minDate" />
         <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="maxDate" />
-        <!-- The number of weeks to be shown. -->
-        <attr name="shownWeekCount" format="integer"/>
-        <!-- The background color for the selected week. -->
-        <attr name="selectedWeekBackgroundColor" format="color|reference" />
-        <!-- The color for the dates of the focused month. -->
-        <attr name="focusedMonthDateColor" format="color|reference" />
-        <!-- The color for the dates of an unfocused month. -->
-        <attr name="unfocusedMonthDateColor" format="color|reference" />
-        <!-- The color for the week numbers. -->
-        <attr name="weekNumberColor" format="color|reference" />
-        <!-- The color for the separator line between weeks. -->
-        <attr name="weekSeparatorLineColor" format="color|reference" />
-        <!-- Drawable for the vertical bar shown at the beginning and at the end of the selected date. -->
-        <attr name="selectedDateVerticalBar" format="reference" />
-        <!-- The text appearance for the week day abbreviation of the calendar header. -->
+        <!-- The text appearance for the month and year in the calendar header. -->
+        <attr name="monthTextAppearance" format="reference" />
+        <!-- The text appearance for the week day abbreviation in the calendar header. -->
         <attr name="weekDayTextAppearance" format="reference" />
-        <!-- The text appearance for the calendar dates. -->
+        <!-- The text appearance for the day numbers in the calendar grid. -->
         <attr name="dateTextAppearance" format="reference" />
-        <!-- The number of weeks to be shown. -->
+        <!-- @hide The background color used for the day selection indicator. -->
+        <attr name="daySelectorColor" format="color" />
+        <!-- @hide The background color used for the day highlight indicator. -->
+        <attr name="dayHighlightColor" format="color" />
+        <!-- @hide Which style of calendar delegate to use. -->
         <attr name="calendarViewMode">
             <enum name="holo" value="0" />
             <enum name="material" value="1" />
         </attr>
+
+        <!-- @deprecated Whether do show week numbers. -->
+        <attr name="showWeekNumber" format="boolean" />
+        <!-- @deprecated The number of weeks to be shown. -->
+        <attr name="shownWeekCount" format="integer"/>
+        <!-- @deprecated The background color for the selected week. -->
+        <attr name="selectedWeekBackgroundColor" format="color|reference" />
+        <!-- @deprecated The color for the dates of the focused month. -->
+        <attr name="focusedMonthDateColor" format="color|reference" />
+        <!-- @deprecated The color for the dates of an unfocused month. -->
+        <attr name="unfocusedMonthDateColor" format="color|reference" />
+        <!-- @deprecated The color for the week numbers. -->
+        <attr name="weekNumberColor" format="color|reference" />
+        <!-- @deprecated The color for the separator line between weeks. -->
+        <attr name="weekSeparatorLineColor" format="color|reference" />
+        <!-- @deprecated Drawable for the vertical bar shown at the beginning and at the end of the selected date. -->
+        <attr name="selectedDateVerticalBar" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="NumberPicker">
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index da68c92..1cb39f0 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -16,16 +16,19 @@
 
 <!-- Colors specific to Material themes. -->
 <resources>
-    <color name="background_material_dark">#ff303030</color>
-    <color name="background_material_light">#fffafafa</color>
-    <color name="background_floating_material_dark">#ff424242</color>
-    <color name="background_floating_material_light">#ffffffff</color>
+    <color name="foreground_material_dark">@color/white</color>
+    <color name="foreground_material_light">@color/black</color>
 
-    <color name="primary_material_dark">#ff212121</color>
-    <color name="primary_material_light">#fff5f5f5</color>
-    <color name="primary_dark_material_dark">#ff000000</color>
-    <color name="primary_dark_material_light">#ff757575</color>
-    <color name="primary_dark_material_light_light_status_bar">#ffe0e0e0</color>
+    <color name="background_material_dark">@color/material_grey_850</color>
+    <color name="background_material_light">@color/material_grey_50</color>
+    <color name="background_floating_material_dark">@color/material_grey_800</color>
+    <color name="background_floating_material_light">@color/white</color>
+
+    <color name="primary_material_dark">@color/material_grey_900</color>
+    <color name="primary_material_light">@color/material_grey_100</color>
+    <color name="primary_dark_material_dark">@color/black</color>
+    <color name="primary_dark_material_light">@color/material_grey_600</color>
+    <color name="primary_dark_material_light_light_status_bar">@color/material_grey_300</color>
 
     <color name="accent_material_light">@color/material_deep_teal_500</color>
     <color name="accent_material_dark">@color/material_deep_teal_200</color>
@@ -38,19 +41,20 @@
     <color name="switch_thumb_disabled_material_dark">#ff616161</color>
     <color name="switch_thumb_disabled_material_light">#ffbdbdbd</color>
 
-    <color name="foreground_material_dark">@color/white</color>
-    <color name="foreground_material_light">@color/black</color>
-
-    <color name="link_text_material_dark">@color/material_deep_teal_200</color>
     <color name="link_text_material_light">@color/material_deep_teal_500</color>
+    <color name="link_text_material_dark">@color/material_deep_teal_200</color>
 
     <!-- Text & foreground colors -->
     <eat-comment />
 
+    <!-- 87% black -->
     <color name="primary_text_default_material_light">#de000000</color>
+    <!-- 54% black -->
     <color name="secondary_text_default_material_light">#8a000000</color>
 
+    <!-- 100% white -->
     <color name="primary_text_default_material_dark">#ffffffff</color>
+    <!-- 70% white -->
     <color name="secondary_text_default_material_dark">#b3ffffff</color>
 
     <item name="hint_alpha_material_dark" format="float" type="dimen">0.50</item>
@@ -66,6 +70,14 @@
     <!-- Primary & accent colors -->
     <eat-comment />
 
+    <color name="material_grey_900">#ff212121</color>
+    <color name="material_grey_850">#ff303030</color>
+    <color name="material_grey_800">#ff424242</color>
+    <color name="material_grey_600">#ff757575</color>
+    <color name="material_grey_300">#ffe0e0e0</color>
+    <color name="material_grey_100">#fff5f5f5</color>
+    <color name="material_grey_50">#fffafafa</color>
+
     <color name="material_deep_teal_200">#ff80cbc4</color>
     <color name="material_deep_teal_500">#ff009688</color>
 
@@ -98,16 +110,16 @@
     <color name="datepicker_default_disabled_text_color_material_light">#80999999</color>
     <color name="datepicker_default_disabled_text_color_material_dark">#80999999</color>
 
-    <color name="datepicker_default_selected_text_color_material_light">#33b5e5</color>
-    <color name="datepicker_default_selected_text_color_material_dark">#33b5e5</color>
+    <color name="datepicker_default_selected_text_color_material_light">#ff33b5e5</color>
+    <color name="datepicker_default_selected_text_color_material_dark">#ff33b5e5</color>
 
-    <color name="datepicker_default_pressed_text_color_material_light">#0099cc</color>
-    <color name="datepicker_default_pressed_text_color_material_dark">#0099cc</color>
+    <color name="datepicker_default_pressed_text_color_material_light">#ff0099cc</color>
+    <color name="datepicker_default_pressed_text_color_material_dark">#ff0099cc</color>
 
     <color name="datepicker_default_circle_background_color_material_light">@color/material_deep_teal_500</color>
     <color name="datepicker_default_circle_background_color_material_dark">@color/material_deep_teal_200</color>
 
-    <color name="datepicker_default_view_animator_color_material_light">#f2f2f2</color>
+    <color name="datepicker_default_view_animator_color_material_light">#fff2f2f2</color>
     <color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
 
 </resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 8d2afde..6fd39f6 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -143,9 +143,7 @@
     <dimen name="timepicker_text_size_inner">12sp</dimen>
 
     <!-- Material date picker dimensions. -->
-    <dimen name="datepicker_year_picker_padding_top">8dp</dimen>
     <dimen name="datepicker_year_label_height">64dp</dimen>
-    <dimen name="datepicker_year_label_text_size">22dp</dimen>
     <dimen name="datepicker_component_width">260dp</dimen>
     <dimen name="datepicker_dialog_width">520dp</dimen>
     <dimen name="datepicker_selected_date_day_size">88dp</dimen>
@@ -154,10 +152,24 @@
     <dimen name="datepicker_header_height">30dp</dimen>
     <dimen name="datepicker_header_text_size">14dp</dimen>
 
+    <dimen name="datepicker_list_year_label_size">16sp</dimen>
+    <dimen name="datepicker_list_year_activated_label_size">26sp</dimen>
+
+    <dimen name="date_picker_year_label_size">16sp</dimen>
+    <dimen name="date_picker_date_label_size">34dp</dimen>
+
     <!-- Used by Material-style SimpleMonthView -->
-    <dimen name="datepicker_day_number_size">12sp</dimen>
-    <dimen name="datepicker_month_label_size">14sp</dimen>
-    <dimen name="datepicker_month_day_label_text_size">12sp</dimen>
-    <dimen name="datepicker_month_list_item_header_height">48dp</dimen>
+    <dimen name="date_picker_month_text_size">14sp</dimen>
+    <dimen name="date_picker_day_of_week_text_size">12sp</dimen>
+    <dimen name="date_picker_day_text_size">12sp</dimen>
+    <dimen name="date_picker_month_height">56dp</dimen>
+    <dimen name="date_picker_day_of_week_height">36dp</dimen>
+    <dimen name="date_picker_day_height">40dp</dimen>
+    <dimen name="date_picker_day_width">44dp</dimen>
+    <dimen name="date_picker_day_selector_radius">20dp</dimen>
+    <dimen name="day_picker_padding_horizontal">20dp</dimen>
+    <dimen name="day_picker_padding_top">6dp</dimen>
+    <dimen name="day_picker_button_margin_top">0dp</dimen>
+
     <dimen name="datepicker_view_animator_height">226dp</dimen>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 19cae03..7672e93 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5042,18 +5042,6 @@
     <!-- Accessibility announcement for minute circular picker [CHAR LIMIT=NONE] -->
     <string name="select_minutes">Select minutes</string>
 
-    <!--
-        Content description for the month and day selector in the date picker, which displays
-        a selectable grid of days laid out by month.
-        [CHAR LIMIT=50]
-     -->
-    <string name="day_picker_description">Month grid of days</string>
-    <!--
-        Content description for the year selector in the date picker, which displays
-        a scrolling, vertical list of years.
-        [CHAR LIMIT=50]
-     -->
-    <string name="year_picker_description">Year list</string>
     <!-- Accessibility announcement for the day picker [CHAR LIMIT=NONE] -->
     <string name="select_day">Select month and day</string>
     <!-- Accessibility announcement for the year picker [CHAR LIMIT=NONE] -->
@@ -5079,7 +5067,11 @@
     <string name="sans_serif">sans-serif</string>
 
     <!-- DO NOT TRANSLATE -->
-    <string name="day_of_week_label_typeface">sans-serif</string>
+    <string name="date_picker_month_typeface">sans-serif-medium</string>
+    <!-- DO NOT TRANSLATE -->
+    <string name="date_picker_day_of_week_typeface">sans-serif-medium</string>
+    <!-- DO NOT TRANSLATE -->
+    <string name="date_picker_day_typeface">sans-serif-medium</string>
 
     <!-- Notify use that they are in Lock-to-app -->
     <string name="lock_to_app_toast">To unpin this screen, touch and hold Back and Overview at the same time.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a8ab18d..f1f7462 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -372,11 +372,13 @@
     <style name="TextAppearance.Material.WindowTitle" parent="TextAppearance.Material.Title" />
     <style name="TextAppearance.Material.DialogWindowTitle" parent="TextAppearance.Material.Title" />
 
-    <style name="TextAppearance.Material.CalendarViewWeekDayView" parent="TextAppearance.Material.Small">
-        <item name="textStyle">bold</item>
-        <item name="textColor">#505050</item>
+    <style name="TextAppearance.Material.Widget.Calendar.Day" parent="TextAppearance.Material.Caption">
+        <item name="textColor">?attr/textColorPrimaryActivated</item>
     </style>
 
+    <style name="TextAppearance.Material.Widget.Calendar.DayOfWeek" parent="TextAppearance.Material.Caption" />
+    <style name="TextAppearance.Material.Widget.Calendar.Month" parent="TextAppearance.Material.Body2" />
+
     <style name="TextAppearance.Material.TimePicker.TimeLabel" parent="TextAppearance.Material">
         <item name="textSize">@dimen/timepicker_time_label_size</item>
         <item name="textColor">@color/time_picker_header_text_material</item>
@@ -406,14 +408,27 @@
     </style>
 
     <style name="TextAppearance.Material.DatePicker.YearLabel" parent="TextAppearance.Material">
-        <item name="includeFontPadding">false</item>
         <item name="textColor">@color/date_picker_header_text_material</item>
-        <item name="textSize">@dimen/datepicker_selected_date_year_size</item>
+        <item name="textSize">@dimen/date_picker_year_label_size</item>
+        <item name="fontFamily">sans-serif-medium</item>
+    </style>
+
+    <style name="TextAppearance.Material.DatePicker.DateLabel" parent="TextAppearance.Material">
+        <item name="textColor">@color/date_picker_header_text_material</item>
+        <item name="textSize">@dimen/date_picker_date_label_size</item>
+        <item name="fontFamily">sans-serif-medium</item>
     </style>
 
     <style name="TextAppearance.Material.DatePicker.List.YearLabel" parent="TextAppearance.Material">
-        <item name="textColor">?attr/textColorSecondaryActivated</item>
-        <item name="textSize">@dimen/datepicker_year_label_text_size</item>
+        <item name="textColor">?attr/textColorPrimary</item>
+        <item name="textSize">@dimen/datepicker_list_year_label_size</item>
+        <item name="fontFamily">sans-serif</item>
+    </style>
+
+    <style name="TextAppearance.Material.DatePicker.List.YearLabel.Activated">
+        <item name="textColor">?attr/colorControlActivated</item>
+        <item name="textSize">@dimen/datepicker_list_year_activated_label_size</item>
+        <item name="fontFamily">sans-serif-medium</item>
     </style>
 
     <style name="TextAppearance.Material.Notification">
@@ -487,7 +502,8 @@
     <!-- Alert dialog button bar button -->
     <style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
         <item name="minWidth">64dp</item>
-        <item name="maxLines">2</item>
+        <item name="singleLine">true</item>
+        <item name="ellipsize">none</item>
         <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
     </style>
 
@@ -615,14 +631,13 @@
     </style>
 
     <style name="Widget.Material.CalendarView" parent="Widget.CalendarView">
-        <item name="selectedWeekBackgroundColor">#330099FF</item>
-        <item name="focusedMonthDateColor">#FFFFFFFF</item>
-        <item name="unfocusedMonthDateColor">#66FFFFFF</item>
-        <item name="weekNumberColor">#33FFFFFF</item>
-        <item name="weekSeparatorLineColor">#19FFFFFF</item>
-        <item name="selectedDateVerticalBar">@drawable/day_picker_week_view_dayline_holo</item>
-        <item name="weekDayTextAppearance">@style/TextAppearance.Material.CalendarViewWeekDayView</item>
         <item name="calendarViewMode">material</item>
+
+        <item name="monthTextAppearance">@style/TextAppearance.Material.Widget.Calendar.Month</item>
+        <item name="weekDayTextAppearance">@style/TextAppearance.Material.Widget.Calendar.DayOfWeek</item>
+        <item name="dateTextAppearance">@style/TextAppearance.Material.Widget.Calendar.Day</item>
+        <item name="daySelectorColor">?attr/colorControlActivated</item>
+        <item name="dayHighlightColor">?attr/colorControlHighlight</item>
     </style>
 
     <style name="Widget.Material.ImageButton" parent="Widget.ImageButton">
@@ -647,11 +662,11 @@
         <item name="internalLayout">@layout/time_picker_material</item>
         <item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
         <item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
-        <item name="headerBackground">@drawable/time_picker_header_material</item>
+        <item name="headerBackground">#ff555555</item>
         <item name="numbersTextColor">?attr/textColorPrimaryActivated</item>
         <item name="numbersInnerTextColor">?attr/textColorSecondaryActivated</item>
-        <item name="numbersBackgroundColor">#10ffffff</item>
         <item name="numbersSelectorColor">?attr/colorControlActivated</item>
+        <item name="numbersBackgroundColor">#ff555555</item>
         <item name="amPmTextColor">?attr/textColorSecondary</item>
     </style>
 
@@ -660,17 +675,10 @@
         <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- Attributes for new-style DatePicker. -->
-        <item name="internalLayout">@layout/date_picker_holo</item>
-        <item name="dayOfWeekBackground">#10000000</item>
-        <item name="dayOfWeekTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfWeekLabel</item>
-        <item name="headerMonthTextAppearance">@style/TextAppearance.Material.DatePicker.MonthLabel</item>
-        <item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfMonthLabel</item>
-        <item name="headerYearTextAppearance">@style/TextAppearance.Material.DatePicker.YearLabel</item>
-        <item name="headerBackground">?attr/colorAccent</item>
+        <item name="internalLayout">@layout/date_picker_material</item>
         <item name="yearListItemTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
-        <item name="yearListSelectorColor">?attr/colorControlActivated</item>
-        <item name="calendarTextColor">?attr/textColorSecondaryActivated</item>
-        <item name="calendarDayBackgroundColor">?attr/colorControlActivated</item>
+        <item name="yearListItemActivatedTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel.Activated</item>
+        <item name="headerBackground">#ff555555</item>
     </style>
 
     <style name="Widget.Material.ActivityChooserView" parent="Widget.ActivityChooserView">
@@ -1021,24 +1029,18 @@
     <style name="Widget.Material.Light.GestureOverlayView" parent="Widget.Material.GestureOverlayView"/>
     <style name="Widget.Material.Light.GridView" parent="Widget.Material.GridView"/>
     <style name="Widget.Material.Light.ImageButton" parent="Widget.Material.ImageButton"/>
-
-    <style name="Widget.Material.Light.CalendarView" parent="Widget.CalendarView">
-        <item name="selectedWeekBackgroundColor">#330066ff</item>
-        <item name="focusedMonthDateColor">#FF000000</item>
-        <item name="unfocusedMonthDateColor">#7F08002B</item>
-        <item name="weekNumberColor">#7F080021</item>
-        <item name="weekSeparatorLineColor">#7F08002A</item>
-        <item name="weekDayTextAppearance">@style/TextAppearance.Material.CalendarViewWeekDayView</item>
-        <item name="calendarViewMode">material</item>
-    </style>
-
+    <style name="Widget.Material.Light.CalendarView" parent="Widget.Material.CalendarView" />
     <style name="Widget.Material.Light.NumberPicker" parent="Widget.Material.NumberPicker"/>
 
     <style name="Widget.Material.Light.TimePicker" parent="Widget.Material.TimePicker">
-        <item name="numbersBackgroundColor">#10000000</item>
+        <item name="headerBackground">?attr/colorAccent</item>
+        <item name="numbersBackgroundColor">#ffeeeeee</item>
     </style>
 
-    <style name="Widget.Material.Light.DatePicker" parent="Widget.Material.DatePicker" />
+    <style name="Widget.Material.Light.DatePicker" parent="Widget.Material.DatePicker">
+        <item name="headerBackground">?attr/colorAccent</item>
+    </style>
+
     <style name="Widget.Material.Light.ActivityChooserView" parent="Widget.Material.ActivityChooserView" />
     <style name="Widget.Material.Light.ImageWell" parent="Widget.Material.ImageWell"/>
     <style name="Widget.Material.Light.ListView" parent="Widget.Material.ListView"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 203b017..c4e9e8e 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1988,7 +1988,7 @@
   <java-symbol type="layout" name="time_picker_material" />
   <java-symbol type="layout" name="time_picker_header_material" />
   <java-symbol type="layout" name="year_label_text_view" />
-  <java-symbol type="layout" name="date_picker_holo" />
+  <java-symbol type="layout" name="date_picker_material" />
 
   <java-symbol type="id" name="time_header" />
   <java-symbol type="id" name="hours" />
@@ -1999,11 +1999,8 @@
   <java-symbol type="id" name="radial_picker" />
   <java-symbol type="id" name="separator" />
   <java-symbol type="id" name="date_picker_header" />
-  <java-symbol type="id" name="date_picker_month_and_day_layout" />
-  <java-symbol type="id" name="day_picker_selector_layout" />
-  <java-symbol type="id" name="date_picker_month" />
-  <java-symbol type="id" name="date_picker_day" />
-  <java-symbol type="id" name="date_picker_year" />
+  <java-symbol type="id" name="date_picker_header_year" />
+  <java-symbol type="id" name="date_picker_header_date" />
   <java-symbol type="id" name="animator" />
 
   <java-symbol type="string" name="done_label" />
@@ -2039,19 +2036,24 @@
   <java-symbol type="string" name="muted_by" />
 
   <java-symbol type="string" name="item_is_selected" />
-  <java-symbol type="string" name="day_of_week_label_typeface" />
   <java-symbol type="string" name="select_day" />
-  <java-symbol type="string" name="day_picker_description" />
   <java-symbol type="string" name="select_year" />
-  <java-symbol type="string" name="year_picker_description" />
 
-  <java-symbol type="dimen" name="datepicker_day_number_size" />
-  <java-symbol type="dimen" name="datepicker_month_label_size" />
-  <java-symbol type="dimen" name="datepicker_month_day_label_text_size" />
-  <java-symbol type="dimen" name="datepicker_month_list_item_header_height" />
+  <java-symbol type="string" name="date_picker_month_typeface" />
+  <java-symbol type="string" name="date_picker_day_of_week_typeface" />
+  <java-symbol type="string" name="date_picker_day_typeface" />
+  <java-symbol type="dimen" name="date_picker_month_text_size" />
+  <java-symbol type="dimen" name="date_picker_day_of_week_text_size" />
+  <java-symbol type="dimen" name="date_picker_day_text_size" />
+  <java-symbol type="dimen" name="date_picker_month_height" />
+  <java-symbol type="dimen" name="date_picker_day_height" />
+  <java-symbol type="dimen" name="date_picker_day_width" />
+  <java-symbol type="dimen" name="date_picker_day_selector_radius" />
+  <java-symbol type="id" name="date_picker_day_picker" />
+  <java-symbol type="id" name="date_picker_year_picker" />
+
   <java-symbol type="dimen" name="datepicker_view_animator_height" />
   <java-symbol type="dimen" name="datepicker_year_label_height" />
-  <java-symbol type="dimen" name="datepicker_year_picker_padding_top" />
 
   <java-symbol type="array" name="config_clockTickVibePattern" />
   <java-symbol type="array" name="config_calendarDateVibePattern" />
@@ -2115,7 +2117,6 @@
   <java-symbol type="id" name="transitionTransform" />
   <java-symbol type="id" name="parentMatrix" />
   <java-symbol type="bool" name="config_auto_attach_data_on_creation" />
-  <java-symbol type="id" name="date_picker_month_day_year_layout" />
   <java-symbol type="attr" name="closeItemLayout" />
   <java-symbol type="layout" name="resolver_different_item_header" />
   <java-symbol type="array" name="config_default_vm_number" />
@@ -2167,4 +2168,10 @@
   <java-symbol type="integer" name="config_screen_magnification_multi_tap_adjustment" />
   <java-symbol type="dimen" name="config_screen_magnification_scaling_threshold" />
   <java-symbol type="dimen" name="timepicker_selector_stroke"/>
+
+  <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.Month" />
+  <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.DayOfWeek" />
+  <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.Day" />
+  <java-symbol type="dimen" name="day_picker_padding_top"/>
+  <java-symbol type="dimen" name="date_picker_day_of_week_height"/>
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 38cfecd..9931d00 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -857,6 +857,7 @@
     <!-- Theme overlay that overrides window properties to display as a dialog. -->
     <style name="ThemeOverlay.Material.Dialog">
         <item name="colorBackgroundCacheHint">@null</item>
+        <item name="colorBackground">?attr/colorBackgroundFloating</item>
 
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
@@ -1271,7 +1272,6 @@
     <style name="Theme.Material.Settings" parent="Theme.Material.DayNight.DarkActionBar">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_500</item>
 
         <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
         <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
@@ -1281,7 +1281,6 @@
     <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.DayNight.BaseDialog">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
@@ -1289,7 +1288,6 @@
     <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.DayNight.Dialog.BaseAlert">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
@@ -1297,7 +1295,6 @@
     <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.DayNight.Dialog.Presentation">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.DayNight.SearchBar">
@@ -1309,6 +1306,5 @@
     <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.DayNight.CompactMenu">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 </resources>
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 1433c79..d10df3e 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -435,7 +435,7 @@
     Image_unlockIfLocked(env, image);
 
     // Set timestamp
-    ALOGV("timestamp to be queued: %lld", timestampNs);
+    ALOGV("timestamp to be queued: %" PRId64, timestampNs);
     res = native_window_set_buffers_timestamp(anw.get(), timestampNs);
     if (res != OK) {
         jniThrowRuntimeException(env, "Set timestamp failed");
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 34e4beb..d234701 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk nie"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi af"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Geen gestoorde netwerke beskikbaar nie"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Saai uit"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Saai tans uit"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Onbenoemde toestel"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Gereed om uit te saai"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 104067a..2bcb2c1 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -261,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"‏إيقاف Wi-Fi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"لا تتوفر أية شبكة محفوظة"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"إرسال"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"جارٍ الإرسال"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"جهاز لا يحمل اسمًا"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"جاهز للإرسال"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 9ac2a64..ee3f826 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No saved networks available"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unnamed device"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ready to cast"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 9ac2a64..ee3f826 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No saved networks available"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unnamed device"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ready to cast"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 9ac2a64..ee3f826 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No saved networks available"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unnamed device"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ready to cast"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 398e0b0..18d8f76 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"شبکه‌ای موجود نیست"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"‏Wi-Fi خاموش است"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"شبکه ذخیره شده‌ای در دسترس نیست"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"فرستادن"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"در حال فرستادن"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"دستگاه بدون نام"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"آماده برای فرستادن"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 66a7df0..5bf8d13 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tidak Ada Jaringan"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Mati"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Jaringan yang tersimpan tak tersedia"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Transmisi"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Melakukan transmisi"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Perangkat tanpa nama"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Siap melakukan transmisi"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index b5e1bfe..6ae0c71 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ບໍ່ມີເຄືອຂ່າຍ"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi​-Fi ປິດ"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"ບໍ່​ມີ​ເຄືອ​ຂ່າຍ​ທີ່​ບັນ​ທຶກ​ໄວ້​ທີ່​ສາ​ມາດ​ໃຊ້​ໄດ້"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ຄາສທ໌"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"​ກຳ​ລັງ​ສົ່ງ​ສັນ​ຍານ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"​ອຸ​ປະ​ກອນບໍ່​ມີ​ຊື່"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"​ພ້ອ​ມ​ສົ່ງ​ສັນ​ຍານ​ແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index a767983..f7268c2 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -255,8 +255,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Сүлжээгүй"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi унтарсан"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Хадгалагдсан сүлжээ байхгүй"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Дамжуулах"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Дамжуулж байна"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Нэргүй төхөөрөмж"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Дамжуулахад бэлэн"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index b6feaa2..58e5239 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ကွန်ရက်မရှိပါ"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ဝိုင်ဖိုင်ပိတ်ရန်"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"သိမ်းဆည်းထား ကွန်ရက်များ မရှိ"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"ကာစ်တင်"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"အမည်မတပ် ကိရိယာ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ကာစ်တ် လုပ်ရန် အသင့် ရှိနေပြီ"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 71247d9..3d5d213 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"नेटवर्क छैन"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाइफाइ बन्द"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"उपलब्ध सञ्जाल सुरक्षित गरिएन"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"प्रसारण गर्दै"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"बेनाम उपकरण"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"प्रसारण गर्न तयार"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index becf69d..ef864de 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ජාලයක් නැත"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi අක්‍රියයි"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"තිබෙන ජාල සුරැකුවේ නැත"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"කාස්ට් කිරීම"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"නම් නොකළ උපාංගය"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"කාස්ට් කිරීමට සුදානම්"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 493c9e7..f60a85a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -257,8 +257,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Naka-off ang Wi-Fi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Walang available na naka-save na mga network"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"I-cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Nagka-cast"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Walang pangalang device"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Handang mag-cast"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 78eadee..6636693 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -259,8 +259,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網絡"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 關閉"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"找不到已儲存的網絡"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"投放"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"正在放送"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"未命名的裝置"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"放送準備完成"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 7f1e876..2d1fab0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -385,7 +385,7 @@
         }
 
         // Return early if there are no tasks in the focused stack
-        if (focusedStack.getTaskCount() == 0) return;
+        if (focusedStack == null || focusedStack.getTaskCount() == 0) return;
 
         ActivityManager.RunningTaskInfo runningTask = mSystemServicesProxy.getTopMostTask();
         // Return early if there is no running task (can't determine affiliated tasks in this case)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9263543..abeb2b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -292,7 +292,7 @@
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) != 0;
         lockToAppEnabled = ssp.getSystemSetting(context,
                 Settings.System.LOCK_TO_APP_ENABLED) != 0;
-        multiStackEnabled = "1".equals(ssp.getSystemProperty("overview.enableMultiStack"));
+        multiStackEnabled = "true".equals(ssp.getSystemProperty("persist.sys.debug.multi_window"));
     }
 
     /** Called when the configuration has changed, and we want to reset any configuration specific
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ca08319..56801e5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -124,9 +124,6 @@
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
         mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
         mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
-        if (mConfig.multiStackEnabled) {
-            mMoveTaskButton.setVisibility(View.VISIBLE);
-        }
 
         // Hide the backgrounds if they are ripple drawables
         if (!Constants.DebugFlags.App.EnableTaskFiltering) {
@@ -209,6 +206,7 @@
                 mLightDismissDrawable : mDarkDismissDrawable);
         mDismissButton.setContentDescription(String.format(mDismissContentDescription,
                 t.activityLabel));
+        mMoveTaskButton.setVisibility((mConfig.multiStackEnabled) ? View.VISIBLE : View.INVISIBLE);
     }
 
     /** Unbinds the bar view from the task */
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 87dc420..64f3070 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -157,7 +157,6 @@
     @Override
     public void onStart() {
         final Context context = getContext();
-        mTwilightManager = getLocalService(TwilightManager.class);
 
         final PowerManager powerManager =
                 (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -188,7 +187,11 @@
         mNightMode = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.UI_NIGHT_MODE, defaultNightMode);
 
-        mTwilightManager.registerListener(mTwilightListener, mHandler);
+        // Update the initial, static configurations.
+        synchronized (this) {
+            updateConfigurationLocked();
+            sendConfigurationLocked();
+        }
 
         publishBinderService(Context.UI_MODE_SERVICE, mService);
     }
@@ -297,8 +300,11 @@
                     pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
             pw.print("  mHoldingConfiguration="); pw.print(mHoldingConfiguration);
                     pw.print(" mSystemReady="); pw.println(mSystemReady);
-            pw.print("  mTwilightService.getCurrentState()=");
-                    pw.println(mTwilightManager.getCurrentState());
+            if (mTwilightManager != null) {
+                // We may not have a TwilightManager.
+                pw.print("  mTwilightService.getCurrentState()=");
+                pw.println(mTwilightManager.getCurrentState());
+            }
         }
     }
 
@@ -306,6 +312,10 @@
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
             synchronized (mLock) {
+                mTwilightManager = getLocalService(TwilightManager.class);
+                if (mTwilightManager != null) {
+                    mTwilightManager.registerListener(mTwilightListener, mHandler);
+                }
                 mSystemReady = true;
                 mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
                 updateComputedNightModeLocked();
@@ -623,9 +633,11 @@
     }
 
     private void updateComputedNightModeLocked() {
-        TwilightState state = mTwilightManager.getCurrentState();
-        if (state != null) {
-            mComputedNightMode = state.isNight();
+        if (mTwilightManager != null) {
+            TwilightState state = mTwilightManager.getCurrentState();
+            if (state != null) {
+                mComputedNightMode = state.isNight();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a530dfa..65949bf 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -55,6 +55,7 @@
 import android.speech.RecognizerIntent;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.KeyEvent;
 
@@ -743,15 +744,23 @@
                 Log.w(TAG, "Attempted to dispatch null or non-media key event.");
                 return;
             }
+
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
-            if (DEBUG) {
-                Log.d(TAG, "dispatchMediaKeyEvent, pid=" + pid + ", uid=" + uid + ", event="
-                        + keyEvent);
-            }
-
             try {
+                if (DEBUG) {
+                    Log.d(TAG, "dispatchMediaKeyEvent, pid=" + pid + ", uid=" + uid + ", event="
+                            + keyEvent);
+                }
+                if (!isUserSetupComplete()) {
+                    // Global media key handling can have the side-effect of starting new
+                    // activities which is undesirable while setup is in progress.
+                    Slog.i(TAG, "Not dispatching media key event because user "
+                            + "setup is in progress.");
+                    return;
+                }
+
                 synchronized (mLock) {
                     // If we don't have a media button receiver to fall back on
                     // include non-playing sessions for dispatching
@@ -1025,6 +1034,11 @@
             return keyCode == KeyEvent.KEYCODE_HEADSETHOOK;
         }
 
+        private boolean isUserSetupComplete() {
+            return Settings.Secure.getIntForUser(getContext().getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+        }
+
         // we only handle public stream types, which are 0-5
         private boolean isValidLocalStreamType(int streamType) {
             return streamType >= AudioManager.STREAM_VOICE_CALL
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 6d09f55..b61a6f7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -373,10 +373,8 @@
             mService.requestTraversalLocked();
         }
 
-        mAnimationBackgroundSurface.destroySurface();
-        mAnimationBackgroundSurface = null;
-        mDimLayer.destroySurface();
-        mDimLayer = null;
+        close();
+
         mDisplayContent = null;
     }
 
@@ -501,8 +499,14 @@
     }
 
     void close() {
-        mDimLayer.mDimSurface.destroy();
-        mAnimationBackgroundSurface.mDimSurface.destroy();
+        if (mAnimationBackgroundSurface != null) {
+            mAnimationBackgroundSurface.destroySurface();
+            mAnimationBackgroundSurface = null;
+        }
+        if (mDimLayer != null) {
+            mDimLayer.destroySurface();
+            mDimLayer = null;
+        }
     }
 
     public void dump(String prefix, PrintWriter pw) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index bcd8d42..ae2c54b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -564,6 +564,10 @@
             }
         }
 
+        // We start this here so that we update our configuration to set watch or television
+        // as appropriate.
+        mSystemServiceManager.startService(UiModeManagerService.class);
+
         try {
             mPackageManagerService.performBootDexOpt();
         } catch (Throwable e) {
@@ -843,8 +847,6 @@
 
             mSystemServiceManager.startService(TwilightService.class);
 
-            mSystemServiceManager.startService(UiModeManagerService.class);
-
             mSystemServiceManager.startService(JobSchedulerService.class);
 
             if (!disableNonCoreServices) {
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 4acbd1c..80036e5 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -131,11 +131,11 @@
     }
 
     @Override
-    public View createViewFromTag(View parent, String name, AttributeSet attrs,
-            boolean inheritContext) {
+    public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
+            boolean ignoreThemeAttrs) {
         View view;
         try {
-            view = super.createViewFromTag(parent, name, attrs, inheritContext);
+            view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttrs);
         } catch (InflateException e) {
             // try to load the class from using the custom view loader
             try {
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 7a73fae..7f1e977 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -21,9 +21,11 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.Context;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.util.Xml;
 
 import java.io.IOException;
@@ -36,9 +38,13 @@
  *
  */
 public class LayoutInflater_Delegate {
-
     private static final String TAG_MERGE = "merge";
 
+    private static final String ATTR_LAYOUT = "layout";
+
+    private static final int[] ATTRS_THEME = new int[] {
+            com.android.internal.R.attr.theme };
+
     public static boolean sIsInInclude = false;
 
     /**
@@ -49,7 +55,7 @@
      */
     @LayoutlibDelegate
     /* package */ static void rInflate(LayoutInflater thisInflater, XmlPullParser parser,
-            View parent, final AttributeSet attrs, boolean finishInflate, boolean inheritContext)
+            View parent, Context context, AttributeSet attrs, boolean finishInflate)
             throws XmlPullParserException, IOException {
 
         if (finishInflate == false) {
@@ -61,7 +67,7 @@
 
         // ---- START DEFAULT IMPLEMENTATION.
 
-        thisInflater.rInflate_Original(parser, parent, attrs, finishInflate, inheritContext);
+        thisInflater.rInflate_Original(parser, parent, context, attrs, finishInflate);
 
         // ---- END DEFAULT IMPLEMENTATION.
 
@@ -74,15 +80,50 @@
     }
 
     @LayoutlibDelegate
-    public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser, View parent,
-            AttributeSet attrs, boolean inheritContext) throws XmlPullParserException, IOException {
-
+    public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser,
+            Context context, View parent, AttributeSet attrs)
+            throws XmlPullParserException, IOException {
         int type;
 
         if (parent instanceof ViewGroup) {
-            final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
+            // Apply a theme wrapper, if requested. This is sort of a weird
+            // edge case, since developers think the <include> overwrites
+            // values in the AttributeSet of the included View. So, if the
+            // included View has a theme attribute, we'll need to ignore it.
+            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
+            final int themeResId = ta.getResourceId(0, 0);
+            final boolean hasThemeOverride = themeResId != 0;
+            if (hasThemeOverride) {
+                context = new ContextThemeWrapper(context, themeResId);
+            }
+            ta.recycle();
+
+            // If the layout is pointing to a theme attribute, we have to
+            // massage the value to get a resource identifier out of it.
+            int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
             if (layout == 0) {
-                final String value = attrs.getAttributeValue(null, "layout");
+                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
+                if (value == null || value.length() <= 0) {
+                    throw new InflateException("You must specify a layout in the"
+                            + " include tag: <include layout=\"@layout/layoutID\" />");
+                }
+
+                // Attempt to resolve the "?attr/name" string to an identifier.
+                layout = context.getResources().getIdentifier(value.substring(1), null, null);
+            }
+
+            // The layout might be referencing a theme attribute.
+            // ---- START CHANGES
+            if (layout != 0) {
+                final TypedValue tempValue = new TypedValue();
+                if (context.getTheme().resolveAttribute(layout, tempValue, true)) {
+                    layout = tempValue.resourceId;
+                }
+            }
+            // ---- END CHANGES
+
+            if (layout == 0) {
+                final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
                 if (value == null) {
                     throw new InflateException("You must specifiy a layout in the"
                             + " include tag: <include layout=\"@layout/layoutID\" />");
@@ -111,13 +152,24 @@
 
                     if (TAG_MERGE.equals(childName)) {
                         // Inflate all children.
-                        thisInflater.rInflate(childParser, parent, childAttrs, false,
-                                inheritContext);
+                        thisInflater.rInflate(childParser, parent, context, childAttrs, false);
                     } else {
                         final View view = thisInflater.createViewFromTag(parent, childName,
-                                childAttrs, inheritContext);
+                                context, childAttrs, hasThemeOverride);
                         final ViewGroup group = (ViewGroup) parent;
 
+                        final TypedArray a = context.obtainStyledAttributes(
+                                attrs, com.android.internal.R.styleable.Include);
+                        final int id = a.getResourceId(
+                                com.android.internal.R.styleable.Include_id, View.NO_ID);
+                        final int visibility = a.getInt(
+                                com.android.internal.R.styleable.Include_visibility, -1);
+                        final boolean hasWidth = a.hasValue(
+                                com.android.internal.R.styleable.Include_layout_width);
+                        final boolean hasHeight = a.hasValue(
+                                com.android.internal.R.styleable.Include_layout_height);
+                        a.recycle();
+
                         // We try to load the layout params set in the <include /> tag. If
                         // they don't exist, we will rely on the layout params set in the
                         // included XML file.
@@ -127,40 +179,27 @@
                         // successfully loaded layout params from the <include /> tag,
                         // false means we need to rely on the included layout params.
                         ViewGroup.LayoutParams params = null;
-                        try {
-                            // ---- START CHANGES
-                            sIsInInclude = true;
-                            // ---- END CHANGES
+                        if (hasWidth && hasHeight) {
+                            try {
+                                // ---- START CHANGES
+                                sIsInInclude = true;
+                                // ---- END CHANGES
 
-                            params = group.generateLayoutParams(attrs);
+                                params = group.generateLayoutParams(attrs);
 
-                        } catch (RuntimeException e) {
-                            // ---- START CHANGES
-                            sIsInInclude = false;
-                            // ---- END CHANGES
-
-                            params = group.generateLayoutParams(childAttrs);
-                        } finally {
-                            // ---- START CHANGES
-                            sIsInInclude = false;
-                            // ---- END CHANGES
-
-                            if (params != null) {
-                                view.setLayoutParams(params);
+                            } finally {
+                                // ---- START CHANGES
+                                sIsInInclude = false;
+                                // ---- END CHANGES
                             }
                         }
+                        if (params == null) {
+                            params = group.generateLayoutParams(childAttrs);
+                        }
+                        view.setLayoutParams(params);
 
                         // Inflate all children.
-                        thisInflater.rInflate(childParser, view, childAttrs, true, true);
-
-                        // Attempt to override the included layout's android:id with the
-                        // one set on the <include /> tag itself.
-                        TypedArray a = thisInflater.mContext.obtainStyledAttributes(attrs,
-                            com.android.internal.R.styleable.View, 0, 0);
-                        int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
-                        // While we're at it, let's try to override android:visibility.
-                        int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
-                        a.recycle();
+                        thisInflater.rInflateChildren(childParser, view, childAttrs, true);
 
                         if (id != View.NO_ID) {
                             view.setId(id);
@@ -188,12 +227,6 @@
             throw new InflateException("<include /> can only be used inside of a ViewGroup");
         }
 
-        final int currentDepth = parser.getDepth();
-        while (((type = parser.next()) != XmlPullParser.END_TAG ||
-                parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
-            // Empty
-        }
+        LayoutInflater.consumeChildElements(parser);
     }
-
-
 }