Update WatchFace project to remove old watch faces that
are no longer good practice and change structure to make sample clearer.

Bug: 32214858
Change-Id: I8f6c2c0e56208e1c557cd9e185ddebd443bb0dab
diff --git a/wearable/wear/WatchFace/Wearable/src/main/AndroidManifest.xml b/wearable/wear/WatchFace/Wearable/src/main/AndroidManifest.xml
index 09b914e..5ac66de 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/AndroidManifest.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2017 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.
@@ -57,7 +57,7 @@
             android:required="false"/>
 
         <service
-            android:name=".AnalogWatchFaceService"
+            android:name=".watchfaces.AnalogWatchFaceService"
             android:label="@string/analog_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -80,27 +80,7 @@
             </intent-filter>
         </service>
         <service
-            android:name=".SweepWatchFaceService"
-            android:label="@string/sweep_name"
-            android:permission="android.permission.BIND_WALLPAPER">
-            <meta-data
-                android:name="android.service.wallpaper"
-                android:resource="@xml/watch_face"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview"
-                android:resource="@drawable/preview_analog"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview_circular"
-                android:resource="@drawable/preview_analog_circular"/>
-
-            <intent-filter>
-                <action android:name="android.service.wallpaper.WallpaperService"/>
-
-                <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
-            </intent-filter>
-        </service>
-        <service
-            android:name=".OpenGLWatchFaceService"
+            android:name=".watchfaces.OpenGLWatchFaceService"
             android:label="@string/opengl_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -123,30 +103,7 @@
             </intent-filter>
         </service>
         <service
-            android:name=".CardBoundsWatchFaceService"
-            android:label="@string/card_bounds_name"
-            android:permission="android.permission.BIND_WALLPAPER">
-            <meta-data
-                android:name="android.service.wallpaper"
-                android:resource="@xml/watch_face"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview"
-                android:resource="@drawable/preview_card_bounds"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview_circular"
-                android:resource="@drawable/preview_card_bounds_circular"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.companionConfigurationAction"
-                android:value="com.example.android.wearable.watchface.CONFIG_CARD_BOUNDS"/>
-
-            <intent-filter>
-                <action android:name="android.service.wallpaper.WallpaperService"/>
-
-                <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
-            </intent-filter>
-        </service>
-        <service
-            android:name=".ComplicationSimpleWatchFaceService"
+            android:name=".watchfaces.ComplicationSimpleWatchFaceService"
             android:enabled="true"
             android:label="@string/complication_simple"
             android:permission="android.permission.BIND_WALLPAPER">
@@ -172,7 +129,7 @@
 
         <activity android:name="android.support.wearable.complications.ComplicationHelperActivity"/>
         <activity
-            android:name=".ComplicationSimpleConfigActivity"
+            android:name=".config.ComplicationSimpleConfigActivity"
             android:label="@string/complication_simple">
             <intent-filter>
                 <action android:name="com.example.android.wearable.watchface.CONFIG_COMPLICATION_SIMPLE"/>
@@ -183,7 +140,7 @@
         </activity>
 
         <service
-            android:name=".InteractiveWatchFaceService"
+            android:name=".watchfaces.InteractiveWatchFaceService"
             android:label="@string/interactive_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -202,8 +159,9 @@
                 <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
             </intent-filter>
         </service>
+
         <service
-            android:name=".DigitalWatchFaceService"
+            android:name=".watchfaces.DigitalWatchFaceService"
             android:label="@string/digital_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -236,7 +194,7 @@
         -->
 
         <activity
-            android:name=".DigitalWatchFaceWearableConfigActivity"
+            android:name=".config.DigitalWatchFaceWearableConfigActivity"
             android:label="@string/digital_config_name">
             <intent-filter>
                 <action android:name="com.example.android.wearable.watchface.CONFIG_DIGITAL"/>
@@ -246,27 +204,7 @@
             </intent-filter>
         </activity>
 
-        <service
-            android:name=".CalendarWatchFaceService"
-            android:label="@string/calendar_name"
-            android:permission="android.permission.BIND_WALLPAPER">
-            <meta-data
-                android:name="android.service.wallpaper"
-                android:resource="@xml/watch_face"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview"
-                android:resource="@drawable/preview_calendar"/>
-            <meta-data
-                android:name="com.google.android.wearable.watchface.preview_circular"
-                android:resource="@drawable/preview_calendar_circular"/>
-
-            <intent-filter>
-                <action android:name="android.service.wallpaper.WallpaperService"/>
-
-                <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
-            </intent-filter>
-        </service>
-        <service android:name=".DigitalWatchFaceConfigListenerService">
+        <service android:name=".config.DigitalWatchFaceConfigListenerService">
             <intent-filter>
                 <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED"/>
 
@@ -277,7 +215,7 @@
             </intent-filter>
         </service>
         <service
-            android:name=".FitDistanceWatchFaceService"
+            android:name=".watchfaces.FitDistanceWatchFaceService"
             android:label="@string/fit_distance_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -300,7 +238,7 @@
             </intent-filter>
         </service>
         <service
-            android:name=".FitStepsWatchFaceService"
+            android:name=".watchfaces.FitStepsWatchFaceService"
             android:label="@string/fit_steps_name"
             android:permission="android.permission.BIND_WALLPAPER">
             <meta-data
@@ -320,13 +258,8 @@
             </intent-filter>
         </service>
 
-        <activity
-            android:name=".CalendarWatchFacePermissionActivity"
-            android:label="@string/title_activity_calendar_watch_face_permission">
-        </activity>
-
         <service
-            android:name=".provider.RandomNumberProviderService"
+            android:name=".providers.RandomNumberProviderService"
             android:icon="@drawable/ic_launcher"
             android:label="@string/complications_provider_random_number"
             android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
@@ -355,7 +288,7 @@
                 android:value="600"/>
         </service>
         <service
