Merge "City search keyboard now starts in uppercase" into ub-deskclock-fantasy
diff --git a/res/layout-land/clock_fragment.xml b/res/layout-land/clock_fragment.xml
index 05d79ec..78afea0 100644
--- a/res/layout-land/clock_fragment.xml
+++ b/res/layout-land/clock_fragment.xml
@@ -50,7 +50,7 @@
         android:layout_weight="32"
         android:clickable="false"
         android:clipToPadding="false"
-        android:paddingBottom="@dimen/medium_space_top" />
+        android:paddingBottom="@dimen/fab_height" />
 
     <!-- Left gutter. -->
     <Space
diff --git a/res/layout-land/stopwatch_fragment.xml b/res/layout-land/stopwatch_fragment.xml
index ca87895..cf9754a 100644
--- a/res/layout-land/stopwatch_fragment.xml
+++ b/res/layout-land/stopwatch_fragment.xml
@@ -34,6 +34,7 @@
         android:layout_weight="@integer/guttered_content_width_percent"
         android:orientation="horizontal">
 
+        <!-- No circle in the stopwatch_view implies it should consume all remaining width. -->
         <FrameLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
diff --git a/res/layout-sw320dp-land/stopwatch_fragment.xml b/res/layout-sw320dp-land/stopwatch_fragment.xml
new file mode 100644
index 0000000..a1657af
--- /dev/null
+++ b/res/layout-sw320dp-land/stopwatch_fragment.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:baselineAligned="false"
+    android:orientation="horizontal">
+
+    <!-- Left gutter. -->
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/gutter_width_percent" />
+
+    <!-- Guttered content. -->
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/guttered_content_width_percent"
+        android:orientation="horizontal">
+
+        <!-- A circle in the stopwatch_view implies it should be sized in the remaining area. -->
+        <android.support.percent.PercentFrameLayout
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:paddingBottom="@dimen/fab_height">
+
+            <com.android.deskclock.TimerCircleFrameLayout
+                app:layout_aspectRatio="100%"
+                app:layout_widthPercent="@fraction/timer_circle_width_percent"
+                app:layout_heightPercent="@fraction/timer_circle_height_percent"
+                android:layout_gravity="center">
+
+                <include layout="@layout/stopwatch_view" />
+
+            </com.android.deskclock.TimerCircleFrameLayout>
+
+        </android.support.percent.PercentFrameLayout>
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/laps_list"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:clipToPadding="false"
+            android:paddingBottom="@dimen/fab_height" />
+
+    </LinearLayout>
+
+    <!-- Right gutter. -->
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/gutter_width_percent" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-sw320dp/timer_item.xml b/res/layout-sw320dp/timer_item.xml
new file mode 100644
index 0000000..bb35498
--- /dev/null
+++ b/res/layout-sw320dp/timer_item.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<!-- This TimerItem includes the circle because ample space exists. -->
+<com.android.deskclock.timer.TimerItem
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <android.support.percent.PercentFrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:layout_gravity="center">
+
+        <com.android.deskclock.TimerCircleFrameLayout
+            app:layout_aspectRatio="100%"
+            app:layout_widthPercent="@fraction/timer_circle_width_percent"
+            app:layout_heightPercent="@fraction/timer_circle_height_percent"
+            android:layout_gravity="center">
+
+            <com.android.deskclock.CircleButtonsLayout
+                android:id="@+id/timer_circle"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <com.android.deskclock.timer.TimerCircleView
+                    android:id="@+id/timer_time"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+
+                <com.android.deskclock.timer.CountingTimerView
+                    android:id="@+id/timer_time_text"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+
+                <Button
+                    android:id="@+id/timer_label"
+                    style="?android:attr/borderlessButtonStyle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="40dp"
+                    android:layout_gravity="top|center_horizontal"
+                    android:clickable="false"
+                    android:ellipsize="end"
+                    android:gravity="center"
+                    android:hint="@string/label"
+                    android:maxLines="1"
+                    android:src="@drawable/ic_label"
+                    android:textAppearance="@style/SecondaryLabelTextAppearance" />
+
+                <ImageButton
+                    android:id="@+id/reset_add"
+                    android:layout_width="@dimen/fab_button_size"
+                    android:layout_height="@dimen/fab_button_size"
+                    android:layout_gravity="bottom|center_horizontal"
+                    android:contentDescription="@string/timer_plus_one"
+                    android:gravity="center"
+                    android:scaleType="center"
+                    android:src="@drawable/ic_plusone" />
+
+            </com.android.deskclock.CircleButtonsLayout>
+
+        </com.android.deskclock.TimerCircleFrameLayout>
+
+    </android.support.percent.PercentFrameLayout>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/fab_height" />
+
+</com.android.deskclock.timer.TimerItem>
\ No newline at end of file
diff --git a/res/layout/expired_timers_activity.xml b/res/layout/expired_timers_activity.xml
index 0bd487e..34ef57e 100644
--- a/res/layout/expired_timers_activity.xml
+++ b/res/layout/expired_timers_activity.xml
@@ -33,8 +33,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:clipToPadding="false"
-            android:orientation="vertical"
-            android:paddingTop="?attr/actionBarSize" />
+            android:orientation="vertical" />
+
     </ScrollView>
 
     <android.support.design.widget.FloatingActionButton
