Added day of week and year/month/day to digital.

Adds internationalized day of week, month, day of month, and year
to the sample digital watchface.
Listens for Locale changes in order to update the date formatter
objects in the digital watchface.

Bug: 21299339
Change-Id: I7216dbfaa6a7009acf99c9437fc3c6f0a234660d
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceService.java
index 0bc420d..a661cdc 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceService.java
@@ -46,7 +46,10 @@
 import com.google.android.gms.wearable.DataMapItem;
 import com.google.android.gms.wearable.Wearable;
 
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
 
@@ -123,16 +126,26 @@
                 .addApi(Wearable.API)
                 .build();
 
-        final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
+        /**
+         * Handles time zone and locale changes.
+         */
+        final BroadcastReceiver mReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 mCalendar.setTimeZone(TimeZone.getDefault());
+                initFormats();
                 invalidate();
             }
         };
-        boolean mRegisteredTimeZoneReceiver = false;
+
+        /**
+         * Unregistering an unregistered receiver throws an exception. Keep track of the
+         * registration state to prevent that.
+         */
+        boolean mRegisteredReceiver = false;
 
         Paint mBackgroundPaint;
+        Paint mDatePaint;
         Paint mHourPaint;
         Paint mMinutePaint;
         Paint mSecondPaint;
@@ -140,10 +153,16 @@
         Paint mColonPaint;
         float mColonWidth;
         boolean mMute;
+
         Calendar mCalendar;
+        Date mDate;
+        SimpleDateFormat mDayOfWeekFormat;
+        java.text.DateFormat mDateFormat;
+
         boolean mShouldDrawColons;
         float mXOffset;
         float mYOffset;
+        float mLineHeight;
         String mAmString;
         String mPmString;
         int mInteractiveBackgroundColor =
@@ -175,11 +194,13 @@
                     .build());
             Resources resources = DigitalWatchFaceService.this.getResources();
             mYOffset = resources.getDimension(R.dimen.digital_y_offset);
+            mLineHeight = resources.getDimension(R.dimen.digital_line_height);
             mAmString = resources.getString(R.string.digital_am);
             mPmString = resources.getString(R.string.digital_pm);
 
             mBackgroundPaint = new Paint();
             mBackgroundPaint.setColor(mInteractiveBackgroundColor);
+            mDatePaint = createTextPaint(resources.getColor(R.color.digital_date));
             mHourPaint = createTextPaint(mInteractiveHourDigitsColor, BOLD_TYPEFACE);
             mMinutePaint = createTextPaint(mInteractiveMinuteDigitsColor);
             mSecondPaint = createTextPaint(mInteractiveSecondDigitsColor);
@@ -187,6 +208,8 @@
             mColonPaint = createTextPaint(resources.getColor(R.color.digital_colons));
 
             mCalendar = Calendar.getInstance();
+            mDate = new Date();
+            initFormats();
         }
 
         @Override
@@ -219,8 +242,9 @@
 
                 registerReceiver();
 
-                // Update time zone in case it changed while we weren't visible.
+                // Update time zone and date formats, in case they changed while we weren't visible.
                 mCalendar.setTimeZone(TimeZone.getDefault());
+                initFormats();
             } else {
                 unregisterReceiver();
 
@@ -235,21 +259,29 @@
             updateTimer();
         }
 