-            android:name=".provider.UpdateComplicationDataService"
+            android:name=".providers.UpdateComplicationDataService"
             android:exported="false">
         </service>
     </application>
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFacePermissionActivity.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFacePermissionActivity.java
deleted file mode 100644
index 7effd33..0000000
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFacePermissionActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.example.android.wearable.watchface;
-
-import android.Manifest;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityCompat;
-import android.support.wearable.activity.WearableActivity;
-import android.util.Log;
-import android.view.View;
-
-/**
- * Simple Activity for displaying Calendar Permission Rationale to user.
- */
-public class CalendarWatchFacePermissionActivity extends WearableActivity {
-
-    private static final String TAG = "PermissionActivity";
-
-    /* Id to identify permission request for calendar. */
-    private static final int PERMISSION_REQUEST_READ_CALENDAR = 1;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_calendar_watch_face_permission);
-        setAmbientEnabled();
-    }
-
-    public void onClickEnablePermission(View view) {
-        Log.d(TAG, "onClickEnablePermission()");
-
-        // On 23+ (M+) devices, GPS permission not granted. Request permission.
-        ActivityCompat.requestPermissions(
-                this,
-                new String[]{Manifest.permission.READ_CALENDAR},
-                PERMISSION_REQUEST_READ_CALENDAR);
-
-    }
-
-    /*
-     * Callback received when a permissions request has been completed.
-     */
-    @Override
-    public void onRequestPermissionsResult(
-            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
-
-        Log.d(TAG, "onRequestPermissionsResult()");
-
-        if (requestCode == PERMISSION_REQUEST_READ_CALENDAR) {
-            if ((grantResults.length == 1)
-                    && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
-                finish();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFaceService.java
deleted file mode 100644
index 98a251c..0000000
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CalendarWatchFaceService.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.android.wearable.watchface;
-
-import android.Manifest;
-import android.content.BroadcastReceiver;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.support.v4.app.ActivityCompat;
-import android.support.wearable.provider.WearableCalendarContract;
-import android.support.wearable.watchface.CanvasWatchFaceService;
-import android.support.wearable.watchface.WatchFaceService;
-import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.DynamicLayout;
-import android.text.Editable;
-import android.text.Html;
-import android.text.Layout;
-import android.text.SpannableStringBuilder;
-import android.text.TextPaint;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.view.SurfaceHolder;
-
-/**
- * Proof of concept sample watch face that demonstrates how a watch face can load calendar data.
- */
-public class CalendarWatchFaceService extends CanvasWatchFaceService {
-    private static final String TAG = "CalendarWatchFace";
-
-    @Override
-    public Engine onCreateEngine() {
-        return new Engine();
-    }
-
-    private class Engine extends CanvasWatchFaceService.Engine {
-
-        static final int BACKGROUND_COLOR = Color.BLACK;
-        static final int FOREGROUND_COLOR = Color.WHITE;
-        static final int TEXT_SIZE = 25;
-        static final int MSG_LOAD_MEETINGS = 0;
-
-        /** Editable string containing the text to draw with the number of meetings in bold. */
-        final Editable mEditable = new SpannableStringBuilder();
-
-        /** Width specified when {@link #mLayout} was created. */
-        int mLayoutWidth;
-
-        /** Layout to wrap {@link #mEditable} onto multiple lines. */
-        DynamicLayout mLayout;
-
-        /** Paint used to draw text. */
-        final TextPaint mTextPaint = new TextPaint();
-
-        int mNumMeetings;
-        private boolean mCalendarPermissionApproved;
-        private String mCalendarNotApprovedMessage;
-
-        private AsyncTask<Void, Void, Integer> mLoadMeetingsTask;
-
-        private boolean mIsReceiverRegistered;
-
-        /** Handler to load the meetings once a minute in interactive mode. */
-        final Handler mLoadMeetingsHandler = new Handler() {
-            @Override
-            public void handleMessage(Message message) {
-                switch (message.what) {
-                    case MSG_LOAD_MEETINGS:
-
-                        cancelLoadMeetingTask();
-
-                        // Loads meetings.
-                        if (mCalendarPermissionApproved) {
-                            mLoadMeetingsTask = new LoadMeetingsTask();
-                            mLoadMeetingsTask.execute();
-                        }
-                        break;
-                }
-            }
-        };
-
-        private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (Intent.ACTION_PROVIDER_CHANGED.equals(intent.getAction())
-                        && WearableCalendarContract.CONTENT_URI.equals(intent.getData())) {
-                    mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS);
-                }
-            }
-        };
-
-        @Override
-        public void onCreate(SurfaceHolder holder) {
-            super.onCreate(holder);
-            Log.d(TAG, "onCreate");
-
-            mCalendarNotApprovedMessage =
-                    getResources().getString(R.string.calendar_permission_not_approved);
-
-            /* Accepts tap events to allow permission changes by user. */
-            setWatchFaceStyle(new WatchFaceStyle.Builder(CalendarWatchFaceService.this)
-                    .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
-                    .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
-                    .setShowSystemUiTime(false)
-                    .setAcceptsTapEvents(true)
-                    .build());
-
-            mTextPaint.setColor(FOREGROUND_COLOR);
-            mTextPaint.setTextSize(TEXT_SIZE);
-
-            // Enables app to handle 23+ (M+) style permissions.
-            mCalendarPermissionApproved =
-                    ActivityCompat.checkSelfPermission(
-                            getApplicationContext(),
-                            Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED;
-
-            if (mCalendarPermissionApproved) {
-                mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS);
-            }
-        }
-
-        @Override
-        public void onDestroy() {
-            mLoadMeetingsHandler.removeMessages(MSG_LOAD_MEETINGS);
-            super.onDestroy();
-        }
-
-        /*
-         * Captures tap event (and tap type) and increments correct tap type total.
-         */
-        @Override
-        public void onTapCommand(int tapType, int x, int y, long eventTime) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "Tap Command: " + tapType);
-            }
-
-            // Ignore lint error (fixed in wearable support library 1.4)
-            if (tapType == WatchFaceService.TAP_TYPE_TAP && !mCalendarPermissionApproved) {
-                Intent permissionIntent = new Intent(
-                        getApplicationContext(),
-                        CalendarWatchFacePermissionActivity.class);
-                permissionIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                startActivity(permissionIntent);
-            }
-        }
-
-        @Override
-        public void onDraw(Canvas canvas, Rect bounds) {
-            // Create or update mLayout if necessary.
-            if (mLayout == null || mLayoutWidth != bounds.width()) {
-                mLayoutWidth = bounds.width();
-                mLayout = new DynamicLayout(mEditable, mTextPaint, mLayoutWidth,
-                        Layout.Alignment.ALIGN_NORMAL, 1 /* spacingMult */, 0 /* spacingAdd */,
-                        false /* includePad */);
-            }
-
-            // Update the contents of mEditable.
-            mEditable.clear();
-
-            if (mCalendarPermissionApproved) {
-                mEditable.append(Html.fromHtml(getResources().getQuantityString(
-                        R.plurals.calendar_meetings, mNumMeetings, mNumMeetings)));
-            } else {
-                mEditable.append(Html.fromHtml(mCalendarNotApprovedMessage));
-            }
-
-            // Draw the text on a solid background.
-            canvas.drawColor(BACKGROUND_COLOR);
-            mLayout.draw(canvas);
-        }
-
-        @Override
-        public void onVisibilityChanged(boolean visible) {
-            Log.d(TAG, "onVisibilityChanged()");
-            super.onVisibilityChanged(visible);
-            if (visible) {
-
-                // Enables app to handle 23+ (M+) style permissions.
-                mCalendarPermissionApproved = ActivityCompat.checkSelfPermission(
-                        getApplicationContext(),
-                        Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED;
-
-                if (mCalendarPermissionApproved) {
-                    IntentFilter filter = new IntentFilter(Intent.ACTION_PROVIDER_CHANGED);
-                    filter.addDataScheme("content");
-                    filter.addDataAuthority(WearableCalendarContract.AUTHORITY, null);
-                    registerReceiver(mBroadcastReceiver, filter);
-                    mIsReceiverRegistered = true;
-
-                    mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS);
-                }
-            } else {
-                if (mIsReceiverRegistered) {
-                    unregisterReceiver(mBroadcastReceiver);
-                    mIsReceiverRegistered = false;
-                }
-                mLoadMeetingsHandler.removeMessages(MSG_LOAD_MEETINGS);
-            }
-        }
-
-        private void onMeetingsLoaded(Integer result) {
-            if (result != null) {
-                mNumMeetings = result;
-                invalidate();
-            }
-        }
-
-        private void cancelLoadMeetingTask() {
-            if (mLoadMeetingsTask != null) {
-                mLoadMeetingsTask.cancel(true);
-            }
-        }
-
-        /**
-         * Asynchronous task to load the meetings from the content provider and report the number of
-         * meetings back via {@link #onMeetingsLoaded}.
-         */
-        private class LoadMeetingsTask extends AsyncTask<Void, Void, Integer> {
-            private PowerManager.WakeLock mWakeLock;
-
-            @Override
-            protected Integer doInBackground(Void... voids) {
-                PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
-                mWakeLock = powerManager.newWakeLock(
-                        PowerManager.PARTIAL_WAKE_LOCK, "CalendarWatchFaceWakeLock");
-                mWakeLock.acquire();
-
-                long begin = System.currentTimeMillis();
-                Uri.Builder builder =
-                        WearableCalendarContract.Instances.CONTENT_URI.buildUpon();
-                ContentUris.appendId(builder, begin);
-                ContentUris.appendId(builder, begin + DateUtils.DAY_IN_MILLIS);
-                final Cursor cursor = getContentResolver().query(builder.build(),
-                        null, null, null, null);
-                int numMeetings = cursor.getCount();
-
-                Log.d(TAG, "Num meetings: " + numMeetings);
-
-                return numMeetings;
-            }
-
-            @Override
-            protected void onPostExecute(Integer result) {
-                releaseWakeLock();
-                onMeetingsLoaded(result);
-            }
-
-            @Override
-            protected void onCancelled() {
-                releaseWakeLock();
-            }
-
-            private void releaseWakeLock() {
-                if (mWakeLock != null) {
-                    mWakeLock.release();
-                    mWakeLock = null;
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CardBoundsWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CardBoundsWatchFaceService.java
deleted file mode 100644
index 359d7af..0000000
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/CardBoundsWatchFaceService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.android.wearable.watchface;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.support.wearable.watchface.CanvasWatchFaceService;
-import android.support.wearable.watchface.WatchFaceStyle;
-import android.util.Log;
-import android.view.SurfaceHolder;
-
-/**
- * Proof of concept sample watch face that demonstrates how a watch face can detect where the peek
- * card is. This watch face draws a border around the area where the peeking card is.
- */
-public class CardBoundsWatchFaceService extends CanvasWatchFaceService {
-
-    private static final String TAG = "CardBoundsWatchFace";
-
-    @Override
-    public Engine onCreateEngine() {
-        return new Engine();
-    }
-
-    private class Engine extends CanvasWatchFaceService.Engine {
-
-        static final int BORDER_WIDTH_PX = 5;
-
-        final Rect mCardBounds = new Rect();
-        final Paint mPaint = new Paint();
-
-        @Override
-        public void onCreate(SurfaceHolder holder) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onCreate");
-            }
-            super.onCreate(holder);
-            setWatchFaceStyle(new WatchFaceStyle.Builder(CardBoundsWatchFaceService.this)
-                    .setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
-                    .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
-                    .setShowSystemUiTime(true)
-                    .setPeekOpacityMode(WatchFaceStyle.PEEK_OPACITY_MODE_TRANSLUCENT)
-                    .build());
-        }
-
-        @Override
-        public void onAmbientModeChanged(boolean inAmbientMode) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onAmbientModeChanged: " + inAmbientMode);
-            }
-            super.onAmbientModeChanged(inAmbientMode);
-            invalidate();
-        }
-
-        @Override
-        public void onPeekCardPositionUpdate(Rect bounds) {
-            super.onPeekCardPositionUpdate(bounds);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onPeekCardPositionUpdate: " + bounds);
-            }
-            super.onPeekCardPositionUpdate(bounds);
-            if (!bounds.equals(mCardBounds)) {
-                mCardBounds.set(bounds);
-                invalidate();
-            }
-        }
-
-        @Override
-        public void onDraw(Canvas canvas, Rect bounds) {
-            // Clear screen.
-            canvas.drawColor(isInAmbientMode() ? Color.BLACK : Color.BLUE);
-
-            // Draw border around card in interactive mode.
-            if (!isInAmbientMode()) {
-                mPaint.setColor(Color.MAGENTA);
-                canvas.drawRect(mCardBounds.left - BORDER_WIDTH_PX,
-                        mCardBounds.top - BORDER_WIDTH_PX,
-                        mCardBounds.right + BORDER_WIDTH_PX,
-                        mCardBounds.bottom + BORDER_WIDTH_PX, mPaint);
-            }
-
-            // Fill area under card.
-            mPaint.setColor(isInAmbientMode() ? Color.RED : Color.GREEN);
-            canvas.drawRect(mCardBounds, mPaint);
-        }
-    }
-}
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/SweepWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/SweepWatchFaceService.java
deleted file mode 100644
index a94097f..0000000
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/SweepWatchFaceService.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.android.wearable.watchface;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.support.v7.graphics.Palette;
-import android.support.wearable.watchface.CanvasWatchFaceService;
-import android.support.wearable.watchface.WatchFaceService;
-import android.support.wearable.watchface.WatchFaceStyle;
-import android.util.Log;
-import android.view.SurfaceHolder;
-
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * Sample analog watch face with a sweep second hand. In ambient mode, the second hand isn't shown.
- * On devices with low-bit ambient mode, the hands are drawn without anti-aliasing in ambient mode.
- * The watch face is drawn with less contrast in mute mode.
- *
- * {@link AnalogWatchFaceService} is similar but has a ticking second hand.
- */
-public class SweepWatchFaceService extends CanvasWatchFaceService {
-
-    private static final String TAG = "SweepWatchFaceService";
-
-    @Override
-    public Engine onCreateEngine() {
-        return new Engine();
-    }
-
-    private class Engine extends CanvasWatchFaceService.Engine {
-
-        private static final float HOUR_STROKE_WIDTH = 5f;
-        private static final float MINUTE_STROKE_WIDTH = 3f;
-        private static final float SECOND_TICK_STROKE_WIDTH = 2f;
-
-        private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 4f;
-
-        private static final int SHADOW_RADIUS = 6;
-
-        private Calendar mCalendar;
-        private boolean mRegisteredTimeZoneReceiver = false;
-        private boolean mMuteMode;
-
-        private float mCenterX;
-        private float mCenterY;
-
-        private float mSecondHandLength;
-        private float mMinuteHandLength;
-        private float mHourHandLength;
-
-        /* Colors for all hands (hour, minute, seconds, ticks) based on photo loaded. */
-        private int mWatchHandColor;
-        private int mWatchHandHighlightColor;
-        private int mWatchHandShadowColor;
-
-        private Paint mHourPaint;
-        private Paint mMinutePaint;
-        private Paint mSecondPaint;
-        private Paint mTickAndCirclePaint;
-
-        private Paint mBackgroundPaint;
-        private Bitmap mBackgroundBitmap;
-        private Bitmap mGrayBackgroundBitmap;
-
-        private boolean mAmbient;
-        private boolean mLowBitAmbient;
-        private boolean mBurnInProtection;
-
-        private Rect mPeekCardBounds = new Rect();
-
-        private final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                mCalendar.setTimeZone(TimeZone.getDefault());
-                invalidate();
-            }
-        };
-
-        @Override
-        public void onCreate(SurfaceHolder holder) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onCreate");
-            }
-            super.onCreate(holder);
-
-            setWatchFaceStyle(new WatchFaceStyle.Builder(SweepWatchFaceService.this)
-                    .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
-                    .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
-                    .setShowSystemUiTime(false)
-                    .build());
-
-            mBackgroundPaint = new Paint();
-            mBackgroundPaint.setColor(Color.BLACK);
-            mBackgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
-
-            /* Set defaults for colors */
-            mWatchHandColor = Color.WHITE;
-            mWatchHandHighlightColor = Color.RED;
-            mWatchHandShadowColor = Color.BLACK;
-
-            mHourPaint = new Paint();
-            mHourPaint.setColor(mWatchHandColor);
-            mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
-            mHourPaint.setAntiAlias(true);
-            mHourPaint.setStrokeCap(Paint.Cap.ROUND);
-            mHourPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-
-            mMinutePaint = new Paint();
-            mMinutePaint.setColor(mWatchHandColor);
-            mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
-            mMinutePaint.setAntiAlias(true);
-            mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
-            mMinutePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-
-            mSecondPaint = new Paint();
-            mSecondPaint.setColor(mWatchHandHighlightColor);
-            mSecondPaint.setStrokeWidth(SECOND_TICK_STROKE_WIDTH);
-            mSecondPaint.setAntiAlias(true);
-            mSecondPaint.setStrokeCap(Paint.Cap.ROUND);
-            mSecondPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-
-            mTickAndCirclePaint = new Paint();
-            mTickAndCirclePaint.setColor(mWatchHandColor);
-            mTickAndCirclePaint.setStrokeWidth(SECOND_TICK_STROKE_WIDTH);
-            mTickAndCirclePaint.setAntiAlias(true);
-            mTickAndCirclePaint.setStyle(Paint.Style.STROKE);
-            mTickAndCirclePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-
-            /* Extract colors from background image to improve watchface style. */
-            Palette.generateAsync(
-                    mBackgroundBitmap,
-                    new Palette.PaletteAsyncListener() {
-                        @Override
-                        public void onGenerated(Palette palette) {
-                            if (palette != null) {
-                                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                                    Log.d(TAG, "Palette: " + palette);
-                                }
-
-                                mWatchHandHighlightColor = palette.getVibrantColor(Color.RED);
-                                mWatchHandColor = palette.getLightVibrantColor(Color.WHITE);
-                                mWatchHandShadowColor = palette.getDarkMutedColor(Color.BLACK);
-                                updateWatchHandStyle();
-                            }
-                        }
-                    });
-
-            mCalendar = Calendar.getInstance();
-        }
-
-        @Override
-        public void onPropertiesChanged(Bundle properties) {
-            super.onPropertiesChanged(properties);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onPropertiesChanged: low-bit ambient = " + mLowBitAmbient);
-            }
-
-            mLowBitAmbient = properties.getBoolean(PROPERTY_LOW_BIT_AMBIENT, false);
-            mBurnInProtection = properties.getBoolean(PROPERTY_BURN_IN_PROTECTION, false);
-        }
-
-        @Override
-        public void onTimeTick() {
-            super.onTimeTick();
-            invalidate();
-        }
-
-        @Override
-        public void onAmbientModeChanged(boolean inAmbientMode) {
-            super.onAmbientModeChanged(inAmbientMode);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onAmbientModeChanged: " + inAmbientMode);
-            }
-            mAmbient = inAmbientMode;
-
-            updateWatchHandStyle();
-
-            invalidate();
-        }
-
-        private void updateWatchHandStyle(){
-            if (mAmbient){
-                mHourPaint.setColor(Color.WHITE);
-                mMinutePaint.setColor(Color.WHITE);
-                mSecondPaint.setColor(Color.WHITE);
-                mTickAndCirclePaint.setColor(Color.WHITE);
-
-                mHourPaint.setAntiAlias(false);
-                mMinutePaint.setAntiAlias(false);
-                mSecondPaint.setAntiAlias(false);
-                mTickAndCirclePaint.setAntiAlias(false);
-
-                mHourPaint.clearShadowLayer();
-                mMinutePaint.clearShadowLayer();
-                mSecondPaint.clearShadowLayer();
-                mTickAndCirclePaint.clearShadowLayer();
-
-            } else {
-                mHourPaint.setColor(mWatchHandColor);
-                mMinutePaint.setColor(mWatchHandColor);
-                mSecondPaint.setColor(mWatchHandHighlightColor);
-                mTickAndCirclePaint.setColor(mWatchHandColor);
-
-                mHourPaint.setAntiAlias(true);
-                mMinutePaint.setAntiAlias(true);
-                mSecondPaint.setAntiAlias(true);
-                mTickAndCirclePaint.setAntiAlias(true);
-
-                mHourPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-                mMinutePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-                mSecondPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-                mTickAndCirclePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
-            }
-        }
-
-        @Override
-        public void onInterruptionFilterChanged(int interruptionFilter) {
-            super.onInterruptionFilterChanged(interruptionFilter);
-            boolean inMuteMode = (interruptionFilter == WatchFaceService.INTERRUPTION_FILTER_NONE);
-
-            /* Dim display in mute mode. */
-            if (mMuteMode != inMuteMode) {
-                mMuteMode = inMuteMode;
-                mHourPaint.setAlpha(inMuteMode ? 100 : 255);
-                mMinutePaint.setAlpha(inMuteMode ? 100 : 255);
-                mSecondPaint.setAlpha(inMuteMode ? 80 : 255);
-                invalidate();
-            }
-        }
-
-        @Override
-        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-            super.onSurfaceChanged(holder, format, width, height);
-
-            /*
-             * Find the coordinates of the center point on the screen, and ignore the window
-             * insets, so that, on round watches with a "chin", the watch face is centered on the
-             * entire screen, not just the usable portion.
-             */
-            mCenterX = width / 2f;
-            mCenterY = height / 2f;
-
-            /*
-             * Calculate lengths of different hands based on watch screen size.
-             */
-            mSecondHandLength = (float) (mCenterX * 0.875);
-            mMinuteHandLength = (float) (mCenterX * 0.75);
-            mHourHandLength = (float) (mCenterX * 0.5);
-
-
-            /* Scale loaded background image (more efficient) if surface dimensions change. */
-            float scale = ((float) width) / (float) mBackgroundBitmap.getWidth();
-
-            mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap,
-                    (int) (mBackgroundBitmap.getWidth() * scale),
-                    (int) (mBackgroundBitmap.getHeight() * scale), true);
-
-            /*
-             * Create a gray version of the image only if it will look nice on the device in
-             * ambient mode. That means we don't want devices that support burn-in
-             * protection (slight movements in pixels, not great for images going all the way to
-             * edges) and low ambient mode (degrades image quality).
-             *
-             * Also, if your watch face will know about all images ahead of time (users aren't
-             * selecting their own photos for the watch face), it will be more
-             * efficient to create a black/white version (png, etc.) and load that when you need it.
-             */
-            if (!mBurnInProtection && !mLowBitAmbient) {
-                initGrayBackgroundBitmap();
-            }
-        }
-
-        private void initGrayBackgroundBitmap() {
-            mGrayBackgroundBitmap = Bitmap.createBitmap(
-                    mBackgroundBitmap.getWidth(),
-                    mBackgroundBitmap.getHeight(),
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(mGrayBackgroundBitmap);
-            Paint grayPaint = new Paint();
-            ColorMatrix colorMatrix = new ColorMatrix();
-            colorMatrix.setSaturation(0);
-            ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
-            grayPaint.setColorFilter(filter);
-            canvas.drawBitmap(mBackgroundBitmap, 0, 0, grayPaint);
-        }
-
-        @Override
-        public void onDraw(Canvas canvas, Rect bounds) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "onDraw");
-            }
-            long now = System.currentTimeMillis();
-            mCalendar.setTimeInMillis(now);
-
-            if (mAmbient && (mLowBitAmbient || mBurnInProtection)) {
-                canvas.drawColor(Color.BLACK);
-            } else if (mAmbient) {
-                canvas.drawBitmap(mGrayBackgroundBitmap, 0, 0, mBackgroundPaint);
-            } else {
-                canvas.drawBitmap(mBackgroundBitmap, 0, 0, mBackgroundPaint);
-            }
-
-            /*
-             * Draw ticks. Usually you will want to bake this directly into the photo, but in
-             * cases where you want to allow users to select their own photos, this dynamically
-             * creates them on top of the photo.
-             */
-            float innerTickRadius = mCenterX - 10;
-            float outerTickRadius = mCenterX;
-            for (int tickIndex = 0; tickIndex < 12; tickIndex++) {
-                float tickRot = (float) (tickIndex * Math.PI * 2 / 12);
-                float innerX = (float) Math.sin(tickRot) * innerTickRadius;
-                float innerY = (float) -Math.cos(tickRot) * innerTickRadius;
-                float outerX = (float) Math.sin(tickRot) * outerTickRadius;
-                float outerY = (float) -Math.cos(tickRot) * outerTickRadius;
-                canvas.drawLine(mCenterX + innerX, mCenterY + innerY,
-                        mCenterX + outerX, mCenterY + outerY, mTickAndCirclePaint);
-            }
-
-            /*
-             * These calculations reflect the rotation in degrees per unit of time, e.g.,
-             * 360 / 60 = 6 and 360 / 12 = 30.
-             */
-            final float seconds =
-                    (mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f);
-            final float secondsRotation = seconds * 6f;
-
-            final float minutesRotation = mCalendar.get(Calendar.MINUTE) * 6f;
-
-            final float hourHandOffset = mCalendar.get(Calendar.MINUTE) / 2f;
-            final float hoursRotation = (mCalendar.get(Calendar.HOUR) * 30) + hourHandOffset;
-
-            /*
-             * Save the canvas state before we can begin to rotate it.
-             */
-            canvas.save();
-
-            canvas.rotate(hoursRotation, mCenterX, mCenterY);
-            canvas.drawLine(
-                    mCenterX,
-                    mCenterY - CENTER_GAP_AND_CIRCLE_RADIUS,
-                    mCenterX,
-                    mCenterY - mHourHandLength,
-                    mHourPaint);
-
-            canvas.rotate(minutesRotation - hoursRotation, mCenterX, mCenterY);
-            canvas.drawLine(
-                    mCenterX,
-                    mCenterY - CENTER_GAP_AND_CIRCLE_RADIUS,
-                    mCenterX,
-                    mCenterY - mMinuteHandLength,
-                    mMinutePaint);
-
-            /*
-             * Ensure the "seconds" hand is drawn only when we are in interactive mode.
-             * Otherwise, we only update the watch face once a minute.
-             */
-            if (!mAmbient) {
-                canvas.rotate(secondsRotation - minutesRotation, mCenterX, mCenterY);
-                canvas.drawLine(
-                        mCenterX,
-                        mCenterY - CENTER_GAP_AND_CIRCLE_RADIUS,
-                        mCenterX,
-                        mCenterY - mSecondHandLength,
-                        mSecondPaint);
-
-            }
-            canvas.drawCircle(
-                    mCenterX,
-                    mCenterY,
-                    CENTER_GAP_AND_CIRCLE_RADIUS,
-                    mTickAndCirclePaint);
-
-            /* Restore the canvas' original orientation. */
-            canvas.restore();
-
-            /* Draw rectangle behind peek card in ambient mode to improve readability. */
-            if (mAmbient) {
-                canvas.drawRect(mPeekCardBounds, mBackgroundPaint);
-            }
-
-            /* Draw every frame as long as we're visible and in interactive mode. */
-            if ((isVisible()) && (!mAmbient)) {
-                invalidate();
-            }
-        }
-
-        @Override
-        public void onVisibilityChanged(boolean visible) {
-            super.onVisibilityChanged(visible);
-
-            if (visible) {
-                registerReceiver();
-                /* Update time zone in case it changed while we weren't visible. */
-                mCalendar.setTimeZone(TimeZone.getDefault());
-                invalidate();
-            } else {
-                unregisterReceiver();
-            }
-        }
-
-        @Override
-        public void onPeekCardPositionUpdate(Rect rect) {
-            super.onPeekCardPositionUpdate(rect);
-            mPeekCardBounds.set(rect);
-        }
-
-        private void registerReceiver() {
-            if (mRegisteredTimeZoneReceiver) {
-                return;
-            }
-            mRegisteredTimeZoneReceiver = true;
-            IntentFilter filter = new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED);
-            SweepWatchFaceService.this.registerReceiver(mTimeZoneReceiver, filter);
-        }
-
-        private void unregisterReceiver() {
-            if (!mRegisteredTimeZoneReceiver) {
-                return;
-            }
-            mRegisteredTimeZoneReceiver = false;
-            SweepWatchFaceService.this.unregisterReceiver(mTimeZoneReceiver);
-        }
-    }
-}
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleConfigActivity.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/ComplicationSimpleConfigActivity.java
similarity index 96%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleConfigActivity.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/ComplicationSimpleConfigActivity.java
index 6d4e521..c63333f 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleConfigActivity.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/ComplicationSimpleConfigActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.config;
 
 import android.app.Activity;
 import android.content.ComponentName;