@@ -47,4 +47,5 @@
         android:src="@drawable/ic_stop_white_24dp"
         app:borderWidth="0dp"
         app:elevation="@dimen/fab_elevation" />
+
 </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/stopwatch_fragment.xml b/res/layout/stopwatch_fragment.xml
index 0be82f1..59c0b52 100644
--- a/res/layout/stopwatch_fragment.xml
+++ b/res/layout/stopwatch_fragment.xml
@@ -28,14 +28,15 @@
         android:layout_height="wrap_content"
         android:layout_gravity="center">
 
-        <FrameLayout
-            android:layout_gravity="center"
+        <com.android.deskclock.TimerCircleFrameLayout
             app:layout_aspectRatio="100%"
-            app:layout_widthPercent="60%">
+            app:layout_widthPercent="@fraction/timer_circle_width_percent"
+            app:layout_heightPercent="@fraction/timer_circle_height_percent"
+            android:layout_gravity="center">
 
             <include layout="@layout/stopwatch_view" />
 
-        </FrameLayout>
+        </com.android.deskclock.TimerCircleFrameLayout>
 
     </android.support.percent.PercentFrameLayout>
 
diff --git a/res/layout/timer_fragment.xml b/res/layout/timer_fragment.xml
index a297dc5..a34d956 100644
--- a/res/layout/timer_fragment.xml
+++ b/res/layout/timer_fragment.xml
@@ -25,42 +25,49 @@
         android:layout_height="match_parent">
 
         <LinearLayout
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_gravity="end|center_vertical"
-            android:layout_marginEnd="24dp"
-            android:gravity="center"
-            android:orientation="vertical">
+            android:layout_marginBottom="@dimen/fab_height"
+            android:orientation="horizontal">
 
-            <ImageView
-                android:id="@+id/page_indicator0"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:contentDescription="@null" />
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="96"
+                android:gravity="center_vertical|end"
+                android:orientation="vertical">
 
-            <ImageView
-                android:id="@+id/page_indicator1"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:contentDescription="@null" />
+                <ImageView
+                    android:id="@+id/page_indicator0"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@null" />
 
-            <ImageView
-                android:id="@+id/page_indicator2"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:contentDescription="@null" />
+                <ImageView
+                    android:id="@+id/page_indicator1"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@null" />
 
-            <ImageView
-                android:id="@+id/page_indicator3"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:contentDescription="@null" />
+                <ImageView
+                    android:id="@+id/page_indicator2"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@null" />
 
+                <ImageView
+                    android:id="@+id/page_indicator3"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@null" />
+
+            </LinearLayout>
+
+            <!-- Right gutter. -->
             <Space
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/footer_button_size"
-                android:layout_marginBottom="16dp"
-                android:layout_marginTop="16dp" />
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="@integer/gutter_width_percent" />
 
         </LinearLayout>
 
diff --git a/res/layout/timer_item.xml b/res/layout/timer_item.xml
index 6c0a277..6440f18 100644
--- a/res/layout/timer_item.xml
+++ b/res/layout/timer_item.xml
@@ -14,37 +14,28 @@
      limitations under the License.
 -->
 
+<!-- This TimerItem discards the circle because space is limited. -->
 <com.android.deskclock.timer.TimerItem
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:gravity="center_vertical"
-    android:orientation="vertical"
-    android:paddingBottom="@dimen/timer_list_padding_bottom">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <com.android.deskclock.CircleButtonsLayout
-        android:id="@+id/timer_circle"
-        android:layout_width="@dimen/circle_size"
-        android:layout_height="@dimen/circle_size"
-        android:layout_gravity="center"
-        android:padding="@dimen/timer_padding">
-
-        <com.android.deskclock.timer.TimerCircleView
-            android:id="@+id/timer_time"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
 
         <com.android.deskclock.timer.CountingTimerView
             android:id="@+id/timer_time_text"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"/>
+            android:layout_height="match_parent" />
 
         <Button
             android:id="@+id/timer_label"
             style="?android:attr/borderlessButtonStyle"
             android:layout_width="wrap_content"
-            android:layout_height="56dp"
+            android:layout_height="40dp"
             android:layout_gravity="top|center_horizontal"
             android:clickable="false"
             android:ellipsize="end"
@@ -52,18 +43,22 @@
             android:hint="@string/label"
             android:maxLines="1"
             android:src="@drawable/ic_label"
