Merge "Add Wi-Fi stress tests."
diff --git a/api/current.xml b/api/current.xml
index e63e82c..cdb6964 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -184323,6 +184323,19 @@
 <parameter name="gmtoff" type="long">
 </parameter>
 </method>
+<method name="getJulianMondayFromWeeksSinceEpoch"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="week" type="int">
+</parameter>
+</method>
 <method name="getWeekNumber"
  return="int"
  abstract="false"
@@ -184334,6 +184347,21 @@
  visibility="public"
 >
 </method>
+<method name="getWeeksSinceEpochFromJulianDay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="julianDay" type="int">
+</parameter>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
 <method name="isEpoch"
  return="boolean"
  abstract="false"
@@ -184557,6 +184585,17 @@
  visibility="public"
 >
 </field>
+<field name="MONDAY_BEFORE_JULIAN_EPOCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2440585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MONTH"
  type="int"
  transient="false"
@@ -234482,7 +234521,7 @@
 >
 <parameter name="year" type="int">
 </parameter>
-<parameter name="monthOfYear" type="int">
+<parameter name="month" type="int">
 </parameter>
 <parameter name="dayOfMonth" type="int">
 </parameter>
@@ -234534,6 +234573,172 @@
 </parameter>
 </method>
 </interface>
+<class name="DayPicker"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getSelectedDay"
+ return="java.util.Calendar"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="java.util.Calendar">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="setOnDateChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.DayPicker.OnSelectedDayChangeListener">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startRangeDate" type="java.util.Calendar">
+</parameter>
+<parameter name="endRangeDate" type="java.util.Calendar">
+</parameter>
+</method>
+<method name="setSelectedDay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectedDay" type="java.util.Calendar">
+</parameter>
+</method>
+</class>
+<interface name="DayPicker.OnSelectedDayChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSelectedDayChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.DayPicker">
+</parameter>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+</method>
+</interface>
 <class name="DialerFilter"
  extends="android.widget.RelativeLayout"
  abstract="false"
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 37f8738..efe527f 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -16,23 +16,18 @@
 
 package android.app;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Build;
 import android.os.Bundle;
-import android.text.TextUtils.TruncateAt;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.DatePicker;
-import android.widget.TextView;
 import android.widget.DatePicker.OnDateChangedListener;
 
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
 /**
  * A simple dialog containing an {@link android.widget.DatePicker}.
  *
@@ -48,13 +43,6 @@
 
     private final DatePicker mDatePicker;
     private final OnDateSetListener mCallBack;
-    private final Calendar mCalendar;
-    private final java.text.DateFormat mTitleDateFormat;
-    private final String[] mWeekDays;
-
-    private int mInitialYear;
-    private int mInitialMonth;
-    private int mInitialDay;
 
     /**
      * The callback used to indicate the user is done filling in the date.
@@ -106,40 +94,18 @@
         super(context, theme);
 
         mCallBack = callBack;
-        mInitialYear = year;
-        mInitialMonth = monthOfYear;
-        mInitialDay = dayOfMonth;
-        DateFormatSymbols symbols = new DateFormatSymbols();
-        mWeekDays = symbols.getShortWeekdays();
-
-        mTitleDateFormat = java.text.DateFormat.
-                                getDateInstance(java.text.DateFormat.FULL);
-        mCalendar = Calendar.getInstance();
-        updateTitle(mInitialYear, mInitialMonth, mInitialDay);
 
         setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
         setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
-        setIcon(R.drawable.ic_dialog_time);
+        setIcon(0);
+        setTitle(R.string.date_picker_dialog_title);
 
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.date_picker_dialog, null);
         setView(view);
         mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
-        mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, this);
-    }
-
-    @Override
-    public void show() {
-        super.show();
-
-        /* Sometimes the full month is displayed causing the title
-         * to be very long, in those cases ensure it doesn't wrap to
-         * 2 lines (as that looks jumpy) and ensure we ellipsize the end.
-         */
-        TextView title = (TextView) findViewById(R.id.alertTitle);
-        title.setSingleLine();
-        title.setEllipsize(TruncateAt.END);
+        mDatePicker.init(year, monthOfYear, dayOfMonth, this);
     }
 
     public void onClick(DialogInterface dialog, int which) {
@@ -152,23 +118,13 @@
 
     public void onDateChanged(DatePicker view, int year,
             int month, int day) {
-        updateTitle(year, month, day);
+        mDatePicker.init(year, month, day, null);
     }
 
     public void updateDate(int year, int monthOfYear, int dayOfMonth) {
-        mInitialYear = year;
-        mInitialMonth = monthOfYear;
-        mInitialDay = dayOfMonth;
         mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
     }
 
-    private void updateTitle(int year, int month, int day) {
-        mCalendar.set(Calendar.YEAR, year);
-        mCalendar.set(Calendar.MONTH, month);
-        mCalendar.set(Calendar.DAY_OF_MONTH, day);
-        setTitle(mTitleDateFormat.format(mCalendar.getTime()));
-    }
-
     @Override
     public Bundle onSaveInstanceState() {
         Bundle state = super.onSaveInstanceState();
@@ -185,6 +141,5 @@
         int month = savedInstanceState.getInt(MONTH);
         int day = savedInstanceState.getInt(DAY);
         mDatePicker.init(year, month, day, this);
-        updateTitle(year, month, day);
     }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ed71da2..1e80da7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -977,6 +977,9 @@
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
             String v = getString(cr, name);
+            if (v == null) {
+                throw new SettingNotFoundException(name);
+            }
             try {
                 return Float.parseFloat(v);
             } catch (NumberFormatException e) {
@@ -1577,7 +1580,7 @@
          * Default screen rotation when no other policy applies.
          * When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a
          * preference, this rotation value will be used. Must be one of the
-         * {@link android.view.Surface#ROTATION_0 Surface rotation constants}. 
+         * {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
          *
          * @see Display#getRotation
          */
@@ -2296,6 +2299,9 @@
         public static float getFloat(ContentResolver cr, String name)
                 throws SettingNotFoundException {
             String v = getString(cr, name);
+            if (v == null) {
+                throw new SettingNotFoundException(name);
+            }
             try {
                 return Float.parseFloat(v);
             } catch (NumberFormatException e) {
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index c05a8fe..c6ffe58 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -42,6 +42,12 @@
     public static final int EPOCH_JULIAN_DAY = 2440588;
 
     /**
+     * The Julian day of the Monday in the week of the epoch, December 29, 1969
+     * on the Gregorian calendar.
+     */
+    public static final int MONDAY_BEFORE_JULIAN_EPOCH = EPOCH_JULIAN_DAY - 3;
+
+    /**
      * True if this is an allDay event. The hour, minute, second fields are
      * all zero, and the date is displayed the same in all time zones.
      */
@@ -770,4 +776,39 @@
         millis = normalize(true);
         return millis;
     }
+
+    /**
+     * Returns the week since {@link #EPOCH_JULIAN_DAY} (Jan 1, 1970) adjusted
+     * for first day of week. This takes a julian day and the week start day and
+     * calculates which week since {@link #EPOCH_JULIAN_DAY} that day occurs in,
+     * starting at 0. *Do not* use this to compute the ISO week number for the
+     * year.
+     *
+     * @param julianDay The julian day to calculate the week number for
+     * @param firstDayOfWeek Which week day is the first day of the week, see
+     *            {@link #SUNDAY}
+     * @return Weeks since the epoch
+     */
+    public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) {
+        int diff = THURSDAY - firstDayOfWeek;
+        if (diff < 0) {
+            diff += 7;
+        }
+        int refDay = EPOCH_JULIAN_DAY - diff;
+        return (julianDay - refDay) / 7;
+    }
+
+    /**
+     * Takes a number of weeks since the epoch and calculates the Julian day of
+     * the Monday for that week. This assumes that the week containing the
+     * {@link #EPOCH_JULIAN_DAY} is considered week 0. It returns the Julian day
+     * for the Monday week weeks after the Monday of the week containing the
+     * epoch.
+     *
+     * @param week Number of weeks since the epoch
+     * @return The julian day for the Monday of the given week since the epoch
+     */
+    public static int getJulianMondayFromWeeksSinceEpoch(int week) {
+        return MONDAY_BEFORE_JULIAN_EPOCH + week * 7;
+    }
 }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 595b487..9a451cc 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -26,50 +28,44 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
-import android.widget.NumberPicker;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 
 /**
  * A view for selecting a month / year / day based on a calendar like layout.
- *
- * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
- * tutorial</a>.</p>
- *
+ * <p>
+ * See the <a href="{@docRoot}
+ * resources/tutorials/views/hello-datepicker.html">Date Picker tutorial</a>.
+ * </p>
  * For a dialog using this view, see {@link android.app.DatePickerDialog}.
  */
 @Widget
 public class DatePicker extends FrameLayout {
 
     private static final int DEFAULT_START_YEAR = 1900;
+
     private static final int DEFAULT_END_YEAR = 2100;
 
-    // This ignores Undecimber, but we only support real Gregorian calendars.
-    private static final int NUMBER_OF_MONTHS = 12;
-
-    /* UI Components */
     private final NumberPicker mDayPicker;
+
     private final NumberPicker mMonthPicker;
+
     private final NumberPicker mYearPicker;
 
-    /**
-     * How we notify users the date has changed.
-     */
-    private OnDateChangedListener mOnDateChangedListener;
-    
-    private int mDay;
-    private int mMonth;
-    private int mYear;
+    private final DayPicker mMiniMonthDayPicker;
 
-    private Object mMonthUpdateLock = new Object();
-    private volatile Locale mMonthLocale;
-    private String[] mShortMonths;
+    private OnDateChangedListener mOnDateChangedListener;
+
+    private Locale mMonthLocale;
+
+    private final Calendar mTempCalendar = Calendar.getInstance();
+
+    private final int mNumberOfMonths = mTempCalendar.getActualMaximum(Calendar.MONTH) + 1;
+
+    private final String[] mShortMonths = new String[mNumberOfMonths];
 
     /**
      * The callback used to indicate the user changes the date.
@@ -80,7 +76,7 @@
          * @param view The view associated with this listener.
          * @param year The year that was set.
          * @param monthOfYear The month that was set (0-11) for compatibility
-         *  with {@link java.util.Calendar}.
+         *            with {@link java.util.Calendar}.
          * @param dayOfMonth The day of the month that was set.
          */
         void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
@@ -89,7 +85,7 @@
     public DatePicker(Context context) {
         this(context, null);
     }
-    
+
     public DatePicker(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -97,103 +93,85 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.date_picker, this, true);
 
+        OnChangeListener onChangeListener = new OnChangeListener() {
+            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
+                notifyDateChanged();
+                updateMiniMonth();
+            }
+        };
+
+        // day
         mDayPicker = (NumberPicker) findViewById(R.id.day);
         mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
         mDayPicker.setSpeed(100);
-        mDayPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                mDay = newVal;
-                notifyDateChanged();
-            }
-        });
+        mDayPicker.setOnChangeListener(onChangeListener);
+
+        // month
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
-        mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        final String[] months = getShortMonths();
-
-        /*
-         * If the user is in a locale where the month names are numeric,
-         * use just the number instead of the "month" character for
-         * consistency with the other fields.
-         */
-        if (months[0].startsWith("1")) {
-            for (int i = 0; i < months.length; i++) {
-                months[i] = String.valueOf(i + 1);
-            }
-            mMonthPicker.setRange(1, NUMBER_OF_MONTHS);
-        } else {
-            mMonthPicker.setRange(1, NUMBER_OF_MONTHS, months);
-        }
-
+        mMonthPicker.setRange(0, mNumberOfMonths - 1, getShortMonths());
         mMonthPicker.setSpeed(200);