@@ -33,6 +33,9 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.example.android.wearable.watchface.watchfaces.ComplicationSimpleWatchFaceService;
+import com.example.android.wearable.watchface.R;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceConfigListenerService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceConfigListenerService.java
similarity index 92%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceConfigListenerService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceConfigListenerService.java
index 8d99de6..617f3b7 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceConfigListenerService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceConfigListenerService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.config;
 
 import android.os.Bundle;
 import android.util.Log;
@@ -26,6 +26,9 @@
 import com.google.android.gms.wearable.Wearable;
 import com.google.android.gms.wearable.WearableListenerService;
 
+import com.example.android.wearable.watchface.watchfaces.DigitalWatchFaceService;
+import com.example.android.wearable.watchface.utils.DigitalWatchFaceUtil;
+
 import java.util.concurrent.TimeUnit;
 
 /**
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceWearableConfigActivity.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceWearableConfigActivity.java
similarity index 97%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceWearableConfigActivity.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceWearableConfigActivity.java
index 4b309e6..75527f3 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceWearableConfigActivity.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/config/DigitalWatchFaceWearableConfigActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.config;
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -22,13 +22,11 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.wearable.view.BoxInsetLayout;
 import android.support.wearable.view.CircledImageView;
 import android.support.wearable.view.WearableListView;
 import android.util.Log;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
@@ -40,6 +38,10 @@
 import com.google.android.gms.wearable.DataMap;
 import com.google.android.gms.wearable.Wearable;
 
+import com.example.android.wearable.watchface.watchfaces.DigitalWatchFaceService;
+import com.example.android.wearable.watchface.utils.DigitalWatchFaceUtil;
+import com.example.android.wearable.watchface.R;
+
 /**
  * The watch-side config activity for {@link DigitalWatchFaceService}, which allows for setting the
  * background color.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/RandomNumberProviderService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/RandomNumberProviderService.java
similarity index 77%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/RandomNumberProviderService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/RandomNumberProviderService.java
index 17d03c2..80f565d 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/RandomNumberProviderService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/RandomNumberProviderService.java
@@ -1,4 +1,20 @@
-package com.example.android.wearable.watchface.provider;
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.wearable.watchface.providers;
 
 import android.app.PendingIntent;
 import android.content.Intent;
@@ -28,7 +44,6 @@
     public void onComplicationActivated(
             int complicationId, int dataType, ComplicationManager complicationManager) {
         Log.d(TAG, "onComplicationActivated(): " + complicationId);
-        super.onComplicationActivated(complicationId, dataType, complicationManager);
     }
 
     /*
@@ -103,17 +118,27 @@
         }
 
         if (complicationData != null) {
+            // In this case, we have the complication id and ask the system to update only that
+            // complication.
+            //
+            // You could also call ProviderUpdateRequester.requestUpdateAll() instead, which
+            // requests that the system call onComplicationUpdate on the specified provider for ALL
+            // active complications using that provider without requiring the id (a bit easier than
+            // tracking complication id throughout app).
             complicationManager.updateComplicationData(complicationId, complicationData);
+
+        } else {
+            // If no data is sent, we still need to inform the ComplicationManager, so the update
+            // job can finish and the wake lock isn't held any longer than necessary.
+            complicationManager.noUpdateRequired(complicationId);
         }
     }
 
     /*
-     * Called when the complication has been deactivated. If you are updating the complication
-     * manager outside of this class with updates, you will want to update your class to stop.
+     * Called when the complication has been deactivated.
      */
     @Override
     public void onComplicationDeactivated(int complicationId) {
         Log.d(TAG, "onComplicationDeactivated(): " + complicationId);
-        super.onComplicationDeactivated(complicationId);
     }
 }