-            android:textAppearance="@style/SecondaryLabelTextAppearance"/>
+            android:textAppearance="@style/SecondaryLabelTextAppearance" />
 
         <ImageButton
             android:id="@+id/reset_add"
-            android:layout_width="50dp"
-            android:layout_height="50dp"
+            android:layout_width="@dimen/fab_button_size"
+            android:layout_height="@dimen/fab_button_size"
             android:layout_gravity="bottom|center_horizontal"
             android:contentDescription="@string/timer_plus_one"
             android:gravity="center"
             android:scaleType="center"
-            android:src="@drawable/ic_plusone"/>
+            android:src="@drawable/ic_plusone" />
 
-    </com.android.deskclock.CircleButtonsLayout>
+    </FrameLayout>
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/fab_height" />
 
 </com.android.deskclock.timer.TimerItem>
\ No newline at end of file
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index bbec0e7..2533246 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -22,27 +22,18 @@
     <dimen name="date_text_size">15sp</dimen>
     <dimen name="next_alarm_text_size">15sp</dimen>
     <dimen name="time_margin_top">24dip</dimen>
-    <dimen name="timer_list_padding_bottom">80dip</dimen>
 
     <dimen name="dialpad_font_size">24sp</dimen>
     <dimen name="dialpad_digit_padding">14dip</dimen>
     <dimen name="timer_setup_delete_margin">12sp</dimen>
-    <dimen name="timer_setup_label_size">16sp</dimen>
 
     <dimen name="actionbar_tab_padding">32dip</dimen>
 
     <!-- Size of margin for circles. -->
-    <dimen name="circle_margin">8dp</dimen>
     <dimen name="analog_clock_margin">70dp</dimen>
-    <dimen name="main_clock_padding">0dp</dimen>
     <dimen name="circle_margin_top">0dp</dimen>
-    <dimen name="top_text_spacing_digital">-25dp</dimen>
     <dimen name="bottom_text_spacing_analog">5dp</dimen>
 
     <dimen name="medium_font_size">48sp</dimen>
 
-    <dimen name="circle_size">190dip</dimen>
-
-    <dimen name="alarm_alert_clock_padding_left">32dp</dimen>
-
 </resources>
\ No newline at end of file
diff --git a/res/layout/blank_footer_view.xml b/res/values-land/fractions.xml
similarity index 60%
copy from res/layout/blank_footer_view.xml
copy to res/values-land/fractions.xml
index c9460fc..4642e0e 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values-land/fractions.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2016 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,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:background="@color/transparent"
-    android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+    <!-- In landscape, -100% width implies only height is used to size the timer container. -->
+    <fraction name="timer_circle_width_percent">-100%</fraction>
+
+    <!-- In landscape, timer circles are 90% of the container height; width matches height. -->
+    <fraction name="timer_circle_height_percent">90%</fraction>
+</resources>
\ No newline at end of file
diff --git a/res/layout/blank_footer_view.xml b/res/values-sw320dp/dimens.xml
similarity index 69%
rename from res/layout/blank_footer_view.xml
rename to res/values-sw320dp/dimens.xml
index c9460fc..d64c205 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values-sw320dp/dimens.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2016 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.
 -->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:background="@color/transparent"
-    android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+    <dimen name="big_font_size">60sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-sw360dp-land/dimens.xml b/res/values-sw360dp-land/dimens.xml
index 0275592..1ff913a 100644
--- a/res/values-sw360dp-land/dimens.xml
+++ b/res/values-sw360dp-land/dimens.xml
@@ -20,6 +20,5 @@
   for different hardware and product builds.
 -->
 <resources>
-  <dimen name="circle_size">232dip</dimen>
   <dimen name="timer_setup_font_size">48sp</dimen>
 </resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 06650e6..1c26c0f 100644
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -28,15 +28,11 @@
     <dimen name="timer_setup_font_size">78sp</dimen>
     <dimen name="timer_setup_button_size">36sp</dimen>
     <dimen name="timer_setup_delete_margin">19sp</dimen>
-    <dimen name="timer_setup_label_size">24sp</dimen>
 
     <!-- Size of margin for circles. -->
     <dimen name="circle_margin_top">0dp</dimen>
-    <dimen name="circle_margin">48dp</dimen>
     <dimen name="analog_clock_margin">48dp</dimen>
 
-    <dimen name="circle_size">360dip</dimen>
-
     <!-- The maximum size of the font for the time in widgets. -->
     <dimen name="widget_max_clock_font_size">100dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index dbe9e1d..67ac240 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -23,7 +23,6 @@
     <dimen name="date_text_size">15sp</dimen>
     <dimen name="next_alarm_text_size">15sp</dimen>
     <dimen name="time_margin_top">48dip</dimen>