-        mMonthPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                
-                /* We display the month 1-12 but store it 0-11 so always
-                 * subtract by one to ensure our internal state is always 0-11
-                 */
-                mMonth = newVal - 1;
-                // Adjust max day of the month
-                adjustMaxDay();
-                notifyDateChanged();
-                updateDaySpinner();
-            }
-        });
+        mMonthPicker.setOnChangeListener(onChangeListener);
+
+        // year
         mYearPicker = (NumberPicker) findViewById(R.id.year);
         mYearPicker.setSpeed(100);
-        mYearPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-                mYear = newVal;
-                // Adjust max day for leap years if needed
-                adjustMaxDay();
-                notifyDateChanged();
-                updateDaySpinner();
-            }
-        });
-        
-        // attributes
+        mYearPicker.setOnChangeListener(onChangeListener);
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
-
         int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
         int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
         mYearPicker.setRange(mStartYear, mEndYear);
-        
         a.recycle();
+
+        // mini-month day-picker
+        mMiniMonthDayPicker = (DayPicker) findViewById(R.id.mini_month_day_picker);
+        mTempCalendar.clear();
+        mTempCalendar.set(mStartYear, 0, 1);
+        Calendar endRangeDate = (Calendar) mTempCalendar.clone();
+        endRangeDate.set(mEndYear, 11, 31);
+        mMiniMonthDayPicker.setRange(mTempCalendar, endRangeDate);
+        mMiniMonthDayPicker.setOnDateChangeListener(new DayPicker.OnSelectedDayChangeListener() {
+            public void onSelectedDayChange(DayPicker view, int year, int month, int monthDay) {
+                updateDate(year, month, monthDay);
+            }
+        });
         
         // initialize to current date
-        Calendar cal = Calendar.getInstance();
-        init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
-        
+        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+        init(mTempCalendar.get(Calendar.YEAR), mTempCalendar.get(Calendar.MONTH),
+                mTempCalendar.get(Calendar.DAY_OF_MONTH), null);
+
         // re-order the number pickers to match the current date format
-        reorderPickers(months);
-        
-        if (!isEnabled()) {
-            setEnabled(false);
-        }
+        reorderPickers();
     }
-    
+
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
         mDayPicker.setEnabled(enabled);
         mMonthPicker.setEnabled(enabled);
         mYearPicker.setEnabled(enabled);
+        mMiniMonthDayPicker.setEnabled(enabled);
     }
 
-    private void reorderPickers(String[] months) {
+    /**
+     * Reorders the pickers according to the date format in the current locale.
+     */
+    private void reorderPickers() {
         java.text.DateFormat format;
         String order;
 
         /*
-         * If the user is in a locale where the medium date format is
-         * still numeric (Japanese and Czech, for example), respect
-         * the date format order setting.  Otherwise, use the order
-         * that the locale says is appropriate for a spelled-out date.
+         * If the user is in a locale where the medium date format is still
+         * numeric (Japanese and Czech, for example), respect the date format
+         * order setting. Otherwise, use the order that the locale says is
+         * appropriate for a spelled-out date.
          */
 
-        if (months[0].startsWith("1")) {
+        if (getShortMonths()[0].startsWith("1")) {
             format = DateFormat.getDateFormat(getContext());
         } else {
             format = DateFormat.getMediumDateFormat(getContext());
@@ -206,10 +184,11 @@
             order = new String(DateFormat.getDateFormatOrder(getContext()));
         }
 
-        /* Remove the 3 pickers from their parent and then add them back in the
+        /*
+         * Remove the 3 pickers from their parent and then add them back in the
          * required order.
          */
-        LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+        LinearLayout parent = (LinearLayout) findViewById(R.id.pickers);
         parent.removeAllViews();
 
         boolean quoted = false;
@@ -230,7 +209,7 @@
                     parent.addView(mMonthPicker);
                     didMonth = true;
                 } else if (c == DateFormat.YEAR && !didYear) {
-                    parent.addView (mYearPicker);
+                    parent.addView(mYearPicker);
                     didYear = true;
                 }
             }
@@ -248,40 +227,145 @@
         }
     }
 
-    public void updateDate(int year, int monthOfYear, int dayOfMonth) {
-        if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) {
-            mYear = year;
-            mMonth = monthOfYear;
-            mDay = dayOfMonth;
-            updateSpinners();
-            reorderPickers(getShortMonths());
+    /**
+     * Updates the current date.
+     *
+     * @param year The year.
+     * @param month The month which is <strong>starting from zero</strong>.
+     * @param dayOfMonth The day of the month.
+     */
+    public void updateDate(int year, int month, int dayOfMonth) {
+        if (mYearPicker.getCurrent() != year
+                || mDayPicker.getCurrent() != dayOfMonth
+                || mMonthPicker.getCurrent() != month) {
+            updatePickers(year, month, dayOfMonth);
+            updateMiniMonth();
             notifyDateChanged();
         }
     }
 
+    /**
+     * @return The short month abbreviations.
+     */
     private String[] getShortMonths() {
         final Locale currentLocale = Locale.getDefault();
-        if (currentLocale.equals(mMonthLocale) && mShortMonths != null) {
+        if (currentLocale.equals(mMonthLocale)) {
             return mShortMonths;
         } else {
-            synchronized (mMonthUpdateLock) {
-                if (!currentLocale.equals(mMonthLocale)) {
-                    mShortMonths = new String[NUMBER_OF_MONTHS];
-                    for (int i = 0; i < NUMBER_OF_MONTHS; i++) {
-                        mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
-                                DateUtils.LENGTH_MEDIUM);
-                    }
-                    mMonthLocale = currentLocale;
-                }
+            for (int i = 0; i < mNumberOfMonths; i++) {
+                mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+                        DateUtils.LENGTH_MEDIUM);
             }
+            mMonthLocale = currentLocale;
             return mShortMonths;
         }
     }
 
+    // Override so we are in complete control of save / restore for this widget.
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+        dispatchThawSelfOnly(container);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        return new SavedState(superState, mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+                mDayPicker.getCurrent());
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        updatePickers(ss.mYear, ss.mMonth, ss.mDay);
+    }
+
+    /**
+     * Initialize the state. If the provided values designate an inconsistent
+     * date the values are normalized before updating the pickers.
+     *
+     * @param year The initial year.
+     * @param monthOfYear The initial month <strong>starting from zero</strong>.
+     * @param dayOfMonth The initial day of the month.
+     * @param onDateChangedListener How user is notified date is changed by
+     *            user, can be null.
+     */
+    public void init(int year, int monthOfYear, int dayOfMonth,
+            OnDateChangedListener onDateChangedListener) {
+        mOnDateChangedListener = onDateChangedListener;
+        updateDate(year, monthOfYear, dayOfMonth);
+    }
+
+    /**
+     * Updates the pickers with the given <code>year</code>, <code>month</code>,
+     * and <code>dayOfMonth</code>. If the provided values designate an inconsistent
+     * date the values are normalized before updating the pickers.
+     */
+    private void updatePickers(int year, int month, int dayOfMonth) {
+        // make sure the date is normalized
+        mTempCalendar.clear();
+        mTempCalendar.set(year, month, dayOfMonth);
+        mYearPicker.setCurrent(mTempCalendar.get(Calendar.YEAR));
+        mMonthPicker.setCurrent(mTempCalendar.get(Calendar.MONTH));
+        mDayPicker.setRange(1, mTempCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+        mDayPicker.setCurrent(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+    }
+
+    /**
+     * Updates the mini-month with the given year, month, and day selected by the
+     * number pickers.
+     */
+    private void updateMiniMonth() {
+        Calendar selectedDay = mMiniMonthDayPicker.getSelectedDay();
+        if (selectedDay.get(Calendar.YEAR) != mYearPicker.getCurrent()
+                || selectedDay.get(Calendar.MONTH) != mMonthPicker.getCurrent()
+                || selectedDay.get(Calendar.DAY_OF_MONTH) != mDayPicker.getCurrent()) {
+            mMiniMonthDayPicker.goTo(mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+                    mDayPicker.getCurrent(), false, true, false);
+        }
+    }
+
+    /**
+     * @return The selected year.
+     */
+    public int getYear() {
+        return mYearPicker.getCurrent();
+    }
+
+    /**
+     * @return The selected month.
+     */
+    public int getMonth() {
+        return mMonthPicker.getCurrent();
+    }
+
+    /**
+     * @return The selected day of month.
+     */
+    public int getDayOfMonth() {
+        return mDayPicker.getCurrent();
+    }
+
+    /**
+     * Notifies the listener, if such, for a change in the selected date.
+     */
+    private void notifyDateChanged() {
+        if (mOnDateChangedListener != null) {
+            mOnDateChangedListener.onDateChanged(DatePicker.this, mYearPicker.getCurrent(),
+                    mMonthPicker.getCurrent(), mDayPicker.getCurrent());
+        }
+    }
+
+    /**
+     * Class for managing state storing/restoring.
+     */
     private static class SavedState extends BaseSavedState {
 
         private final int mYear;
+
         private final int mMonth;
+
         private final int mDay;
 
         /**
@@ -293,7 +377,7 @@
             mMonth = month;
             mDay = day;
         }
-        
+
         /**
          * Constructor called from {@link #CREATOR}
          */
@@ -304,18 +388,6 @@
             mDay = in.readInt();
         }
 
-        public int getYear() {
-            return mYear;
-        }
-
-        public int getMonth() {
-            return mMonth;
-        }
-
-        public int getDay() {
-            return mDay;
-        }
-
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
@@ -324,104 +396,17 @@
             dest.writeInt(mDay);
         }
 
-        public static final Parcelable.Creator<SavedState> CREATOR =
-                new Creator<SavedState>() {
+        @SuppressWarnings("all")
+        // suppress unused and hiding
+        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
 
-                    public SavedState createFromParcel(Parcel in) {
-                        return new SavedState(in);
-                    }
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
 
-                    public SavedState[] newArray(int size) {
-                        return new SavedState[size];
-                    }
-                };
-    }
-
-
-    /**
-     * Override so we are in complete control of save / restore for this widget.
-     */
-    @Override
-    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
-        dispatchThawSelfOnly(container);
-    }
-
-    @Override
-    protected Parcelable onSaveInstanceState() {
-        Parcelable superState = super.onSaveInstanceState();
-        
-        return new SavedState(superState, mYear, mMonth, mDay);
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Parcelable state) {
-        SavedState ss = (SavedState) state;
-        super.onRestoreInstanceState(ss.getSuperState());
-        mYear = ss.getYear();
-        mMonth = ss.getMonth();
-        mDay = ss.getDay();
-        updateSpinners();
-    }
-
-    /**
-     * Initialize the state.
-     * @param year The initial year.
-     * @param monthOfYear The initial month.
-     * @param dayOfMonth The initial day of the month.
-     * @param onDateChangedListener How user is notified date is changed by user, can be null.
-     */
-    public void init(int year, int monthOfYear, int dayOfMonth,
-            OnDateChangedListener onDateChangedListener) {
-        mYear = year;
-        mMonth = monthOfYear;
-        mDay = dayOfMonth;
-        mOnDateChangedListener = onDateChangedListener;
-        updateSpinners();
-    }
-
-    private void updateSpinners() {
-        updateDaySpinner();
-        mYearPicker.setCurrent(mYear);
-        
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        mMonthPicker.setCurrent(mMonth + 1);
-    }
-
-    private void updateDaySpinner() {
-        Calendar cal = Calendar.getInstance();
-        cal.set(mYear, mMonth, mDay);
-        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
-        mDayPicker.setRange(1, max);
-        mDayPicker.setCurrent(mDay);
-    }
-
-    public int getYear() {
-        return mYear;
-    }
-
-    public int getMonth() {
-        return mMonth;
-    }
-
-    public int getDayOfMonth() {
-        return mDay;
-    }
-
-    private void adjustMaxDay(){
-        Calendar cal = Calendar.getInstance();
-        cal.set(Calendar.YEAR, mYear);
-        cal.set(Calendar.MONTH, mMonth);
-        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
-        if (mDay > max) {
-            mDay = max;
-        }
-    }
-
-    private void notifyDateChanged() {
-        if (mOnDateChangedListener != null) {
-            mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
-        }
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
     }
 }