\ No newline at end of file
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/UpdateComplicationDataService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/UpdateComplicationDataService.java
similarity index 74%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/UpdateComplicationDataService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/UpdateComplicationDataService.java
index 203e491..ae04bf5 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/provider/UpdateComplicationDataService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/providers/UpdateComplicationDataService.java
@@ -1,4 +1,20 @@
-package com.example.android.wearable.watchface.provider;
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.wearable.watchface.providers;
 
 import android.app.IntentService;
 import android.content.ComponentName;
@@ -12,6 +28,8 @@
  */
 public class UpdateComplicationDataService extends IntentService {
 
+    // TODO (jewalker): Revise to Explicit Broadcast Receiver to handle O changes.
+
     private static final String TAG = "UpdateCompService";
 
     public static final String ACTION_UPDATE_COMPLICATION =
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceUtil.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/DigitalWatchFaceUtil.java
similarity index 97%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceUtil.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/DigitalWatchFaceUtil.java
index e13440d..42298d0 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceUtil.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/DigitalWatchFaceUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.utils;
 
 import android.graphics.Color;
 import android.net.Uri;
@@ -30,6 +30,8 @@
 import com.google.android.gms.wearable.PutDataMapRequest;
 import com.google.android.gms.wearable.Wearable;
 
+import com.example.android.wearable.watchface.watchfaces.DigitalWatchFaceService;
+
 public final class DigitalWatchFaceUtil {
     private static final String TAG = "DigitalWatchFaceUtil";
 
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/Gles2ColoredTriangleList.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/Gles2ColoredTriangleList.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/Gles2ColoredTriangleList.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/Gles2ColoredTriangleList.java
index 2441c65..cfdd3a3 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/Gles2ColoredTriangleList.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/utils/Gles2ColoredTriangleList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.utils;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/AnalogWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/AnalogWatchFaceService.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/AnalogWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/AnalogWatchFaceService.java
index 9fd73a5..1a9573e 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/AnalogWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/AnalogWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -38,6 +38,8 @@
 import android.util.Log;
 import android.view.SurfaceHolder;
 
+import com.example.android.wearable.watchface.R;
+
 import java.util.Calendar;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -46,8 +48,6 @@
  * Sample analog watch face with a ticking second hand. In ambient mode, the second hand isn't
  * shown. On devices with low-bit ambient mode, the hands are drawn without anti-aliasing in ambient
  * mode. The watch face is drawn with less contrast in mute mode.
- *
- * {@link SweepWatchFaceService} is similar but has a sweep second hand.
  */
 public class AnalogWatchFaceService extends CanvasWatchFaceService {
     private static final String TAG = "AnalogWatchFaceService";
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/ComplicationSimpleWatchFaceService.java
similarity index 74%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/ComplicationSimpleWatchFaceService.java
index 4905293..f0a5309 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/ComplicationSimpleWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/ComplicationSimpleWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -38,14 +38,19 @@
 import android.support.wearable.complications.ComplicationData;
 import android.support.wearable.complications.ComplicationHelperActivity;
 import android.support.wearable.complications.ComplicationText;
+import android.support.wearable.complications.SystemProviders;
+import android.support.wearable.complications.rendering.TextRenderer;
 import android.support.wearable.watchface.CanvasWatchFaceService;
 import android.support.wearable.watchface.WatchFaceService;
 import android.support.wearable.watchface.WatchFaceStyle;
-import android.text.TextUtils;
+import android.text.TextPaint;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.Gravity;
 import android.view.SurfaceHolder;
 
+import com.example.android.wearable.watchface.R;
+
 import java.util.Calendar;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -83,8 +88,8 @@
     private class Engine extends CanvasWatchFaceService.Engine {
         private static final int MSG_UPDATE_TIME = 0;
 
-        private static final float COMPLICATION_TEXT_SIZE = 38f;
-        private static final int COMPLICATION_TAP_BUFFER = 40;
+        private static final float COMPLICATION_MAIN_TEXT_SIZE = 38f;
+        private static final float COMPLICATION_SUB_TEXT_SIZE = 34f;
 
         private static final float HOUR_STROKE_WIDTH = 5f;
         private static final float MINUTE_STROKE_WIDTH = 3f;
@@ -121,15 +126,21 @@
         private Bitmap mBackgroundBitmap;
         private Bitmap mGrayBackgroundBitmap;
 
-        // Variables for painting Complications
-        private Paint mComplicationPaint;
+        // Renders text for complications in specified bounds (shrinks text in some cases).
+        private TextRenderer mLeftMainTextComplicationRenderer;
+        private TextRenderer mLeftSubTextComplicationRenderer;
+        private TextRenderer mRightMainTextComplicationRenderer;
+        private TextRenderer mRightSubTextComplicationRenderer;
 
-        /* To properly place each complication, we need their x and y coordinates. While the width
-         * may change from moment to moment based on the time, the height will not change, so we
-         * store it as a local variable and only calculate it only when the surface changes
-         * (onSurfaceChanged()).
-         */
-        private int mComplicationsY;
+        // Holds Paint style for all complications.
+        private TextPaint mComplicationMainTextPaint;
+        private TextPaint mComplicationSubTextPaint;
+
+        // Bounds for the upper (main text) and lower (subtext) areas of the complications.
+        private Rect mLeftComplicationMainTextBounds;
+        private Rect mLeftComplicationSubTextBounds;
+        private Rect mRightComplicationMainTextBounds;
+        private Rect mRightComplicationSubTextBounds;
 
         /* Maps active complication ids to the data for that complication. Note: Data will only be
          * present if the user has chosen a provider via the settings activity for the watch face.
@@ -140,8 +151,6 @@
         private boolean mLowBitAmbient;
         private boolean mBurnInProtection;
 
-        private Rect mPeekCardBounds = new Rect();
-
         private final BroadcastReceiver mTimeZoneReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -178,18 +187,35 @@
 
             mCalendar = Calendar.getInstance();
 
-            setWatchFaceStyle(new WatchFaceStyle.Builder(ComplicationSimpleWatchFaceService.this)
-                    .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
-                    .setAcceptsTapEvents(true)
-                    .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
-                    .setShowSystemUiTime(false)
-                    .build());
-
+            initializeComplicationDefaults();
             initializeBackground();
             initializeComplication();
             initializeWatchFace();
         }
 
+        /*
+        * Sets a system provider as the default provider for the specified watch face
+        * complication id.
+        *
+        * To set a non-system provider as a default, or to clear a default,
+        * use setDefaultComplicationProvider(int, ComponentName, int).
+        *
+        * Important Note: Call these methods before initializing your watch face with
+        * setWatchFaceStyle(). In this example, we call setWatchFaceStyle() in the
+        * initializeWatchFace() method called after this method in onCreate().
+        */
+        private void initializeComplicationDefaults() {
+            setDefaultSystemComplicationProvider(
+                    RIGHT_DIAL_COMPLICATION,
+                    SystemProviders.DATE,
+                    ComplicationData.TYPE_SHORT_TEXT);
+
+            setDefaultSystemComplicationProvider(
+                    LEFT_DIAL_COMPLICATION,
+                    SystemProviders.WATCH_BATTERY,
+                    ComplicationData.TYPE_SHORT_TEXT);
+        }
+
         private void initializeBackground() {
             mBackgroundPaint = new Paint();
             mBackgroundPaint.setColor(Color.BLACK);
@@ -202,11 +228,38 @@
             }
             mActiveComplicationDataSparseArray = new SparseArray<>(COMPLICATION_IDS.length);
 
-            mComplicationPaint = new Paint();
-            mComplicationPaint.setColor(Color.WHITE);
-            mComplicationPaint.setTextSize(COMPLICATION_TEXT_SIZE);
-            mComplicationPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
-            mComplicationPaint.setAntiAlias(true);
+            // Both TextPaint objects are used for all complications.
+            mComplicationMainTextPaint = new TextPaint();
+            mComplicationMainTextPaint.setColor(Color.WHITE);
+            mComplicationMainTextPaint.setTextSize(COMPLICATION_MAIN_TEXT_SIZE);
+            mComplicationMainTextPaint.setTypeface(
+                    Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
+            mComplicationMainTextPaint.setAntiAlias(true);
+
+            mComplicationSubTextPaint = new TextPaint();
+            mComplicationSubTextPaint.setColor(Color.WHITE);
+            mComplicationSubTextPaint.setTextSize(COMPLICATION_SUB_TEXT_SIZE);
+            mComplicationSubTextPaint.setTypeface(
+                    Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
+            mComplicationSubTextPaint.setAntiAlias(true);
+
+            // By default, all text is aligned to the center. If you want to change the text
+            // alignment, use setAlignment() on your TextRenderer instance.
+            mLeftMainTextComplicationRenderer = new TextRenderer();
+            mLeftMainTextComplicationRenderer.setGravity(Gravity.BOTTOM);
+            mLeftMainTextComplicationRenderer.setPaint(mComplicationMainTextPaint);
+
+            mLeftSubTextComplicationRenderer = new TextRenderer();
+            mLeftSubTextComplicationRenderer.setGravity(Gravity.TOP);
+            mLeftSubTextComplicationRenderer.setPaint(mComplicationSubTextPaint);
+
+            mRightMainTextComplicationRenderer = new TextRenderer();
+            mRightMainTextComplicationRenderer.setGravity(Gravity.BOTTOM);
+            mRightMainTextComplicationRenderer.setPaint(mComplicationMainTextPaint);
+
+            mRightSubTextComplicationRenderer = new TextRenderer();
+            mRightSubTextComplicationRenderer.setGravity(Gravity.TOP);
+            mRightSubTextComplicationRenderer.setPaint(mComplicationSubTextPaint);
 
             setActiveComplications(COMPLICATION_IDS);
         }
@@ -261,6 +314,10 @@
                             }
                         }
                     });
+
+            setWatchFaceStyle(new WatchFaceStyle.Builder(ComplicationSimpleWatchFaceService.this)
+                    .setAcceptsTapEvents(true)
+                    .build());
         }
 
         @Override