-    <dimen name="timer_list_padding_bottom">112dip</dimen>
     <dimen name="screensaver_margin">20dip</dimen>
     <dimen name="alarm_label_padding">64dip</dimen>
     <dimen name="bottom_text_size">18sp</dimen>
@@ -47,7 +46,6 @@
     <dimen name="small_space">32dp</dimen>
     <dimen name="medium_space_top">46dp</dimen>
     <dimen name="medium_space_bottom">18dp</dimen>
-    <dimen name="main_clock_padding">40dp</dimen>
 
     <dimen name="label_margin_big">8dp</dimen>
     <dimen name="label_margin_small">4dp</dimen>
@@ -57,15 +55,11 @@
     <dimen name="timer_setup_font_size">86sp</dimen>
     <dimen name="timer_setup_button_size">36sp</dimen>
     <dimen name="timer_setup_delete_margin">21sp</dimen>
-    <dimen name="timer_setup_label_size">28sp</dimen>
 
     <!-- Size of margin for circles. -->
     <dimen name="circle_margin_top">48dp</dimen>
-    <dimen name="circle_margin">96dp</dimen>
     <dimen name="analog_clock_margin">96dp</dimen>
 
-    <dimen name="circle_size">400dp</dimen>
-
      <!-- Width of the clock, for use with alarm buttons. -->
     <dimen name="alarm_alert_display_width">550dip</dimen>
 
@@ -85,6 +79,4 @@
     <dimen name="city_widget_name_font_size">20dp</dimen>
     <!-- The maximum size of the font for the time in widgets. -->
     <dimen name="widget_max_clock_font_size">125dp</dimen>
-
-    <dimen name="footer_button_size">80dip</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index f2d557f..d3046f2 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -18,13 +18,10 @@
      for different hardware and product builds. -->
 <resources>
 
-    <dimen name="alarm_alert_clock_padding_left">128dp</dimen>
-
     <dimen name="dialpad_font_size">42sp</dimen>
     <dimen name="dialpad_digit_padding">26dip</dimen>
     <dimen name="timer_setup_font_size">78sp</dimen>
     <dimen name="timer_setup_button_size">36sp</dimen>
     <dimen name="timer_setup_delete_margin">19sp</dimen>
-    <dimen name="timer_setup_label_size">24sp</dimen>
 
 </resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index bf80208..41864eb 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -21,8 +21,6 @@
     <dimen name="label_edittext_padding">21dp</dimen>
     <dimen name="time_margin_top">32dip</dimen>
     <dimen name="timer_padding">16dp</dimen>
-    <dimen name="timer_list_padding_bottom">88dip</dimen>
-    <!-- 88dip + 0.5 of footer_button_size -->
     <dimen name="screensaver_margin">16dip</dimen>
     <dimen name="alarm_label_padding">8dip</dimen>
     <dimen name="bottom_text_spacing_digital">-8dp</dimen>
@@ -36,12 +34,11 @@
 
     <dimen name="actionbar_tab_padding">0dip</dimen>
 
-    <dimen name="footer_button_size">56dip</dimen>
-
-    <dimen name="alarm_text_font_size">14sp</dimen>
-    <dimen name="circletimer_dot_size">12dip</dimen>
-    <dimen name="circletimer_circle_size">4dip</dimen>
-    <dimen name="circletimer_marker_size">16dip</dimen>
+    <dimen name="alarm_text_font_size">12sp</dimen>
+    <dimen name="circletimer_dot_size">12dp</dimen>
+    <dimen name="circletimer_circle_size">4dp</dimen>
+    <dimen name="circletimer_marker_size">16dp</dimen>
+    <dimen name="max_timer_circle_size">360dp</dimen>
 
     <dimen name="alarm_lockscreen_alarm_horizontal_padding">16dp</dimen>
     <dimen name="alarm_lockscreen_alarm_vertical_padding">48dp</dimen>
@@ -49,7 +46,7 @@
     <dimen name="alarm_lockscreen_bottom_margin">40dp</dimen>
 
     <dimen name="main_clock_font_size">64sp</dimen>
-    <dimen name="big_font_size">60sp</dimen>
+    <dimen name="big_font_size">32sp</dimen>
     <dimen name="medium_font_size">56sp</dimen>
     <dimen name="small_font_size">32sp</dimen>
     <dimen name="label_font_size">16sp</dimen>
@@ -82,7 +79,6 @@
     <!--margin should be ~ half timer_setup_font_size -->
     <dimen name="timer_setup_delete_margin">14sp</dimen>
     <dimen name="timer_setup_delete_padding">12dp</dimen>
-    <dimen name="timer_setup_label_size">18sp</dimen>
 
     <dimen name="cities_list_item_height">56dip</dimen>
 
@@ -90,8 +86,6 @@
     <dimen name="circle_margin_top">16dp</dimen>
     <dimen name="analog_clock_margin">60dp</dimen>
 