diff --git a/core/java/android/widget/DayPicker.java b/core/java/android/widget/DayPicker.java
new file mode 100644
index 0000000..11c23ab
--- /dev/null
+++ b/core/java/android/widget/DayPicker.java
@@ -0,0 +1,1474 @@
+/*
+ * Copyright (C) 2010 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.app.Service;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView.OnScrollListener;
+
+import java.security.InvalidParameterException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
+
+/**
+ * Displays a day picker in the form of a calendar. The calendar
+ * is represented as a list where each row depicts a week. Each week is
+ * composed of items that are selectable days.
+ */
+public class DayPicker extends FrameLayout {
+
+    /**
+     * The number of milliseconds in a day.
+     *
+     * @hide
+     */
+    protected static final long MILLIS_IN_DAY = 86400000L;
+
+    /**
+     * The number of day in a week.
+     *
+     * @hide
+     */
+    protected static final int DAYS_PER_WEEK = 7;
+
+    /**
+     * The number of milliseconds in a week.
+     *
+     * @hide
+     */
+    protected static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
+
+    /**
+     * Affects when the month selection will change while scrolling up
+     *
+     * @hide
+     */ 
+    protected static final int SCROLL_HYST_WEEKS = 2;
+
+    /**
+     * How long the GoTo fling animation should last.
+     *
+     * @hide
+     */
+    protected static final int GOTO_SCROLL_DURATION = 1000;
+
+    /**
+     * The duration of the adjustment upon a user scroll in milliseconds.
+     *
+     * @hide
+     */
+    protected static final int ADJUSTMENT_SCROLL_DURATION = 500;
+
+    /**
+     * How long to wait after receiving an onScrollStateChanged notification
+     * before acting on it.
+     *
+     * @hide
+     */
+    protected static final int SCROLL_CHANGE_DELAY = 40;
+
+    /**
+     * The scale used to compensate for different screen density.
+     *
+     * @hide
+     */
+    protected static float sScale;
+
+    /**
+     * The top offset of the weeks list.
+     *
+     * @hide
+     */
+    protected static int mListTopOffset = 2;
+
+    /**
+     * The visible height of a week view.
+     *
+     * @hide
+     */
+    protected int mWeekMinVisibleHeight = 12;
+
+
+    /**
+     * The visible height of a week view.
+     *
+     * @hide
+     */
+    protected int mBottomBuffer = 20;
+
+    /**
+     * The number of shown weeks.
+     *
+     * @hide
+     */
+    protected int mShownWeekCount = 6;
+
+    /**
+     * Flag whether to show the week number.
+     *
+     * @hide
+     */
+    protected boolean mShowWeekNumber = true;
+
+    /**
+     * The number of day per week to be shown
+     *
+     * @hide
+     */
+    protected int mDaysPerWeek = 7;
+
+    /**
+     * The friction of the week list while flinging.
+     *
+     * @hide
+     */
+    protected float mFriction = .05f;
+
+    /**
+     * Scale for adjusting velocity of the week list while flinging.
+     *
+     * @hide
+     */
+    protected float mVelocityScale = 0.333f;
+
+    /**
+     * The adapter for the weeks list.
+     *
+     * @hide
+     */
+    protected WeeksAdapter mAdapter;
+
+    /**
+     * The weeks list.
+     *
+     * @hide
+     */
+    protected ListView mListView;
+
+    /**
+     * The name of the month to display.
+     *
+     * @hide
+     */
+    protected TextView mMonthName;
+
+    /**
+     * The header with week day names.
+     *
+     * @hide
+     */
+    protected ViewGroup mDayNamesHeader;
+
+    /**
+     * Cached labels for the week names header.
+     *
+     * @hide
+     */
+    protected String[] mDayLabels;
+
+    /**
+     * Temporary instance to avoid multiple instantiations.
+     *
+     * @hide
+     */
+    protected Calendar mTempCalendar = Calendar.getInstance();
+
+    /**
+     * The first day of the week based on the current locale.
+     *
+     * @hide
+     */
+    protected int mFirstDayOfWeek = LocaleData.get(Locale.getDefault()).firstDayOfWeek;
+
+    /**
+     * The first day of the focused month.
+     *
+     * @hide
+     */
+    protected Calendar mFirstDayOfMonth = Calendar.getInstance();
+
+    /**
+     * Which month should be displayed/highlighted [0-11]
+     *
+     * @hide
+     */
+    protected int mCurrentMonthDisplayed;
+
+    /**
+     * Used for tracking during a scroll.
+     *
+     * @hide
+     */
+    protected long mPreviousScrollPosition;
+
+    /**
+     * Used for tracking which direction the view is scrolling.
+     *
+     * @hide
+     */
+    protected boolean mIsScrollingUp = false;
+
+    /**
+     * The previous scroll state of the weeks ListView.
+     *
+     * @hide
+     */
+    protected int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * The current scroll state of the weeks ListView.
+     *
+     * @hide
+     */
+    protected int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * Listener for changes in the selected day.
+     *
+     * @hide
+     */
+    protected OnSelectedDayChangeListener mOnChangeListener;
+
+    /**
+     * Command for adjusting the position after a scroll/fling.
+     *
+     * @hide
+     */
+    protected ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
+
+    /**
+     * The start date of the range supported by this picker.
+     *
+     * @hide
+     */
+    protected Calendar mStartRangeDate = Calendar.getInstance();
+
+    /**
+     * The end date of the range supported by this picker.
+     *
+     * @hide
+     */
+    protected Calendar mEndRangeDate = Calendar.getInstance();
+
+    /**
+     * String for formatting the month name in the title text view.
+     *
+     * @hide
+     */
+    protected String mMonthNameFormatSrting = "MMMM, yyyy";
+
+    /**
+     * The callback used to indicate the user changes the date.
+     */
+    public interface OnSelectedDayChangeListener {
+
+        /**
+         * Called upon change of the selected day.
+         *
+         * @param view The view associated with this listener.
+         * @param year The year that was set.
+         * @param month The month that was set [0-11].
+         * @param dayOfMonth The day of the month that was set.
+         */
+        public void onSelectedDayChange(DayPicker view, int year, int month, int dayOfMonth);
+    }
+
+    public DayPicker(Context context) {
+        this(context, null);
+    }
+
+    public DayPicker(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DayPicker(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, 0);
+
+        LayoutInflater layoutInflater = (LayoutInflater) mContext
+                .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
+        View content = layoutInflater.inflate(R.layout.day_picker, null, false);
+        addView(content);
+
+        mListView = (ListView) findViewById(R.id.list);
+        mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
+        mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
+
+        // Adjust sizes for screen density
+        if (sScale == 0) {
+            sScale = mContext.getResources().getDisplayMetrics().density;
+            if (sScale != 1) {
+                mWeekMinVisibleHeight *= sScale;
+                mBottomBuffer *= sScale;
+                mListTopOffset *= sScale;
+            }
+        }
+
+        // set default range
+        mStartRangeDate.clear();
+        mStartRangeDate.set(1900, 0, 1);
+        mEndRangeDate.clear();
+        mEndRangeDate.set(2100, 0, 1);
+
+        setUpHeader();
+        updateHeader();
+        setUpListView();
+        setUpAdapter();
+
+        // go to today now
+        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+        goTo(mTempCalendar, false, true, true);
+        invalidate();
+    }
+
+    /**
+     * Sets the range supported by this day picker. This is the picker will not
+     * support dates before <code>startRangeDate</code> and <code>endRangeDate
+     * </code>.
+     *
+     * @param startRangeDate The start date.
+     * @param endRangeDate The end date.
+     */
+    public void setRange(Calendar startRangeDate, Calendar endRangeDate) {
+        boolean doSetupAdapter = false;
+        if (mStartRangeDate.get(Calendar.DAY_OF_YEAR) != startRangeDate.get(Calendar.DAY_OF_YEAR)
+                || mStartRangeDate.get(Calendar.YEAR) != startRangeDate.get(Calendar.YEAR)) {
+            mStartRangeDate = startRangeDate;
+            doSetupAdapter = true;
+        }
+        if (mEndRangeDate.get(Calendar.DAY_OF_YEAR) != endRangeDate.get(Calendar.DAY_OF_YEAR)
+                || mEndRangeDate.get(Calendar.YEAR) != endRangeDate.get(Calendar.YEAR)) {
+            mEndRangeDate = endRangeDate;
+            doSetupAdapter = true;
+            
+        }
+        if (doSetupAdapter) {
+            setUpAdapter();
+        }
+    }
+
+    /**
+     * Sets the listener to be notified upon day selection changes.
+     *
+     * @param listener The listener to be called back.
+     */
+    public void setOnDateChangeListener(OnSelectedDayChangeListener listener) {
+        mOnChangeListener = listener;
+    }
+
+    /**
+     * Gets the selected day.
+     *
+     * @return The selected day.
+     */
+    public Calendar getSelectedDay() {
+        return mAdapter.mSelectedDay;
+    }
+
+    /**
+     * Sets the selected day. This is equivalent to a call to
+     * {@link #goTo(Calendar, boolean, boolean, boolean)} with
+     * the arguments <code>selectedDay</code>, <code>false</code>,
+     * <code>true</code>, <code>false</code> respectively.
+     *
+     * @param selectedDay The selected day.
+     */
+    public void setSelectedDay(Calendar selectedDay) {
+        goTo(selectedDay, false, true, false);
+    }
+
+    /**
+     * Creates a new adapter if necessary and sets up its parameters. Override
+     * this method to provide a custom adapter.
+     *
+     * @hide
+     */
+    protected void setUpAdapter() {
+        if (mAdapter == null) {
+            mAdapter = new WeeksAdapter(getContext());
+            mAdapter.registerDataSetObserver(new DataSetObserver() {
+                @Override
+                public void onChanged() {
+                    if (mOnChangeListener != null) {
+                        Calendar selectedDay = mAdapter.getSelectedDay();
+                        mOnChangeListener.onSelectedDayChange(DayPicker.this,
+                                selectedDay.get(Calendar.YEAR),
+                                selectedDay.get(Calendar.MONTH),
+                                selectedDay.get(Calendar.DAY_OF_MONTH));
+                    }
+                }
+            });
+            mListView.setAdapter(mAdapter);
+        }
+
+        // refresh the view with the new parameters
+        mAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * Sets up the strings to be used by the header. Override this method to use
+     * different strings or modify the view params.
+     *
+     * @hide
+     */
+    protected void setUpHeader() {
+        mDayLabels = new String[mDaysPerWeek];
+        for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
+            int calendarDay = (i < mDaysPerWeek) ? i : 1; // Calendar.MONDAY is
+            // 1
+            mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+                    DateUtils.LENGTH_SHORTEST);
+        }
+    }
+
+    /**
+     * Sets all the required fields for the list view. Override this method to
+     * set a different list view behavior.
+     *
+     * @hide
+     */
+    protected void setUpListView() {
+        // Configure the listview
+        mListView.setDivider(null);
+        mListView.setItemsCanFocus(true);
+        mListView.setVerticalScrollBarEnabled(false);
+        mListView.setOnScrollListener(new OnScrollListener() {
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                DayPicker.this.onScrollStateChanged(view, scrollState);
+            }
+
+            public void onScroll(
+                    AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                DayPicker.this.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
+            }
+        });
+        // Make the scrolling behavior nicer
+        mListView.setFriction(mFriction);
+        mListView.setVelocityScale(mVelocityScale);
+    }
+
+    /**
+     * Fixes the day names header to provide correct spacing and updates the
+     * label text. Override this to set up a custom header.
+     *
+     * @hide
+     */
+    protected void updateHeader() {
+        TextView label = (TextView) mDayNamesHeader.getChildAt(0);
+        if (mShowWeekNumber) {
+            label.setVisibility(View.VISIBLE);
+        } else {
+            label.setVisibility(View.GONE);
+        }
+        for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
+            label = (TextView) mDayNamesHeader.getChildAt(i);
+            if (i < mDaysPerWeek + 1) {
+                label.setText(mDayLabels[i - 1]);
+                label.setVisibility(View.VISIBLE);
+            } else {
+                label.setVisibility(View.GONE);
+            }
+        }
+        mDayNamesHeader.invalidate();
+    }
+
+    /**
+     * 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 year The year to move to.
+     * @param month The month to move to <strong>starting from zero<strong>.
+     * @param dayOfMonth The month 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.
+     */
+    public void goTo(int year, int month, int dayOfMonth, boolean animate, boolean setSelected,
+            boolean forceScroll) {
+        mTempCalendar.clear();
+        mTempCalendar.set(year, month, dayOfMonth);
+        goTo(mTempCalendar, animate, setSelected, forceScroll);
+    }
+
+    /**
+     * 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 date The time 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.
+     */
+    public void goTo(Calendar date, boolean animate, boolean setSelected, boolean forceScroll) {
+        long timeInMillis = date.getTimeInMillis();
+        if (timeInMillis < mStartRangeDate.getTimeInMillis()
+                || timeInMillis > mEndRangeDate.getTimeInMillis()) {
+            throw new IllegalArgumentException("Time not between " + mStartRangeDate.getTime()
+                    + " and " + mEndRangeDate.getTime());
+        }
+        // Find the first and last entirely visible weeks
+        int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild != null && firstChild.getTop() < 0) {
+            firstFullyVisiblePosition++;
+        }
+        int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
+        if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
+            lastFullyVisiblePosition--;
+        }
+        if (setSelected) {
+            mAdapter.setSelectedDay(date);
+        }
+        // Get the week we're going to
+        int position = getWeeksDelta(date);
+
+        // Check if the selected day is now outside of our visible range
+        // and if so scroll to the month that contains it
+        if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
+                || forceScroll) {
+            mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
+            mFirstDayOfMonth.setTimeZone(date.getTimeZone());
+            mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
+
+            setMonthDisplayed(mFirstDayOfMonth);
+            position = getWeeksDelta(mFirstDayOfMonth);
+
+            mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
+            if (animate) {
+                mListView.smoothScrollToPositionFromTop(position, mListTopOffset,
+                        GOTO_SCROLL_DURATION);
+            } else {
+                mListView.setSelectionFromTop(position, mListTopOffset);
+                // Perform any after scroll operations that are needed
+                onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
+            }
+        } else if (setSelected) {
+            // Otherwise just set the selection
+            setMonthDisplayed(date);
+        }
+    }
+
+    /**
+     * Called when a <code>view</code> transitions to a new <code>scrollState
+     * </code>.
+     *
+     * @hide
+     */
+    protected void onScrollStateChanged(AbsListView view, int scrollState) {
+        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+    }
+
+    /**
+     * Updates the title and selected month if the <code>view</code> has moved to a new
+     * month.
+     *
+     * @hide
+     */
+    protected void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        WeekView child = (WeekView) view.getChildAt(0);
+        if (child == null) {
+            return;
+        }
+
+        // Figure out where we are
+        int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
+        long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
+
+        // If we have moved since our last call update the direction
+        if (currScroll < mPreviousScrollPosition) {
+            mIsScrollingUp = true;
+        } else if (currScroll > mPreviousScrollPosition) {
+            mIsScrollingUp = false;
+        } else {
+            return;
+        }
+
+        // Use some hysteresis for checking which month to highlight. This
+        // causes the month to transition when two full weeks of a month are
+        // visible when scrolling up, and when the first day in a month reaches
+        // the top of the screen when scrolling down.
+        if (mIsScrollingUp) {
+            child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
+        } else if (offset != 0) {
+            child = (WeekView) view.getChildAt(offset);
+        }
+
+        // Find out which month we're moving into
+        int month;
+        if (mIsScrollingUp) {
+            month = child.getMonthOfFirstWeekDay();
+        } else {
+            month = child.getMonthOfLastWeekDay();
+        }
+
+        // And how it relates to our current highlighted month
+        int monthDiff;
+        if (mCurrentMonthDisplayed == 11 && month == 0) {
+            monthDiff = 1;
+        } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+            monthDiff = -1;
+        } else {
+            monthDiff = month - mCurrentMonthDisplayed;
+        }
+
+        // Only switch months if we're scrolling away from the currently
+        // selected month
+        if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+            Calendar firstDay = child.getFirstDay();
+            if (mIsScrollingUp) {
+                firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+            } else {
+                firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+            }
+            setMonthDisplayed(firstDay);
+        }
+        mPreviousScrollPosition = currScroll;
+        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.
+     *
+     * @param calendar A day in the new focus month.
+     *
+     * @hide
+     */
+    protected void setMonthDisplayed(Calendar calendar) {
+        mMonthName.setText(DateFormat.format(mMonthNameFormatSrting, calendar));
+        mMonthName.invalidate();
+        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+        // TODO Send Accessibility Event
+    }
+
+    /**
+     * @return Returns the number of weeks between the current week day of the
+     *         <code>fromDate</code> and the first day of week of
+     *         <code>toDate</code>.
+     *
+     * @hide
+     */
+    protected int getWeeksDelta(Calendar toDate) {
+        if (toDate.before(mStartRangeDate)) {
+            throw new IllegalArgumentException("fromDate: " + mStartRangeDate.getTime()
+                    + " does not precede toDate: " + toDate.getTime());
+        }
+        int fromDateDayOfWeek = mStartRangeDate.get(Calendar.DAY_OF_WEEK);
+        long diff = (fromDateDayOfWeek - toDate.getFirstDayOfWeek()) * MILLIS_IN_DAY;
+        if (diff < 0) {
+            diff = diff + MILLIS_IN_WEEK;
+        }
+        long refDay = mStartRangeDate.getTimeInMillis() - diff;
+        return (int) ((toDate.getTimeInMillis() - refDay) / MILLIS_IN_WEEK);
+    }
+
+    /**
+     * Command responsible for acting upon scroll state changes.
+     *
+     * @hide
+     */
+    protected class ScrollStateRunnable implements Runnable {
+        private AbsListView mView;
+
+        private int mNewState;
+
+        /**
+         * 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) {
+            removeCallbacks(this);
+            mView = view;
+            mNewState = scrollState;
+            removeCallbacks(this);
+            postDelayed(this, SCROLL_CHANGE_DELAY);
+        }
+
+        public void run() {
+            mCurrentScrollState = mNewState;
+            // Fix the position after a scroll or a fling ends
+            if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+                mPreviousScrollState = mNewState;
+                View child = mView.getChildAt(0);
+                if (child == null) {
+                    // The view is no longer visible, just return
+                    return;
+                }
+                int dist = child.getBottom() - mListTopOffset;
+                if (dist > mListTopOffset) {
+                    if (mIsScrollingUp) {
+                        mView.smoothScrollBy(dist - child.getHeight(), ADJUSTMENT_SCROLL_DURATION);
+                    } else {
+                        mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
+                    }
+                }
+            } else {
+                mPreviousScrollState = mNewState;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a specialized adapter for creating a list of weeks with
+     * selectable days. It can be configured to display the week number, start
+     * the week on a given day, show a reduced number of days, or display an
+     * arbitrary number of weeks at a time.
+     * </p>
+     *
+     * @hide
+     */
+    public class WeeksAdapter extends BaseAdapter implements OnTouchListener {
+
+        /**
+         * The default maximum year supported by the Date Time Picker.
+         */
+        public static final int DEFAULT_MAX_CALENDAR_YEAR = 2100;
+
+        /**
+         * The default minimum year supported by the Date Time Picker.
+         */
+        public static final int DEFAULT_MIN_CALENDAR_YEAR = 1900;
+
+        /**
+         * The number of weeks to display at a time.
+         */
+        public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks";
+
+        /**
+         * Which month should be in focus currently.
+         */
+        public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month";
+
+        /**
+         * Whether the week number should be shown. Non-zero to show them.
+         */
+        public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers";
+
+        /**
+         * Which day the week should start on. {@link Time#SUNDAY} through
+         * {@link Time#SATURDAY}.
+         */
+        public static final String WEEK_PARAMS_WEEK_START = "week_start";
+
+        /**
+         * The year of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_YEAR = "selected_year";
+
+        /**
+         * The month of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_MONTH = "selected_month";
+
+        /**
+         * The year of the highlighted day.
+         */
+        public static final String WEEK_PARAMS_DAY_OF_MONTH = "selected_day_of_month";
+
+        /**
+         * The start date of the supported interval.
+         */
+        public static final String WEEK_PARAMS_START_DATE_RANGE_MILLIS = "start_date_gange_millis";
+
+        /**
+         * The end date of the supported interval.
+         */
+        public static final String WEEK_PARAMS_END_DATE_RANGE_MILLIS = "end_date_gange_millis";
+
+        /**
+         * How many days of the week to display [1-7].
+         */
+        public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week";
+
+        protected int WEEK_7_OVERHANG_HEIGHT = 7;
+
+        protected int mSelectedWeek;
+
+        protected GestureDetector mGestureDetector;
+
+        protected int mFocusMonth = 0;
+
+        private final Calendar mSelectedDay = Calendar.getInstance();
+
+        private int mTotalWeekCount = -1;
+
+        public WeeksAdapter(Context context) {
+            mContext = context;
+
+            if (sScale == 0) {
+                sScale = context.getResources().getDisplayMetrics().density;
+                if (sScale != 1) {
+                    WEEK_7_OVERHANG_HEIGHT *= sScale;
+                }
+            }
+            init();
+        }
+
+        /**
+         * Set up the gesture detector and selected time
+         */
+        protected void init() {
+            mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
+            mSelectedWeek = getWeeksDelta(mSelectedDay);
+            mTotalWeekCount = getWeeksDelta(mEndRangeDate);
+        }
+
+        /**
+         * Updates the selected day and related parameters.
+         * 
+         * @param selectedDay The time to highlight
+         */
+        public void setSelectedDay(Calendar selectedDay) {
+            if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDay.get(Calendar.DAY_OF_YEAR)
+                    && selectedDay.get(Calendar.YEAR) == mSelectedDay.get(Calendar.YEAR)) {
+                return;
+            }
+            mSelectedDay.setTimeInMillis(selectedDay.getTimeInMillis());
+            mSelectedDay.setTimeZone(selectedDay.getTimeZone());
+            mSelectedWeek = getWeeksDelta(mSelectedDay);
+            mFocusMonth = mSelectedDay.get(Calendar.MONTH);
+            notifyDataSetChanged();
+            invalidate();  // Test
+        }
+
+        /**
+         * @return The selected day of month.
+         */
+        public Calendar getSelectedDay() {
+            return mSelectedDay;
+        }
+
+        /**
+         * updates any config options that may have changed and refreshes the
+         * view
+         */
+        public void refresh() {
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mTotalWeekCount;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            WeekView v;
+            HashMap<String, Object> drawingParams = null;
+            if (convertView != null) {
+                v = (WeekView) convertView;
+                // We store the drawing parameters in the view so it can be
+                // recycled
+                drawingParams = (HashMap<String, Object>) v.getTag();
+            } else {
+                v = getNewView();
+                // Set up the new view
+                android.widget.AbsListView.LayoutParams params =
+                    new android.widget.AbsListView.LayoutParams(
+                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                v.setLayoutParams(params);
+                v.setClickable(true);
+                v.setOnTouchListener(this);
+
+                drawingParams = new HashMap<String, Object>();
+            }
+
+            // pass in all the view parameters
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SHOW_WK_NUM,
+                    mShowWeekNumber ? 1 : 0);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK, position);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth);
+            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SELECTED_DAY,
+                    (mSelectedWeek == position) ? mSelectedDay.get(Calendar.DAY_OF_WEEK) : -1);
+            v.setWeekParams(drawingParams);
+
+            return v;
+        }
+
+        /**
+         * Puts the given <code>value</code> for the drawing
+         * <code>parameter</code> in the <code>drawingParams</code>.
+         */
+        private void putDrawingParementer(HashMap<String, Object> drawingParams, String parameter,
+                int value) {
+            int[] valueArray = (int[]) drawingParams.get(parameter);
+            if (valueArray == null) {
+                valueArray = new int[1];
+                drawingParams.put(parameter, valueArray);
+            }
+            valueArray[0] = value;
+        }
+
+        /**
+         * Creates a new WeekView and returns it. Override this to customize the
+         * view creation.
+         *
+         * @return A new WeekView
+         */
+        protected WeekView getNewView() {
+            return new WeekView(mContext);
+        }
+
+        /**
+         * Changes which month is in focus and updates the view.
+         *
+         * @param month The month to show as in focus [0-11]
+         */
+        public void setFocusMonth(int month) {
+            if (mFocusMonth == month) {
+                return;
+            }
+            mFocusMonth = month;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            if (mGestureDetector.onTouchEvent(event)) {
+                WeekView weekView = (WeekView) v;
+                weekView.getDayFromLocation(event.getX(), mTempCalendar);
+                if (mTempCalendar.get(Calendar.YEAR) != 0) {
+                    onDayTapped(mTempCalendar);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Maintains the same hour/min/sec but moves the day to the tapped day.
+         * 
+         * @param day The day that was tapped
+         */
+        protected void onDayTapped(Calendar day) {
+            setSelectedDay(day);
+        }
+
+        /**
+         * This is here so we can identify single tap events and set the
+         * selected day correctly
+         */
+        protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a dynamic view for drawing a single week. It can be configured to
+     * display the week number, start the week on a given day, or show a reduced
+     * number of days. It is intended for use as a single view within a
+     * ListView. See {@link WeeksAdapter} for usage.
+     * </p>
+     *
+     * @hide
+     */
+    public class WeekView extends View {
+
+        /*
+         * These params can be passed into the view to control how it appears.
+         * {@link #VIEW_PARAMS_WEEK} is the only required field, though the
+         * default values are unlikely to fit most layouts correctly.
+         */
+
+        /**
+         * This sets the height of this week in pixels
+         */
+        public static final String VIEW_PARAMS_HEIGHT = "height";
+
+        /**
+         * This specifies the position (or weeks since the epoch) of this week.
+         */
+        public static final String VIEW_PARAMS_WEEK = "week";
+
+        /**
+         * This sets one of the days in this view as selected
+         * {@link Time#SUNDAY} through {@link Time#SATURDAY}.
+         */
+        public static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
+
+        /**
+         * Which day the week should start on. {@link Time#SUNDAY} through
+         * {@link Time#SATURDAY}.
+         */
+        public static final String VIEW_PARAMS_WEEK_START = "week_start";
+
+        /**
+         * How many days to display at a time. Days will be displayed starting
+         * with {@link #mFirstDay}.
+         */
+        public static final String VIEW_PARAMS_NUM_DAYS = "num_days";
+
+        /**
+         * Which month is currently in focus, as defined by {@link Time#month}
+         * [0-11].
+         */
+        public static final String VIEW_PARAMS_FOCUS_MONTH = "focus_month";
+
+        /**
+         * If this month should display week numbers. false if 0, true
+         * otherwise.
+         */
+        public static final String VIEW_PARAMS_SHOW_WK_NUM = "show_wk_num";
+
+        protected int mDefaultHeight = 32;
+
+        protected int mMinHeight = 10;
+
+        protected static final int DEFAULT_SELECTED_DAY = -1;
+
+        protected static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
+
+        protected static final int DEFAULT_NUM_DAYS = 7;
+
+        protected static final int DEFAULT_SHOW_WK_NUM = 0;
+
+        protected static final int DEFAULT_FOCUS_MONTH = -1;
+
+        protected static final int DAY_SEPARATOR_WIDTH = 1;
+
+        protected int mNumberTextSize = 14;
+
+        // affects the padding on the sides of this view
+        protected int mPadding = 0;
+
+        protected final Rect mTempRect = new Rect();
+
+        protected final Paint mDrawPaint = new Paint();
+
+        protected Paint mMonthNumDrawPaint = new Paint();
+
+        protected Drawable mSelectedDayLine;
+
+        protected final int mSelectionBackgroundColor;
+
+        protected final int mFocusedMonthDateColor;
+
+        protected final int mOtherMonthDateColor;
+
+        protected final int mGridLinesColor;
+
+        protected final int mWeekNumberColor;
+
+        // Cache the number strings so we don't have to recompute them each time
+        protected String[] mDayNumbers;
+
+        // Quick lookup for checking which days are in the focus month
+        protected boolean[] mFocusDay;
+
+        // The first day displayed by this item
+        protected Calendar mFirstDay;
+
+        // The month of the first day in this week
+        protected int mMonthOfFirstWeekDay = -1;
+
+        // The month of the last day in this week
+        protected int mLastWeekDayMonth = -1;
+
+        // The position of this week, equivalent to weeks since the week of Jan
+        // 1st, 1900
+        protected int mWeek = -1;
+
+        // Quick reference to the width of this view, matches parent
+        protected int mWidth;
+
+        // The height this view should draw at in pixels, set by height param
+        protected int mHeight = mDefaultHeight;
+
+        // Whether the week number should be shown
+        protected boolean mShowWeekNum = false;
+
+        // If this view contains the selected day
+        protected boolean mHasSelectedDay = false;
+
+        // Which day is selected [0-6] or -1 if no day is selected
+        protected int mSelectedDay = DEFAULT_SELECTED_DAY;
+
+        // How many days to display
+        protected int mNumDays = DEFAULT_NUM_DAYS;
+
+        // The number of days + a spot for week number if it is displayed
+        protected int mNumCells = mNumDays;
+
+        // The left edge of the selected day
+        protected int mSelectedLeft = -1;
+
+        // The right edge of the selected day
+        protected int mSelectedRight = -1;
+
+        public WeekView(Context context) {
+            super(context);
+
+            TypedValue outTypedValue = new TypedValue();
+            context.getTheme().resolveAttribute(R.attr.dayPickerWeekViewStyle, outTypedValue, true);
+            TypedArray attributesArray = context.obtainStyledAttributes(outTypedValue.resourceId,
+                    R.styleable.DayPickerWeekView);
+
+            mSelectionBackgroundColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_selectionBackgroundColor, 0);
+            mFocusedMonthDateColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_focusedMonthDateColor, 0);
+            mOtherMonthDateColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_otherMonthDateColor, 0);
+            mGridLinesColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_gridLinesColor, 0);
+            mWeekNumberColor = attributesArray.getColor(
+                    R.styleable.DayPickerWeekView_weekNumberColor, 0);
+            mSelectedDayLine = attributesArray
+                    .getDrawable(R.styleable.DayPickerWeekView_selectedDayLine);
+            attributesArray.recycle();
+
+            if (sScale == 0) {
+                sScale = context.getResources().getDisplayMetrics().density;
+                if (sScale != 1) {
+                    mDefaultHeight *= sScale;
+                    mMinHeight *= sScale;
+                    mNumberTextSize *= sScale;
+                }
+            }
+
+            // Sets up any standard paints that will be used
+            setPaintProperties();
+        }
+
+        /**
+         * Sets all the parameters for displaying this week. The only required
+         * parameter is the week number. Other 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. See {@link #VIEW_PARAMS_HEIGHT} for more info on
+         * parameters.
+         *
+         * @param params A map of the new parameters, see
+         *            {@link #VIEW_PARAMS_HEIGHT}
+         */
+        public void setWeekParams(HashMap<String, Object> params) {
+            if (!params.containsKey(VIEW_PARAMS_WEEK)) {
+                throw new InvalidParameterException(
+                        "You must specify the week number for this view");
+            }
+            setTag(params);
+            // We keep the current value for any params not present
+            if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
+                mHeight = ((int[]) params.get(VIEW_PARAMS_HEIGHT))[0];
+                if (mHeight < mMinHeight) {
+                    mHeight = mMinHeight;
+                }
+            }
+            if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
+                mSelectedDay = ((int[]) params.get(VIEW_PARAMS_SELECTED_DAY))[0];
+            }
+            mHasSelectedDay = mSelectedDay != -1;
+            if (params.containsKey(VIEW_PARAMS_NUM_DAYS)) {
+                mNumDays = ((int[]) params.get(VIEW_PARAMS_NUM_DAYS))[0];
+            }
+            if (params.containsKey(VIEW_PARAMS_SHOW_WK_NUM)) {
+                if (((int[]) params.get(VIEW_PARAMS_SHOW_WK_NUM))[0] != 0) {
+                    mNumCells = mNumDays + 1;
+                    mShowWeekNum = true;
+                } else {
+                    mShowWeekNum = false;
+                }
+            } else {
+                mNumCells = mShowWeekNum ? mNumDays + 1 : mNumDays;
+            }
+            mWeek = ((int[]) params.get(VIEW_PARAMS_WEEK))[0];
+            mTempCalendar.clear();
+            mTempCalendar.set(1900, 0, 1);
+            mTempCalendar.add(Calendar.WEEK_OF_YEAR, mWeek);
+            if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
+                mTempCalendar.setFirstDayOfWeek(((int[]) params.get(VIEW_PARAMS_WEEK_START))[0]);
+            } else {
+                mTempCalendar.setFirstDayOfWeek(DEFAULT_WEEK_START);
+            }
+
+            // Allocate space for caching the day numbers and focus values
+            mDayNumbers = new String[mNumCells];
+            mFocusDay = new boolean[mNumCells];
+
+            // If we're showing the week number calculate it based on Monday
+            int i = 0;
+            if (mShowWeekNum) {
+                mDayNumbers[0] = Integer.toString(mTempCalendar.get(Calendar.WEEK_OF_YEAR));
+                i++;
+            }
+
+            // Now adjust our starting day based on the start day of the week
+            int diff = mTempCalendar.getFirstDayOfWeek() - mTempCalendar.get(Calendar.DAY_OF_WEEK);
+            mTempCalendar.add(Calendar.DAY_OF_MONTH, diff);
+
+            mFirstDay = (Calendar) mTempCalendar.clone();
+
+            mMonthOfFirstWeekDay = mTempCalendar.get(Calendar.MONTH);
+
+            int focusMonth = params.containsKey(VIEW_PARAMS_FOCUS_MONTH) ? ((int[]) params
+                    .get(VIEW_PARAMS_FOCUS_MONTH))[0] : DEFAULT_FOCUS_MONTH;
+
+            for (; i < mNumCells; i++) {
+                mFocusDay[i] = (mTempCalendar.get(Calendar.MONTH) == focusMonth);
+                mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+                mTempCalendar.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            // We do one extra add at the end of the loop, if that pushed us to
+            // new month undo it
+            if (mTempCalendar.get(Calendar.DAY_OF_MONTH) == 1) {
+                mTempCalendar.add(Calendar.DAY_OF_MONTH, -1);
+            }
+            mLastWeekDayMonth = mTempCalendar.get(Calendar.MONTH);
+
+            updateSelectionPositions();
+        }
+
+        /**
+         * Sets up the text and style properties for painting. Override this if
+         * you want to use a different paint.
+         */
+        protected void setPaintProperties() {
+            mDrawPaint.setFakeBoldText(false);
+            mDrawPaint.setAntiAlias(true);
+            mDrawPaint.setTextSize(mNumberTextSize);
+            mDrawPaint.setStyle(Style.FILL);
+
+            mMonthNumDrawPaint.setFakeBoldText(true);
+            mMonthNumDrawPaint.setAntiAlias(true);
+            mMonthNumDrawPaint.setTextSize(mNumberTextSize);
+            mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
+            mMonthNumDrawPaint.setStyle(Style.FILL);
+            mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+        }
+
+        /**
+         * Returns the month of the first day in this week.
+         *
+         * @return The month the first day of this view is in.
+         */
+        public int getMonthOfFirstWeekDay() {
+            return mMonthOfFirstWeekDay;
+        }
+
+        /**
+         * Returns the month of the last day in this week
+         *
+         * @return The month the last day of this view is in
+         */
+        public int getMonthOfLastWeekDay() {
+            return mLastWeekDayMonth;
+        }
+
+        /**
+         * Returns the first day in this view.
+         *
+         * @return The first day in the view.
+         */
+        public Calendar getFirstDay() {
+            return mFirstDay;
+        }
+
+        /**
+         * Returns the number of days this view will display.
+         */
+        public int getNumDays() {
+            return mNumDays;
+        }
+
+        /**
+         * Calculates the day that the given x position is in, accounting for
+         * week number. Returns a Time referencing that day or null if
+         *
+         * @param x The x position of the touch eventy
+         */
+        public void getDayFromLocation(float x, Calendar outCalendar) {
+            int dayStart = mShowWeekNum ? (mWidth - mPadding * 2) / mNumCells + mPadding : mPadding;
+            if (x < dayStart || x > mWidth - mPadding) {
+                outCalendar.set(0, 0, 0, 0, 0, 0);
+                return;
+            }
+            // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+            int dayPosition = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
+            outCalendar.setTimeZone(mFirstDay.getTimeZone());
+            outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
+            outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            drawBackground(canvas);
+            drawWeekNums(canvas);
+            drawDaySeparators(canvas);
+        }
+
+        /**
+         * This draws the selection highlight if a day is selected in this week.
+         * Override this method if you wish to have a different background
+         * drawn.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawBackground(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mDrawPaint.setColor(mSelectionBackgroundColor);
+
+            mTempRect.top = DAY_SEPARATOR_WIDTH;
+            mTempRect.bottom = mHeight;
+            mTempRect.left = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells
+                    : mPadding;
+            mTempRect.right = mSelectedLeft - 2;
+            canvas.drawRect(mTempRect, mDrawPaint);
+
+            mTempRect.left = mSelectedRight + 3;
+            mTempRect.right = mWidth - mPadding;
+            canvas.drawRect(mTempRect, mDrawPaint);
+        }
+
+        /**
+         * Draws the week and month day numbers for this week. Override this
+         * method if you need different placement.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawWeekNums(Canvas canvas) {
+            float textHeight = mDrawPaint.getTextSize();
+            int y = (int) ((mHeight + textHeight) / 2) - DAY_SEPARATOR_WIDTH;
+            int nDays = mNumCells;
+
+            mDrawPaint.setTextAlign(Align.CENTER);
+            int i = 0;
+            int divisor = 2 * nDays;
+            if (mShowWeekNum) {
+                mDrawPaint.setColor(mWeekNumberColor);
+                int x = (mWidth - mPadding * 2) / divisor + mPadding;
+                canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                i++;
+            }
+            for (; i < nDays; i++) {
+                mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                        : mOtherMonthDateColor);
+                int x = (2 * i + 1) * (mWidth - mPadding * 2) / divisor + mPadding;
+                canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+            }
+        }
+
+        /**
+         * Draws a horizontal line for separating the weeks. Override this
+         * method if you want custom separators.
+         *
+         * @param canvas The canvas to draw on
+         */
+        protected void drawDaySeparators(Canvas canvas) {
+            mDrawPaint.setColor(mGridLinesColor);
+            mDrawPaint.setStrokeWidth(DAY_SEPARATOR_WIDTH);
+            float x = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells : mPadding;
+            canvas.drawLine(x, 0, mWidth - mPadding, 0, mDrawPaint);
+
+            if (mHasSelectedDay) {
+                mSelectedDayLine.setBounds(mSelectedLeft - 2, DAY_SEPARATOR_WIDTH,
+                        mSelectedLeft + 4, mHeight + 1);
+                mSelectedDayLine.draw(canvas);
+                mSelectedDayLine.setBounds(mSelectedRight - 3, DAY_SEPARATOR_WIDTH,
+                        mSelectedRight + 3, mHeight + 1);
+                mSelectedDayLine.draw(canvas);
+            }
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            mWidth = w;
+            updateSelectionPositions();
+        }
+
+        /**
+         * This calculates the positions for the selected day lines.
+         */
+        protected void updateSelectionPositions() {
+            if (mHasSelectedDay) {
+                int selectedPosition = mSelectedDay - mTempCalendar.getFirstDayOfWeek();
+                if (selectedPosition < 0) {
+                    selectedPosition += 7;
+                }
+                if (mShowWeekNum) {
+                    selectedPosition++;
+                }
+                mSelectedLeft = selectedPosition * (mWidth - mPadding * 2) / mNumCells + mPadding;
+                mSelectedRight = (selectedPosition + 1) * (mWidth - mPadding * 2) / mNumCells
+                        + mPadding;
+            }
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+        }
+    }
+}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 43d194f..e5544e9 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -30,8 +30,8 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.Rect;
 import android.graphics.Paint.Align;