@@ -321,34 +378,13 @@
                         && (complicationData.getType() != ComplicationData.TYPE_NOT_CONFIGURED)
                         && (complicationData.getType() != ComplicationData.TYPE_EMPTY)) {
 
-                    Rect complicationBoundingRect = new Rect(0, 0, 0, 0);
+                    if (mLeftComplicationMainTextBounds.contains(x, y)
+                            || mLeftComplicationSubTextBounds.contains(x, y)) {
+                        return LEFT_DIAL_COMPLICATION;
+                    } else if (mRightComplicationMainTextBounds.contains(x, y)
+                            || mRightComplicationSubTextBounds.contains(x, y)) {
+                        return RIGHT_DIAL_COMPLICATION;
 
-                    switch (COMPLICATION_IDS[i]) {
-                        case LEFT_DIAL_COMPLICATION:
-                            complicationBoundingRect.set(
-                                    0,                                          // left
-                                    mComplicationsY - COMPLICATION_TAP_BUFFER,  // top
-                                    (mWidth / 2),                               // right
-                                    ((int) COMPLICATION_TEXT_SIZE               // bottom
-                                            + mComplicationsY
-                                            + COMPLICATION_TAP_BUFFER));
-                            break;
-
-                        case RIGHT_DIAL_COMPLICATION:
-                            complicationBoundingRect.set(
-                                    (mWidth / 2),                               // left
-                                    mComplicationsY - COMPLICATION_TAP_BUFFER,  // top
-                                    mWidth,                                     // right
-                                    ((int) COMPLICATION_TEXT_SIZE               // bottom
-                                            + mComplicationsY
-                                            + COMPLICATION_TAP_BUFFER));
-                            break;
-                    }
-
-                    if (complicationBoundingRect.width() > 0) {
-                        if (complicationBoundingRect.contains(x, y)) {
-                            return COMPLICATION_IDS[i];
-                        }
                     } else {
                         Log.e(TAG, "Not a recognized complication id.");
                     }
@@ -416,7 +452,17 @@
             updateWatchHandStyle();
 
             // Updates complication style
-            mComplicationPaint.setAntiAlias(!inAmbientMode);
+            mComplicationMainTextPaint.setAntiAlias(!inAmbientMode);
+            mComplicationSubTextPaint.setAntiAlias(!inAmbientMode);
+
+            // If the properties of the TextPaint have changed, then the TextRenderer may not be
+            // aware that the layout needs to be updated. In this case, a layout update should be
+            // forced by calling requestUpdateLayout().
+            mLeftMainTextComplicationRenderer.requestUpdateLayout();
+            mLeftSubTextComplicationRenderer.requestUpdateLayout();
+
+            mRightMainTextComplicationRenderer.requestUpdateLayout();
+            mRightSubTextComplicationRenderer.requestUpdateLayout();
 
             // Check and trigger whether or not timer should be running (only in active mode).
             updateTimer();
@@ -488,11 +534,28 @@
             mCenterX = mWidth / 2f;
             mCenterY = mHeight / 2f;
 
-            /*
-             * Since the height of the complications text does not change, we only have to
-             * recalculate when the surface changes.
-             */
-            mComplicationsY = (int) ((mHeight / 2) + (mComplicationPaint.getTextSize() / 2));
+            // Calculates Left and Right complications' bounds for TextRenderer.
+            int top, left, bottom, right = 0;
+            int heightOfComplication = height / 6;
+
+            left = 0;
+            top = (height / 2) - heightOfComplication;
+            right = width / 2;
+            bottom = height / 2;
+            mLeftComplicationMainTextBounds = new Rect(left, top, right, bottom);
+
+            left = right;
+            right = width;
+            mRightComplicationMainTextBounds = new Rect(left, top, right, bottom);
+
+            top = height / 2;
+            bottom = top + heightOfComplication;
+            mRightComplicationSubTextBounds = new Rect(left, top, right, bottom);
+
+            right = left;
+            left = 0;
+            mLeftComplicationSubTextBounds = new Rect(left, top, right, bottom);
+
 
             /*
              * Calculate lengths of different hands based on watch screen size.
@@ -580,47 +643,52 @@
                     if (complicationData.getType() == ComplicationData.TYPE_SHORT_TEXT
                             || complicationData.getType() == ComplicationData.TYPE_NO_PERMISSION) {
 
-                        ComplicationText mainText = complicationData.getShortText();
-                        ComplicationText subText = complicationData.getShortTitle();
-
-                        CharSequence complicationMessage =
-                                mainText.getText(getApplicationContext(), currentTimeMillis);
-
-                        /* In most cases you would want the subText (Title) under the
-                         * mainText (Text), but to keep it simple for the code lab, we are
-                         * concatenating them all on one line.
-                         */
-                        if (subText != null) {
-                            complicationMessage = TextUtils.concat(
-                                    complicationMessage,
-                                    " ",
-                                    subText.getText(getApplicationContext(), currentTimeMillis));
-                        }
-
-                        //Log.d(TAG, "Com id: " + COMPLICATION_IDS[i] + "\t" + complicationMessage);
-                        double textWidth =
-                                mComplicationPaint.measureText(
-                                        complicationMessage,
-                                        0,
-                                        complicationMessage.length());
-
-                        int complicationsX;
-
                         if (COMPLICATION_IDS[i] == LEFT_DIAL_COMPLICATION) {
-                            complicationsX = (int) ((mWidth / 2) - textWidth) / 2;
-                        } else {
-                            // RIGHT_DIAL_COMPLICATION calculations
-                            int offset = (int) ((mWidth / 2) - textWidth) / 2;
-                            complicationsX = (mWidth / 2) + offset;
-                        }
+                            // Set the text every time you draw, even if the ComplicationData has
+                            // not changed, in case the text includes a time-dependent value.
+                            mLeftMainTextComplicationRenderer.setText(
+                                    ComplicationText.getText(
+                                            getApplicationContext(),
+                                            complicationData.getShortTitle(),
+                                            currentTimeMillis));
 
-                        canvas.drawText(
-                                complicationMessage,
-                                0,
-                                complicationMessage.length(),
-                                complicationsX,
-                                mComplicationsY,
-                                mComplicationPaint);
+                            mLeftSubTextComplicationRenderer.setText(
+                                    ComplicationText.getText(
+                                            getApplicationContext(),
+                                            complicationData.getShortText(),
+                                            currentTimeMillis));
+
+                            // Assuming both the title and text exist.
+                            mLeftMainTextComplicationRenderer.draw(
+                                    canvas,
+                                    mLeftComplicationMainTextBounds);
+                            mLeftSubTextComplicationRenderer.draw(
+                                    canvas,
+                                    mLeftComplicationSubTextBounds);
+
+                        } else if (COMPLICATION_IDS[i] == RIGHT_DIAL_COMPLICATION) {
+                            // Set the text every time you draw, even if the ComplicationData has
+                            // not changed, in case the text includes a time-dependent value.
+                            mRightMainTextComplicationRenderer.setText(
+                                    ComplicationText.getText(
+                                            getApplicationContext(),
+                                            complicationData.getShortTitle(),
+                                            currentTimeMillis));
+
+                            mRightSubTextComplicationRenderer.setText(
+                                    ComplicationText.getText(
+                                            getApplicationContext(),
+                                            complicationData.getShortText(),
+                                            currentTimeMillis));
+
+                            // Assuming both the title and text exist.
+                            mRightMainTextComplicationRenderer.draw(
+                                    canvas,
+                                    mRightComplicationMainTextBounds);
+                            mRightSubTextComplicationRenderer.draw(
+                                    canvas,
+                                    mRightComplicationSubTextBounds);
+                        }
                     }
                 }
             }