-    <dimen name="circle_size">280dp</dimen>
-
     <!-- The width and height of the notification icon -->
     <dimen name="notification_icon_size">64dp</dimen>
      <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
@@ -109,10 +103,6 @@
     <!-- Size of digital world clock font in landscape. -->
     <dimen name="world_clock_digital_font_size">40sp</dimen>
 
-    <!-- Height of the button footers. 56 height and 16 on top and bottom. -->
-    <dimen name="button_footer_height">88dip</dimen>
-    <!-- Negative value of the height of the button footers, for use with lightsout. -->
-
     <dimen name="min_analog_widget_size">110dp</dimen>
 
     <!-- digital widget sizing information -->
diff --git a/res/layout/blank_footer_view.xml b/res/values/fractions.xml
similarity index 60%
copy from res/layout/blank_footer_view.xml
copy to res/values/fractions.xml
index c9460fc..62c866d 100644
--- a/res/layout/blank_footer_view.xml
+++ b/res/values/fractions.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2016 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,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:background="@color/transparent"
-    android:layout_height="@dimen/button_footer_height" />
\ No newline at end of file
+
+<resources>
+    <!-- In portrait, -100% height implies only width is used to size the timer container. -->
+    <fraction name="timer_circle_height_percent">-100%</fraction>
+
+    <!-- In portrait, timer circles are 60% of the container width; height matches width. -->
+    <fraction name="timer_circle_width_percent">60%</fraction>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f9a140e..dccf10a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -288,13 +288,19 @@
     <!-- Title for ringtones that cannot be located by uri. -->
     <string name="unknown_ringtone_title">Unknown</string>
 
-    <!-- Text to display when alarm volume is muted. -->
+    <!-- Text to display when alarm volume is muted. [CHAR LIMIT=50] -->
     <string name="alarm_volume_muted">Alarm volume muted</string>
 
-    <!-- Text for action that presents a volume control to adjust alarm volume. -->
+    <!-- Text for action that presents a volume control to adjust alarm volume. [CHAR LIMIT=20] -->
     <string name="unmute_alarm_volume">Unmute</string>
 
-    <!-- Text to display when do-not-disturb is blocking alarms. -->
+    <!-- Text to display when system default alarm ringtone is silent. [CHAR LIMIT=50] -->
+    <string name="silent_default_alarm_ringtone">Default alarm ringtone is silent</string>
+
+    <!-- Text for action that shows the UI that changes the default alarm ringtone. [CHAR LIMIT=20] -->
+    <string name="change_default_alarm_ringtone">Change</string>
+
+    <!-- Text to display when do-not-disturb is blocking alarms. [CHAR LIMIT=60] -->
     <string name="alarms_blocked_by_dnd">Device is set to total silence</string>
 
     <!-- Title of the setting to change hardware button behavior. This string