+        private void initFormats() {
+            mDayOfWeekFormat = new SimpleDateFormat("EEEE", Locale.getDefault());
+            mDayOfWeekFormat.setCalendar(mCalendar);
+            mDateFormat = DateFormat.getDateFormat(DigitalWatchFaceService.this);
+            mDateFormat.setCalendar(mCalendar);
+        }
+
         private void registerReceiver() {
-            if (mRegisteredTimeZoneReceiver) {
+            if (mRegisteredReceiver) {
                 return;
             }
-            mRegisteredTimeZoneReceiver = true;
+            mRegisteredReceiver = true;
             IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
-            DigitalWatchFaceService.this.registerReceiver(mTimeZoneReceiver, filter);
+            filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+            DigitalWatchFaceService.this.registerReceiver(mReceiver, filter);
         }
 
         private void unregisterReceiver() {
-            if (!mRegisteredTimeZoneReceiver) {
+            if (!mRegisteredReceiver) {
                 return;
             }
-            mRegisteredTimeZoneReceiver = false;
-            DigitalWatchFaceService.this.unregisterReceiver(mTimeZoneReceiver);
+            mRegisteredReceiver = false;
+            DigitalWatchFaceService.this.unregisterReceiver(mReceiver);
         }
 
         @Override
@@ -269,6 +301,7 @@
             float amPmSize = resources.getDimension(isRound
                     ? R.dimen.digital_am_pm_size_round : R.dimen.digital_am_pm_size);
 
+            mDatePaint.setTextSize(resources.getDimension(R.dimen.digital_date_text_size));
             mHourPaint.setTextSize(textSize);
             mMinutePaint.setTextSize(textSize);
             mSecondPaint.setTextSize(textSize);
@@ -321,6 +354,7 @@
 
             if (mLowBitAmbient) {
                 boolean antiAlias = !inAmbientMode;
+                mDatePaint.setAntiAlias(antiAlias);
                 mHourPaint.setAntiAlias(antiAlias);
                 mMinutePaint.setAntiAlias(antiAlias);
                 mSecondPaint.setAntiAlias(antiAlias);
@@ -335,7 +369,7 @@
         }
 
         private void adjustPaintColorToCurrentMode(Paint paint, int interactiveColor,
-                int ambientColor) {
+                                                   int ambientColor) {
             paint.setColor(isInAmbientMode() ? ambientColor : interactiveColor);
         }
 
@@ -353,6 +387,7 @@
             if (mMute != inMuteMode) {
                 mMute = inMuteMode;
                 int alpha = inMuteMode ? MUTE_ALPHA : NORMAL_ALPHA;
+                mDatePaint.setAlpha(alpha);
                 mHourPaint.setAlpha(alpha);
                 mMinutePaint.setAlpha(alpha);
                 mColonPaint.setAlpha(alpha);
@@ -409,7 +444,9 @@
 
         @Override
         public void onDraw(Canvas canvas, Rect bounds) {
-            mCalendar.setTimeInMillis(System.currentTimeMillis());
+            long now = System.currentTimeMillis();
+            mCalendar.setTimeInMillis(now);
+            mDate.setTime(now);
             boolean is24Hour = DateFormat.is24HourFormat(DigitalWatchFaceService.this);
 
             // Show colons for the first half of each second so the colons blink on when the time
@@ -430,9 +467,6 @@
                     hour = 12;
                 }
                 hourString = String.valueOf(hour);
-                if (hour < 10) {
-                    x += mHourPaint.measureText("0");
-                }
             }
             canvas.drawText(hourString, x, mYOffset, mHourPaint);
             x += mHourPaint.measureText(hourString);
@@ -463,6 +497,19 @@
                 canvas.drawText(getAmPmString(
                         mCalendar.get(Calendar.AM_PM)), x, mYOffset, mAmPmPaint);
             }
+
+            // Only render the day of week and date if there is no peek card, so they do not bleed
+            // into each other in ambient mode.
+            if (getPeekCardPosition().isEmpty()) {
+                // Day of week
+                canvas.drawText(
+                        mDayOfWeekFormat.format(mDate),
+                        mXOffset, mYOffset + mLineHeight, mDatePaint);
+                // Date
+                canvas.drawText(
+                        mDateFormat.format(mDate),
+                        mXOffset, mYOffset + mLineHeight * 2, mDatePaint);
+            }
         }
 
         /**
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml b/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml
index 0da08ed..1370192 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml
@@ -14,6 +14,7 @@
  limitations under the License.
 -->
 <resources>
+    <color name="digital_date">#aaaaaa</color>
     <color name="digital_am_pm">#aaaaa0</color>
     <color name="digital_colons">#aaaaa0</color>
     <color name="config_activity_background">#ffffff</color>
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml b/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml
index 8f04e56..aef847b 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml
@@ -16,11 +16,13 @@
 <resources>
     <dimen name="digital_text_size">40dp</dimen>
     <dimen name="digital_text_size_round">45dp</dimen>
+    <dimen name="digital_date_text_size">20dp</dimen>
     <dimen name="digital_am_pm_size">25dp</dimen>
     <dimen name="digital_am_pm_size_round">30dp</dimen>
     <dimen name="digital_x_offset">15dp</dimen>
     <dimen name="digital_x_offset_round">25dp</dimen>
-    <dimen name="digital_y_offset">90dp</dimen>
+    <dimen name="digital_y_offset">80dp</dimen>
+    <dimen name="digital_line_height">25dp</dimen>
     <dimen name="digital_config_color_picker_item_margin">32dp</dimen>
     <dimen name="content_padding_start">12dp</dimen>
 </resources>