+import android.graphics.Rect;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Spanned;
@@ -41,11 +41,11 @@
 import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.LayoutInflater.Filter;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.LayoutInflater.Filter;
 import android.view.animation.OvershootInterpolator;
 import android.view.inputmethod.InputMethodManager;
 
@@ -166,7 +166,12 @@
     /**
      * Listener to be notified upon current value change.
      */
-    private OnChangedListener mListener;
+    private OnChangeListener mOnChangeListener;
+
+    /**
+     * Listener to be notified upon scroll state change.
+     */
+    private OnScrollListener mOnScrollListener;
 
     /**
      * Formatter for for displaying the current value.
@@ -308,9 +313,14 @@
     private final Rect mTempRect = new Rect();
 
     /**
+     * The current scroll state of the number picker.
+     */
+    private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
      * The callback interface used to indicate the number value has changed.
      */
-    public interface OnChangedListener {
+    public interface OnChangeListener {
         /**
          * @param picker The NumberPicker associated with this listener.
          * @param oldVal The previous value.
@@ -320,6 +330,36 @@
     }
 
     /**
+     * Interface for listening to the picker scroll state.
+     */
+    public interface OnScrollListener {
+
+        /**
+         * The view is not scrolling.
+         */
+        public static int SCROLL_STATE_IDLE = 0;
+
+        /**
+         * The user is scrolling using touch, and their finger is still on the screen.
+         */
+        public static int SCROLL_STATE_TOUCH_SCROLL = 1;
+
+        /**
+         * The user had previously been scrolling using touch and performed a fling.
+         */
+        public static int SCROLL_STATE_FLING = 2;
+
+        /**
+         * Callback method to be invoked while the number picker is being scrolled.
+         *
+         * @param view The view whose scroll state is being reported
+         * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
+         * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
+         */
+        public void onScrollStateChanged(NumberPicker view, int scrollState);
+    }
+
+    /**
      * Interface used to format the number into a string for presentation
      */
     public interface Formatter {
@@ -492,11 +532,15 @@
                 mBeginEditOnUpEvent = false;
                 mAdjustScrollerOnUpEvent = true;
                 if (mDrawSelectorWheel) {
-                    mBeginEditOnUpEvent = mFlingScroller.isFinished()
+                    boolean scrollersFinished = mFlingScroller.isFinished()
                             && mAdjustScroller.isFinished();
+                    if (!scrollersFinished) {
+                        mFlingScroller.forceFinished(true);
+                        mAdjustScroller.forceFinished(true);
+                        tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
+                    }
+                    mBeginEditOnUpEvent = scrollersFinished;
                     mAdjustScrollerOnUpEvent = true;
-                    mFlingScroller.forceFinished(true);
-                    mAdjustScroller.forceFinished(true);
                     hideInputControls();
                     return true;
                 }
@@ -512,6 +556,7 @@
                 int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
                 if (deltaDownY > mTouchSlop) {
                     mBeginEditOnUpEvent = false;
+                    tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                     setDrawSelectorWheel(true);
                     hideInputControls();
                     return true;
@@ -531,10 +576,12 @@
         switch (action) {
             case MotionEvent.ACTION_MOVE:
                 float currentMoveY = ev.getY();
-                if (mBeginEditOnUpEvent) {
+                if (mBeginEditOnUpEvent
+                        || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                     int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
                     if (deltaDownY > mTouchSlop) {
                         mBeginEditOnUpEvent = false;
+                        tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                     }
                 }
                 int deltaMoveY = (int) (currentMoveY - mLastMotionEventY);
@@ -550,6 +597,7 @@
                     InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
                             Context.INPUT_METHOD_SERVICE);
                     imm.showSoftInput(mInputText, 0);
+                    mInputText.setSelection(0, mInputText.getText().length());
                     return true;
                 }
                 VelocityTracker velocityTracker = mVelocityTracker;
@@ -557,6 +605,7 @@
                 int initialVelocity = (int) velocityTracker.getYVelocity();
                 if (Math.abs(initialVelocity) > mMinimumFlingVelocity) {
                     fling(initialVelocity);
+                    tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_FLING);
                 } else {
                     if (mAdjustScrollerOnUpEvent) {
                         if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) {
@@ -689,10 +738,19 @@
     /**
      * Set the callback that indicates the number has been adjusted by the user.
      *
-     * @param listener the callback, should not be null.
+     * @param onChangeListener the callback, should not be null.
      */
-    public void setOnChangeListener(OnChangedListener listener) {
-        mListener = listener;
+    public void setOnChangeListener(OnChangeListener onChangeListener) {
+        mOnChangeListener = onChangeListener;
+    }
+
+    /**
+     * Set the callback that in notified for scroll state changes.
+     *
+     * @param onScrollListener the callback, should not be null.
+     */
+    public void setOnScrollListener(OnScrollListener onScrollListener) {
+        mOnScrollListener = onScrollListener;
     }
 
     /**
@@ -966,6 +1024,7 @@
     private void onScrollerFinished(Scroller scroller) {
         if (scroller == mFlingScroller) {
             postAdjustScrollerCommand(0);
+            tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
         } else {
             showInputControls();
             updateInputTextView();
@@ -973,6 +1032,17 @@
     }
 
     /**
+     * Notifies the scroll listener for the given <code>scrollState</code>
+     * if the scroll state differs from the current scroll state.
+     */
+    private void tryNotifyScrollListener(int scrollState) {
+        if (mOnScrollListener != null && mScrollState != scrollState) {
+            mScrollState = scrollState;
+            mOnScrollListener.onScrollStateChanged(this, scrollState);
+        }
+    }
+
+    /**
      * Flings the selector with the given <code>velocityY</code>.
      */
     private void fling(int velocityY) {
@@ -1118,7 +1188,8 @@
             scrollSelectorValue = "";
         } else {
             if (mDisplayedValues != null) {
-                scrollSelectorValue = mDisplayedValues[selectorIndex];
+                int displayedValueIndex = selectorIndex - mStart;
+                scrollSelectorValue = mDisplayedValues[displayedValueIndex];
             } else {
                 scrollSelectorValue = formatNumber(selectorIndex);
             }
@@ -1167,8 +1238,8 @@
      * NumberPicker.
      */
     private void notifyChange(int previous, int current) {
-        if (mListener != null) {
-            mListener.onChanged(this, previous, mCurrent);
+        if (mOnChangeListener != null) {
+            mOnChangeListener.onChanged(this, previous, mCurrent);
         }
     }
 
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 6cf1387..24b5e4a 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -25,7 +25,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
 import java.text.DateFormatSymbols;
 import java.util.Calendar;
@@ -110,7 +110,7 @@
 
         // hour
         mHourPicker = (NumberPicker) findViewById(R.id.hour);
-        mHourPicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
+        mHourPicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
             public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentHour = newVal;
                 if (!mIs24HourView) {
@@ -137,7 +137,7 @@
         mMinutePicker.setRange(0, 59);
         mMinutePicker.setSpeed(100);
         mMinutePicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
+        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
             public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentMinute = newVal;
                 onTimeChanged();
@@ -146,7 +146,7 @@
 
         // am/pm
         mAmPmPicker = (NumberPicker) findViewById(R.id.amPm);
-        mAmPmPicker.setOnChangeListener(new OnChangedListener() {
+        mAmPmPicker.setOnChangeListener(new OnChangeListener() {
             public void onChanged(NumberPicker picker, int oldVal, int newVal) {
                 picker.requestFocus();
                 if (mIsAm) {
@@ -184,7 +184,7 @@
             setEnabled(false);
         }
     }
-    
+
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
diff --git a/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..ed1a5e9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..f264cb6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 4fd46b3..5c023ee 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -19,45 +19,74 @@
 
 <!-- Layout of date picker-->
 
-<!-- Warning: everything within the parent is removed and re-ordered depending
-     on the date format selected by the user. -->
+<!-- Warning: everything within the "pickers" layout is removed and re-ordered
+     depending on the date format selected by the user.
+-->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/parent"
-    android:orientation="horizontal"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
     android:layout_gravity="center_horizontal"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
+    android:orientation="horizontal"
+    android:gravity="center">
 
-    <!-- Month -->
-    <NumberPicker
-        android:id="@+id/month"
-        android:layout_width="80dip"
+    <LinearLayout android:id="@+id/pickers"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        android:layout_marginRight="15dip"
+        android:layout_weight="0.5"
+        android:orientation="horizontal"
+        android:gravity="center">
 
-    <!-- Day -->
-    <NumberPicker
-        android:id="@+id/day"
-        android:layout_width="80dip"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- Month -->
+        <NumberPicker
+            android:id="@+id/month"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
 
-    <!-- Year -->
-    <NumberPicker
-        android:id="@+id/year"
-        android:layout_width="95dip"
-        android:layout_height="wrap_content"
-        android:layout_marginLeft="1dip"
-        android:layout_marginRight="1dip"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        />
+        <!-- Day -->
+        <NumberPicker
+            android:id="@+id/day"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+        <!-- Year -->
+        <NumberPicker
+            android:id="@+id/year"
+            android:layout_width="48dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="15dip"
+            android:layout_marginTop="35dip"
+            android:layout_marginBottom="35dip"       
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+    </LinearLayout>
+
+    <!-- mini-month day-picker -->
+      <DayPicker
+          android:id="@+id/mini_month_day_picker"
+          android:layout_width="200dip"
+          android:layout_height="230dip"
+          android:layout_marginLeft="15dip"
+          android:layout_weight="0.5"
+          android:focusable="true"
+          android:focusableInTouchMode="true"
+          />
+
 </LinearLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 949c8a3..90de1f5 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -17,9 +17,14 @@
 */
 -->
 
+<!-- Note: We want the DatePicker to take as much space as possible, therefore
+           we set the width and height bigger than the max AlertDialog size
+           determined by our parent WeightedLinearLayout.
+
+           See: alert_dialog.xml
+-->
 <DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/datePicker"
-    android:padding="5dip"
     android:layout_gravity="center_horizontal"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"/>
+    android:layout_width="250dip"
+    android:layout_height="600dip"/>
diff --git a/core/res/res/layout/day_picker.xml b/core/res/res/layout/day_picker.xml
new file mode 100644
index 0000000..46ab450
--- /dev/null
+++ b/core/res/res/layout/day_picker.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true" >
+
+    <TextView android:id="@+android:id/month_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal" 
+        android:paddingTop="10dip"
+        android:paddingBottom="10dip"
+        style="@android:style/TextAppearance.Medium" />
+
+    <LinearLayout android:id="@+android:id/day_names"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="6dip"
+        android:layout_marginRight="2dip"
+        android:layout_marginLeft="2dip"
+        android:gravity="center">
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:visibility="gone" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            style="?android:attr/dayPickerWeekDayViewStyle" />
+
+    </LinearLayout>
+
+    <ListView android:id="@android:id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:drawSelectorOnTop="false"
+            android:cacheColorHint="@android:color/transparent"
+            android:fastScrollEnabled="false"
+            android:overScrollMode="never" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index fa288422..bf81c18 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -30,7 +30,7 @@
         android:id="@+id/hour"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginRight="20dip"
+        android:layout_marginRight="13dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
@@ -50,8 +50,8 @@
         android:id="@+id/minute"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="20dip"
-        android:layout_marginRight="22dip"
+        android:layout_marginLeft="13dip"
+        android:layout_marginRight="15dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
@@ -63,7 +63,7 @@
         android:id="@+id/amPm"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="22dip"
+        android:layout_marginLeft="15dip"
         android:layout_marginTop="35dip"
         android:layout_marginBottom="35dip"
         android:focusable="true"
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index d5a6b5e..09326c8 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -22,4 +22,4 @@
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:padding="5dip" />
+    />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 109fb0d..81191ff 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -503,16 +503,23 @@
         <attr name="listPopupWindowStyle" format="reference" />
         <!-- Default PopupMenu style. -->
         <attr name="popupMenuStyle" format="reference" />
-        <!-- NumberPicker up button style -->
+
+        <!-- @hide NumberPicker up button style -->
         <attr name="numberPickerUpButtonStyle" format="reference" />
-        <!-- NumberPicker down button style -->
+        <!-- @hide NumberPicker down button style -->
         <attr name="numberPickerDownButtonStyle" format="reference" />
-        <!-- NumberPicker input text style -->
+        <!-- @hide NumberPicker input text style -->
         <attr name="numberPickerInputTextStyle" format="reference" />
 
-        <!-- NumberPicker the fading edge length of the selector wheel -->
+        <!-- @hide NumberPicker the fading edge length of the selector wheel -->
         <attr name="numberPickerStyle" format="reference" />
 
+        <!-- @hide DayPicker$WeekView style-->
+        <attr name="dayPickerWeekViewStyle" format="reference" />
+
+        <!-- @hide DayPickerDayView style-->
+        <attr name="dayPickerWeekDayViewStyle" format="reference" />
+
         <!-- =================== -->
         <!-- Action bar styles   -->
         <!-- =================== -->
@@ -2943,6 +2950,16 @@
     </declare-styleable>
 
     <!-- @hide -->
+    <declare-styleable name="DayPickerWeekView">
+        <attr name="selectionBackgroundColor" format="color|reference" />
+        <attr name="focusedMonthDateColor" format="color|reference" />
+        <attr name="otherMonthDateColor" format="color|reference" />
+        <attr name="weekNumberColor" format="color|reference" />
+        <attr name="gridLinesColor" format="color|reference" />
+        <attr name="selectedDayLine" format="reference" />
+    </declare-styleable>
+
+    <!-- @hide -->
     <declare-styleable name="NumberPicker">
         <attr name="orientation" />
         <attr name="solidColor" format="color|reference" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ae029e5..8fa1d32 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1567,6 +1567,6 @@
   <public type="style" name="Holo.Light.ButtonBar.AlertDialog" />
   <public type="style" name="Holo.SegmentedButton" />
   <public type="style" name="Holo.Light.SegmentedButton" />
-
   <public type="string" name="selectTextMode" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9f98ce4..2e235f0 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2295,6 +2295,8 @@
 
     <!-- The title of the time picker dialog. [CHAR LIMIT=NONE] -->
     <string name="time_picker_dialog_title">Set time</string>
+    <!-- The title of the date picker dialog. [CHAR LIMIT=NONE] -->
+    <string name="date_picker_dialog_title">Set date</string>
     <!-- Name of the button in the date/time picker to accept the date/time change -->
     <string name="date_time_set">Set</string>
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 58553e1..8d7556f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -238,6 +238,11 @@
         <item name="android:textColor">#ff272727</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Small.DayPickerWeekDayView">
+        <item name="android:textStyle">bold</item>
+    </style>
+
     <!-- Widget Styles -->
 
     <style name="Widget">
@@ -468,21 +473,35 @@
         <item name="android:background">@android:drawable/btn_default</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.DayPickerWeekView">
+        <item name="android:selectionBackgroundColor">#330099FF</item>
+        <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:weekNumberColor">#33FFFFFF</item>
+        <item name="android:gridLinesColor">#19FFFFFF</item>
+        <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+    </style>
+
+    <!-- @hide -->
     <style name="Widget.NumberPicker">
         <item name="android:orientation">vertical</item>
         <item name="android:fadingEdge">vertical</item>
         <item name="android:fadingEdgeLength">50dip</item>
-        <item name="android:solidColor">?android:attr/colorBackground</item>
+        <item name="android:solidColor">@android:color/transparent</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerUpButton">
         <item name="android:background">@android:drawable/timepicker_up_btn</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerDownButton">
         <item name="android:background">@android:drawable/timepicker_down_btn</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.EditText.NumberPickerInputText">
         <item name="android:textAppearance">@style/TextAppearance.Large.Inverse.NumberPickerInputText</item>
         <item name="android:gravity">center</item>
@@ -834,6 +853,7 @@
         <item name="android:textStyle">bold</item>
     </style>
 
+    <!-- @hide -->
     <style name="TextAppearance.Large.Inverse.NumberPickerInputText">
         <item name="android:textColor">@android:color/primary_text_light</item>
         <item name="android:textSize">30sp</item>
@@ -1200,6 +1220,11 @@
         <item name="android:textSize">18sp</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Holo.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+        <item name="android:textColor">#505050</item>
+    </style>
+
     <!-- Light text styles -->
     <style name="TextAppearance.Holo.Light" parent="TextAppearance.Holo">
     </style>
@@ -1296,6 +1321,10 @@
         <item name="android:textSize">18sp</item>
     </style>
 
+    <!-- @hide -->
+    <style name="TextAppearance.Holo.Light.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+    </style>
+
     <!-- Widget Styles -->
 
     <style name="Widget.Holo" parent="Widget">
@@ -1406,22 +1435,35 @@
         <item name="android:listSelector">?android:attr/selectableItemBackground</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.Holo.DayPickerWeekView">
+        <item name="android:selectionBackgroundColor">#330099FF</item>
+        <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:weekNumberColor">#33FFFFFF</item>
+        <item name="android:gridLinesColor">#19FFFFFF</item>
+        <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+    </style>
+
     <style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
         <item name="android:background">@android:drawable/btn_default_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerUpButton">
         <item name="android:background">@null</item>
         <item name="android:paddingBottom">26sp</item>
         <item name="android:src">@android:drawable/timepicker_up_btn_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@null</item>
         <item name="android:paddingTop">26sp</item>
         <item name="android:src">@android:drawable/timepicker_down_btn_holo_dark</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.EditText.NumberPickerInputText">
         <item name="android:paddingTop">13sp</item>
         <item name="android:paddingBottom">13sp</item>
@@ -1767,14 +1809,21 @@
         <item name="android:background">@android:drawable/btn_default_holo_light</item>
     </style>
 
+    <!-- @hide -->
+    <style name="Widget.Holo.Light.DayPickerWeekView" parent="Widget.DayPickerWeekView">
+    </style>
+
+    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerUpButton" parent="Widget.Holo.Light.ImageButton.NumberPickerUpButton">
         <item name="android:background">@android:drawable/timepicker_up_btn_holo_light</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerDownButton" parent="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@android:drawable/timepicker_down_btn_holo_light</item>
     </style>
 
+    <!-- @hide -->
     <style name="Widget.Holo.Light.EditText.NumberPickerInputText" parent="Widget.Holo.EditText.NumberPickerInputText">
     </style>
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 0f21e9f..94e8f96 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -26,7 +26,7 @@
          of it a dark color.
     -->
     <style name="Theme">
-    
+
         <item name="colorForeground">@android:color/bright_foreground_dark</item>
         <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
         <item name="colorBackground">@android:color/background_dark</item>
@@ -280,6 +280,12 @@
         <item name="numberPickerInputTextStyle">@style/Widget.EditText.NumberPickerInputText</item>
         <item name="numberPickerStyle">@style/Widget.NumberPicker</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Small.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- Variant of the default (dark) theme with no title bar -->
@@ -917,6 +923,12 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.EditText.NumberPickerInputText</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- New Honeycomb holographic theme. Light version.  The widgets in the
@@ -1162,6 +1174,12 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.Light.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.Light.EditText.NumberPickerInputText</item>
 
+        <!-- DayPicker$WeekView style-->
+        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.Light.DayPickerWeekView</item>
+
+        <!-- DayPickerWeekDayView style-->
+        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.Light.DayPickerWeekDayView</item>
+
     </style>
 
     <!-- Development legacy name; if you're using this, switch. -->
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 6587b51..d4edafd 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -378,6 +378,12 @@
 static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) {
     const ScriptCState::SymbolTable_t *sym;
     ScriptC *s = (ScriptC *)pContext;
+    if (!strcmp(name, "__isThreadable")) {
+      return (BCCvoid*) s->mEnviroment.mIsThreadable;
+    } else if (!strcmp(name, "__clearThreadable")) {
+      s->mEnviroment.mIsThreadable = false;
+      return NULL;
+    }
     sym = ScriptCState::lookupSymbol(name);
     if (!sym) {
         sym = ScriptCState::lookupSymbolCL(name);
diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
new file mode 100644
index 0000000..7d41d1c
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.animation.PropertyValuesHolder
+ *
+ * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ *
+ * The main goal of this class' methods are to provide a native way to access setters and getters
+ * on some object. In this case we want to default to using Java reflection instead so the native
+ * methods do nothing.
+ *
+ */
+/*package*/ class PropertyValuesHolder_Delegate {
+
+    /*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) {
+        // return 0 to force PropertyValuesHolder to use Java reflection.
+        return 0;
+    }
+
+    /*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) {
+        // return 0 to force PropertyValuesHolder to use Java reflection.
+        return 0;
+    }
+
+    /*package*/ static void nCallIntMethod(Object target, int methodID, int arg) {
+        // do nothing
+    }
+
+    /*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) {
+        // do nothing
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index d58cde8..0130970 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -458,16 +458,10 @@
                 mCanvas.setDensity(mParams.getDensity());
             }
 
-            long preDrawTime = System.currentTimeMillis();
-
             mViewRoot.draw(mCanvas);
 
-            long drawTime = System.currentTimeMillis();
-
             mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
 
-            System.out.println(String.format("rendering (ms): %03d", drawTime - preDrawTime));
-
             // success!
             return SceneStatus.SUCCESS.createResult();
         } catch (Throwable e) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4440685..1d40d33 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -105,6 +105,7 @@
      * The list of classes on which to delegate all native methods.
      */
     private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
+        "android.animation.PropertyValuesHolder",
         "android.graphics.Bitmap",
         "android.graphics.Canvas",
         "android.graphics.DashPathEffect",