diff --git a/src/com/android/deskclock/CircleButtonsLayout.java b/src/com/android/deskclock/CircleButtonsLayout.java
index a00d6cb..1830ef8 100644
--- a/src/com/android/deskclock/CircleButtonsLayout.java
+++ b/src/com/android/deskclock/CircleButtonsLayout.java
@@ -16,9 +16,6 @@
  */
 public class CircleButtonsLayout extends FrameLayout {
 
-    private int mCircleTimerViewId;
-    private int mResetAddButtonId;
-    private int mLabelId;
     private float mDiamOffset;
     private View mCircleView;
     private ImageButton mResetAddButton;
@@ -31,12 +28,6 @@
 
     public CircleButtonsLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
-    }
-
-    public void setCircleTimerViewIds(int circleTimerViewId, int stopButtonId,  int labelId) {
-        mCircleTimerViewId = circleTimerViewId;
-        mResetAddButtonId = stopButtonId;
-        mLabelId = labelId;
 
         final Resources res = getContext().getResources();
         final float strokeSize = res.getDimension(R.dimen.circletimer_circle_size);
@@ -56,13 +47,10 @@
     }
 
     protected void remeasureViews() {
-        if (mCircleView == null) {
-            mCircleView = findViewById(mCircleTimerViewId);
-            if (mCircleView == null) {
-                return;
-            }
-            mResetAddButton = (ImageButton) findViewById(mResetAddButtonId);
-            mLabel = (TextView) findViewById(mLabelId);
+        if (mLabel == null) {
+            mCircleView = findViewById(R.id.timer_time);
+            mLabel = (TextView) findViewById(R.id.timer_label);
+            mResetAddButton = (ImageButton) findViewById(R.id.reset_add);
         }
 
         final int frameWidth = mCircleView.getMeasuredWidth();
diff --git a/src/com/android/deskclock/ClockFragment.java b/src/com/android/deskclock/ClockFragment.java
index 0a5a714..041e951 100644
--- a/src/com/android/deskclock/ClockFragment.java
+++ b/src/com/android/deskclock/ClockFragment.java
@@ -102,7 +102,6 @@
         super.onCreateView(inflater, container, icicle);
 
         final OnTouchListener startScreenSaverListener = new StartScreenSaverListener();
-        final View footerView = inflater.inflate(R.layout.blank_footer_view, mCityList, false);
         final View fragmentView = inflater.inflate(R.layout.clock_fragment, container, false);
 
         mCityAdapter = new SelectedCitiesAdapter(getActivity());
@@ -110,7 +109,6 @@
         mCityList = (ListView) fragmentView.findViewById(R.id.cities);
         mCityList.setDivider(null);
         mCityList.setAdapter(mCityAdapter);
-        mCityList.addFooterView(footerView, null, false);
         mCityList.setOnTouchListener(startScreenSaverListener);
         mCityList.setOnScrollListener(new VerticalScrollPositionUpdater());
 
diff --git a/src/com/android/deskclock/DeskClock.java b/src/com/android/deskclock/DeskClock.java
index 7e7fa55..dde040e 100644
--- a/src/com/android/deskclock/DeskClock.java
+++ b/src/com/android/deskclock/DeskClock.java
@@ -26,21 +26,24 @@
 import android.app.FragmentManager;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.media.AudioManager;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.provider.Settings;
+import android.support.annotation.StringRes;
 import android.support.design.widget.Snackbar;
 import android.support.design.widget.TabLayout;
 import android.support.design.widget.TabLayout.ViewPagerOnTabSelectedListener;
 import android.support.v13.app.FragmentPagerAdapter;
 import android.support.v4.content.ContextCompat;
-import android.support.v4.os.BuildCompat;
 import android.support.v4.view.ViewPager.OnPageChangeListener;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
@@ -70,7 +73,9 @@
 import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
 import static android.media.AudioManager.FLAG_SHOW_UI;
 import static android.media.AudioManager.STREAM_ALARM;
+import static android.media.RingtoneManager.TYPE_ALARM;
 import static android.provider.Settings.System.CONTENT_URI;
+import static android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI;
 import static android.support.v4.view.ViewPager.SCROLL_STATE_DRAGGING;
 import static android.support.v4.view.ViewPager.SCROLL_STATE_IDLE;
 import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING;
@@ -115,6 +120,12 @@
     /** Updates the user interface to reflect the selected tab from the backing model. */
     private final TabListener mTabChangeWatcher = new TabChangeWatcher();
 
+    /** Displays a snackbar explaining that the system default alarm ringtone is silent. */
+    private final Runnable mShowSilentAlarmSnackbarRunnable = new ShowSilentAlarmSnackbarRunnable();
+
+    /** Observes default alarm ringtone changes while the app is in the foreground. */
+    private final ContentObserver mAlarmRingtoneChangeObserver = new AlarmRingtoneChangeObserver();
+
     /** Displays a snackbar explaining that the alarm volume is muted. */
     private final Runnable mShowMutedVolumeSnackbarRunnable = new ShowMutedVolumeSnackbarRunnable();
 
@@ -300,24 +311,28 @@
 
         if (mShowSilencedAlarmsSnackbar) {
             if (isDoNotDisturbBlockingAlarms()) {
-                // Show the alarms blocked snackbar after a brief delay so it is more noticeable.
                 mSnackbarAnchor.postDelayed(mShowDNDBlockingSnackbarRunnable, SECOND_IN_MILLIS);
             } else if (isAlarmStreamMuted()) {
-                // Show the volume muted snackbar after a brief delay so it is more noticeable.
                 mSnackbarAnchor.postDelayed(mShowMutedVolumeSnackbarRunnable, SECOND_IN_MILLIS);
+            } else if (isSystemAlarmRingtoneSilent()) {
+                mSnackbarAnchor.postDelayed(mShowSilentAlarmSnackbarRunnable, SECOND_IN_MILLIS);
             }
         }
 
+        // Subsequent starts of this activity should show the snackbar by default.
+        mShowSilencedAlarmsSnackbar = true;
+
+        final ContentResolver cr = getContentResolver();
+        // Watch for system alarm ringtone changes while the app is in the foreground.
+        cr.registerContentObserver(DEFAULT_ALARM_ALERT_URI, false, mAlarmRingtoneChangeObserver);
+
         // Watch for alarm volume changes while the app is in the foreground.
-        getContentResolver().registerContentObserver(VOLUME_URI, true, mAlarmVolumeChangeObserver);
+        cr.registerContentObserver(VOLUME_URI, false, mAlarmVolumeChangeObserver);
 
         if (Utils.isMOrLater()) {
             // Watch for do-not-disturb changes while the app is in the foreground.
             registerReceiver(mDoNotDisturbChangeReceiver, DND_CHANGE_FILTER);
         }
-
-        // Subsequent starts of this activity should show the snackbar by default.
-        mShowSilencedAlarmsSnackbar = true;
     }
 
     @Override
@@ -363,6 +378,9 @@
 
     @Override
     protected void onStop() {
+        // Stop watching for system alarm ringtone changes while the app is in the background.
+        getContentResolver().unregisterContentObserver(mAlarmRingtoneChangeObserver);
+
         // Stop watching for alarm volume changes while the app is in the background.
         getContentResolver().unregisterContentObserver(mAlarmVolumeChangeObserver);
 
@@ -372,6 +390,7 @@
         }
 
         // Remove any scheduled work to show snackbars; it is no longer relevant.
+        mSnackbarAnchor.removeCallbacks(mShowSilentAlarmSnackbarRunnable);
         mSnackbarAnchor.removeCallbacks(mShowDNDBlockingSnackbarRunnable);
         mSnackbarAnchor.removeCallbacks(mShowMutedVolumeSnackbarRunnable);
         super.onStop();
@@ -476,6 +495,24 @@
         return (DeskClockFragment) mFragmentTabPagerAdapter.getItem(index);
     }
 