@@ -700,11 +768,6 @@
 
             /* Restore the canvas' original orientation. */
             canvas.restore();
-
-            /* Draw rectangle behind peek card in ambient mode to improve readability. */
-            if (mAmbient) {
-                canvas.drawRect(mPeekCardBounds, mBackgroundPaint);
-            }
         }
 
         @Override
@@ -724,12 +787,6 @@
             updateTimer();
         }
 
-        @Override
-        public void onPeekCardPositionUpdate(Rect rect) {
-            super.onPeekCardPositionUpdate(rect);
-            mPeekCardBounds.set(rect);
-        }
-
         private void registerReceiver() {
             if (mRegisteredTimeZoneReceiver) {
                 return;
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/watchfaces/DigitalWatchFaceService.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/DigitalWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/DigitalWatchFaceService.java
index f3f97fb..5b6396e 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/watchfaces/DigitalWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -47,6 +47,9 @@
 import com.google.android.gms.wearable.DataMapItem;
 import com.google.android.gms.wearable.Wearable;
 
+import com.example.android.wearable.watchface.utils.DigitalWatchFaceUtil;
+import com.example.android.wearable.watchface.R;
+
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitDistanceWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitDistanceWatchFaceService.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitDistanceWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitDistanceWatchFaceService.java
index 6dee04e..892af39 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitDistanceWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitDistanceWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -50,6 +50,8 @@
 import com.google.android.gms.fitness.data.Field;
 import com.google.android.gms.fitness.result.DailyTotalResult;
 
+import com.example.android.wearable.watchface.R;
+
 import java.util.Calendar;
 import java.util.List;
 import java.util.TimeZone;
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitStepsWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitStepsWatchFaceService.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitStepsWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitStepsWatchFaceService.java
index 1f7b298..22ea3b0 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/FitStepsWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/FitStepsWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import com.google.android.gms.common.ConnectionResult;
 import com.google.android.gms.common.api.GoogleApiClient;
@@ -48,6 +48,8 @@
 import android.view.SurfaceHolder;
 import android.view.WindowInsets;
 
+import com.example.android.wearable.watchface.R;
+
 import java.util.Calendar;
 import java.util.List;
 import java.util.TimeZone;
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/InteractiveWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/InteractiveWatchFaceService.java
similarity index 97%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/InteractiveWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/InteractiveWatchFaceService.java
index 7a50208..08cb8be 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/InteractiveWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/InteractiveWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -29,6 +29,8 @@
 import android.view.SurfaceHolder;
 import android.view.WindowInsets;
 
+import com.example.android.wearable.watchface.R;
+
 /**
  * Demonstrates interactive watch face capabilities, i.e., touching the display and registering
  * three different events: touch, touch-cancel and tap. The watch face UI will show the count of
diff --git a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/OpenGLWatchFaceService.java b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/OpenGLWatchFaceService.java
similarity index 98%
rename from wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/OpenGLWatchFaceService.java
rename to wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/OpenGLWatchFaceService.java
index 01adcdb..11e3ebf 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/OpenGLWatchFaceService.java
+++ b/wearable/wear/WatchFace/Wearable/src/main/java/com/example/android/wearable/watchface/watchfaces/OpenGLWatchFaceService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.example.android.wearable.watchface;
+package com.example.android.wearable.watchface.watchfaces;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -28,6 +28,8 @@
 import android.view.Gravity;
 import android.view.SurfaceHolder;
 
+import com.example.android.wearable.watchface.utils.Gles2ColoredTriangleList;
+
 import java.util.Calendar;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_calendar_watch_face_permission.xml b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_calendar_watch_face_permission.xml
deleted file mode 100644
index bf0e3f6..0000000
--- a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_calendar_watch_face_permission.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.wearable.view.BoxInsetLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:id="@+id/container"
-    android:background="@color/white"
-    android:paddingTop="32dp"
-    android:paddingLeft="36dp"
-    android:paddingRight="22dp"
-    tools:context="com.example.android.wearable.watchface.CalendarWatchFacePermissionActivity"
-    tools:deviceIds="wear">
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:onClick="onClickEnablePermission"
-        android:orientation="vertical"
-        app:layout_box="all">
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textSize="16sp"
-            android:paddingBottom="18dp"
-            android:textColor="#000000"
-            android:text="@string/calendar_permission_text"/>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <android.support.wearable.view.CircledImageView
-                android:id="@+id/circle"
-                android:layout_width="40dp"
-                android:layout_height="40dp"
-                app:circle_radius="20dp"
-                app:circle_color="#0086D4"
-                android:src="@drawable/ic_lock_open_white_24dp"/>
-
-            <android.support.v4.widget.Space
-                android:layout_width="8dp"
-                android:layout_height="8dp"/>
-
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="16sp"
-                android:textColor="#0086D4"
-                android:text="Enable Permission"/>
-
-
-        </LinearLayout>
-
-    </LinearLayout>
-</android.support.wearable.view.BoxInsetLayout>
\ No newline at end of file
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_config.xml b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_config.xml
index 01f5cac..d32ea10 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_config.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_config.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2016 The Android Open Source Project
+  ~ Copyright (C) 2017 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.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_list_item.xml b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_list_item.xml
index e995271..6eabc7f 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_list_item.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_complication_simple_list_item.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2016 The Android Open Source Project
+  ~ Copyright (C) 2017 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.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_digital_config.xml b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_digital_config.xml
index a368390..1672404 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_digital_config.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/layout/activity_digital_config.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/layout/color_picker_item.xml b/wearable/wear/WatchFace/Wearable/src/main/res/layout/color_picker_item.xml
index 9b07e2a..0ec5844 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/layout/color_picker_item.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/layout/color_picker_item.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/values/arrays.xml b/wearable/wear/WatchFace/Wearable/src/main/res/values/arrays.xml
index a2e37ac..f1cc40d 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/arrays.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/arrays.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2017 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.
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 1370192..8dd0d78 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/color.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
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 0b0672b..d3fc3ef 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/dimens.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/values/strings.xml b/wearable/wear/WatchFace/Wearable/src/main/res/values/strings.xml
index e4b2717..6c1a3e1 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/values/strings.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/values/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.
@@ -18,10 +18,9 @@
     <string name="opengl_name">Sample OpenGL</string>
     <string name="interactive_name">Sample Interactive</string>
     <string name="analog_name">Sample Analog</string>
-    <string name="complication_simple">Sample Complication Simple</string>
-    <string name="sweep_name">Sample Sweep</string>
-    <string name="card_bounds_name">Sample Card Bounds</string>
+    <string name="complication_simple">Sample Complication</string>
     <string name="digital_name">Sample Digital</string>
+
     <string name="digital_background_color">Background color</string>
     <string name="digital_config_name">Digital watch face configuration</string>
     <string name="digital_am">AM</string>
@@ -34,15 +33,6 @@
     <string name="fit_steps">%1$d steps</string>
     <string name="fit_distance">%1$,.2f meters</string>
 
-    <string name="calendar_name">Sample Calendar</string>
-    <string name="calendar_permission_not_approved">&lt;br&gt;&lt;br&gt;&lt;br&gt;WatchFace requires Calendar permission. Click on this WatchFace or visit Settings &gt; Permissions to approve.</string>
-    <plurals name="calendar_meetings">
-        <item quantity="one">&lt;br&gt;&lt;br&gt;&lt;br&gt;You have &lt;b&gt;%1$d&lt;/b&gt; meeting in the next 24 hours.</item>
-        <item quantity="other">&lt;br&gt;&lt;br&gt;&lt;br&gt;You have &lt;b&gt;%1$d&lt;/b&gt; meetings in the next 24 hours.</item>
-    </plurals>
-    <string name="title_activity_calendar_watch_face_permission">Calendar Permission Activity</string>
-    <string name="calendar_permission_text">WatchFace requires Calendar access.</string>
-
     <string name="complication_simple_config_name">Configuration</string>
     <string name="complications_provider_random_number">Random Number</string>
 
diff --git a/wearable/wear/WatchFace/Wearable/src/main/res/xml/watch_face.xml b/wearable/wear/WatchFace/Wearable/src/main/res/xml/watch_face.xml
index aa2e343..4c46d8f 100644
--- a/wearable/wear/WatchFace/Wearable/src/main/res/xml/watch_face.xml
+++ b/wearable/wear/WatchFace/Wearable/src/main/res/xml/watch_face.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2017 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.