+    private boolean isSystemAlarmRingtoneSilent() {
+        return RingtoneManager.getActualDefaultRingtoneUri(this, TYPE_ALARM) == null;
+    }
+
+    private void showSilentRingtoneSnackbar() {
+        final OnClickListener changeClickListener = new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
+            }
+        };
+
+        SnackbarManager.show(
+                createSnackbar(R.string.silent_default_alarm_ringtone)
+                        .setAction(R.string.change_default_alarm_ringtone, changeClickListener)
+        );
+    }
+
     private boolean isAlarmStreamMuted() {
         return mAudioManager.getStreamVolume(STREAM_ALARM) <= 0;
     }
@@ -491,7 +528,7 @@
         };
 
         SnackbarManager.show(
-                Snackbar.make(mSnackbarAnchor, R.string.alarm_volume_muted, 5000)
+                createSnackbar(R.string.alarm_volume_muted)
                         .setAction(R.string.unmute_alarm_volume, unmuteClickListener)
         );
     }
@@ -505,13 +542,20 @@
     }
 
     private void showDoNotDisturbIsBlockingAlarmsSnackbar() {
-        SnackbarManager.show(Snackbar.make(mSnackbarAnchor, R.string.alarms_blocked_by_dnd, 5000));
+        SnackbarManager.show(createSnackbar(R.string.alarms_blocked_by_dnd));
+    }
+
+    /**
+     * @return a Snackbar that displays the message with the given id for 5 seconds
+     */
+    private Snackbar createSnackbar(@StringRes int messageId) {
+        return Snackbar.make(mSnackbarAnchor, messageId, 5000 /* duration */);
     }
 
     /**
      * As the view pager changes the selected page, update the model to record the new selected tab.
      */
-    private class PageChangeWatcher implements OnPageChangeListener {
+    private final class PageChangeWatcher implements OnPageChangeListener {
 
         /** The last reported page scroll state; used to detect exotic state changes. */
         private int mPriorState = SCROLL_STATE_IDLE;
@@ -579,7 +623,7 @@
      * If this listener is attached to {@link #mHideAnimation} when it ends, the corresponding
      * {@link #mShowAnimation} is automatically started.
      */
-    private class AutoStartShowListener extends AnimatorListenerAdapter {
+    private final class AutoStartShowListener extends AnimatorListenerAdapter {
         @Override
         public void onAnimationEnd(Animator animation) {
             // Prepare the hide animation for its next use; by default do not auto-show after hide.
@@ -597,6 +641,17 @@
     }
 
     /**
+     * Displays a snackbar that indicates the system default alarm ringtone currently silent and
+     * offers an action that displays the system alarm ringtone setting to adjust it.
+     */
+    private final class ShowSilentAlarmSnackbarRunnable implements Runnable {
+        @Override
+        public void run() {
+            showSilentRingtoneSnackbar();
+        }
+    }
+
+    /**
      * Displays a snackbar that indicates the alarm volume is currently muted and offers an action
      * that displays the system volume control to adjust it.
      */
@@ -618,6 +673,25 @@
     }
 
     /**
+     * Observe changes to the system default alarm ringtone while the application is in the
+     * foreground and show/hide the snackbar that warns when the ringtone is silent.
+     */
+    private final class AlarmRingtoneChangeObserver extends ContentObserver {
+        private AlarmRingtoneChangeObserver() {
+            super(new Handler());
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            if (isSystemAlarmRingtoneSilent()) {
+                showSilentRingtoneSnackbar();
+            } else {
+                SnackbarManager.dismiss();
+            }
+        }
+    }
+
+    /**
      * Observe changes to the alarm stream volume while the application is in the foreground and
      * show/hide the snackbar that warns when the alarm volume is muted.
      */
@@ -640,7 +714,7 @@
      * Observe changes to the do-not-disturb setting while the application is in the foreground
      * and show/hide the snackbar that warns when the setting is blocking alarms.
      */
-    private class DoNotDisturbChangeReceiver extends BroadcastReceiver {
+    private final class DoNotDisturbChangeReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             if (isDoNotDisturbBlockingAlarms()) {
@@ -654,7 +728,7 @@
     /**
      * As the model reports changes to the selected tab, update the user interface.
      */
-    private class TabChangeWatcher implements TabListener {
+    private final class TabChangeWatcher implements TabListener {
         @Override
         public void selectedTabChanged(Tab oldSelectedTab, Tab newSelectedTab) {
             final int index = newSelectedTab.ordinal();
@@ -692,7 +766,7 @@
     /**
      * This adapter produces the DeskClockFragments that are the contents of the tabs.
      */
-    private static class TabFragmentAdapter extends FragmentPagerAdapter {
+    private static final class TabFragmentAdapter extends FragmentPagerAdapter {
 
         private final FragmentManager mFragmentManager;
         private final Context mContext;
diff --git a/src/com/android/deskclock/TimerCircleFrameLayout.java b/src/com/android/deskclock/TimerCircleFrameLayout.java
new file mode 100644
index 0000000..45bd546
--- /dev/null
+++ b/src/com/android/deskclock/TimerCircleFrameLayout.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.deskclock;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * A container that frames a timer circle of some sort. The circle is allowed to grow naturally
+ * according to its layout constraints up to the {@link R.dimen#max_timer_circle_size largest}
+ * allowable size.
+ */
+public class TimerCircleFrameLayout extends FrameLayout {
+
+    public TimerCircleFrameLayout(Context context) {
+        super(context);
+    }
+
+    public TimerCircleFrameLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TimerCircleFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    /**
+     * Note: this method assumes the parent container will specify {@link MeasureSpec#EXACTLY exact}
+     * width and height values.
+     *
+     * @param widthMeasureSpec horizontal space requirements as imposed by the parent
+     * @param heightMeasureSpec vertical space requirements as imposed by the parent
+     */
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Fetch the exact sizes imposed by the parent container.
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
+        final int height = MeasureSpec.getSize(heightMeasureSpec);
+        final int smallestDimension = Math.min(width, height);
+
+        // Fetch the absolute maximum circle size allowed.
+        final int maxSize = getResources().getDimensionPixelSize(R.dimen.max_timer_circle_size);
+        final int size = Math.min(smallestDimension, maxSize);
+
+        // Set the size of this container.
+        widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+        heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/deskclock/timer/TimerItem.java b/src/com/android/deskclock/timer/TimerItem.java
index 3f5267e..9bf03c8 100644
--- a/src/com/android/deskclock/timer/TimerItem.java
+++ b/src/com/android/deskclock/timer/TimerItem.java
@@ -24,7 +24,6 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import com.android.deskclock.CircleButtonsLayout;
 import com.android.deskclock.R;
 import com.android.deskclock.data.Timer;
 
@@ -63,10 +62,7 @@
         mResetAddButton = (ImageView) findViewById(R.id.reset_add);
         mCircleView = (TimerCircleView) findViewById(R.id.timer_time);
         mTimerText = (CountingTimerView) findViewById(R.id.timer_time_text);
-
-        // This layout dynamically positions the label and reset buttons.
-        final CircleButtonsLayout cbl = (CircleButtonsLayout) findViewById(R.id.timer_circle);
-        cbl.setCircleTimerViewIds(R.id.timer_time, R.id.reset_add, R.id.timer_label);
+        mTimerText.setShowBoundingCircle(mCircleView != null);
     }
 
     /**
@@ -76,9 +72,6 @@
         // Update the time.
         mTimerText.setTime(timer.getRemainingTime(), false);
 
-        // Update the progress of the circle.
-        mCircleView.update(timer);
-
         // Update the label if it changed.
         final String label = timer.getLabel();
         if (!TextUtils.equals(label, mLabelView.getText())) {
@@ -87,7 +80,15 @@
 
         // Update visibility of things that may blink.
         final boolean blinkOff = SystemClock.elapsedRealtime() % 1000 < 500;
-        mCircleView.setVisibility(timer.isExpired() && blinkOff ? INVISIBLE : VISIBLE);
+        if (mCircleView != null) {
+            final boolean hideCircle = timer.isExpired() && blinkOff;
+            mCircleView.setVisibility(hideCircle ? INVISIBLE : VISIBLE);
+
+            if (!hideCircle) {
+                // Update the progress of the circle.
+                mCircleView.update(timer);
+            }
+        }
         mTimerText.showTime(!timer.isPaused() || !blinkOff);
 
         // Update some potentially expensive areas of the user interface only on state changes.
@@ -125,4 +126,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file