OSDN Git Service

auto import from //depot/cupcake/@135843
authorThe Android Open Source Project <initial-contribution@android.com>
Wed, 4 Mar 2009 03:32:15 +0000 (19:32 -0800)
committerThe Android Open Source Project <initial-contribution@android.com>
Wed, 4 Mar 2009 03:32:15 +0000 (19:32 -0800)
72 files changed:
Android.mk [new file with mode: 0644]
AndroidManifest.xml [new file with mode: 0644]
MODULE_LICENSE_APACHE2 [new file with mode: 0644]
NOTICE [new file with mode: 0644]
res/drawable/animate_circle.xml [new file with mode: 0644]
res/drawable/circle0.png [new file with mode: 0644]
res/drawable/circle1.png [new file with mode: 0644]
res/drawable/circle2.png [new file with mode: 0644]
res/drawable/circle3.png [new file with mode: 0644]
res/drawable/clock_dial.png [new file with mode: 0644]
res/drawable/clock_hour.png [new file with mode: 0644]
res/drawable/clock_minute.png [new file with mode: 0644]
res/drawable/clockdroid2_dial.png [new file with mode: 0644]
res/drawable/clockdroid2_hour.png [new file with mode: 0644]
res/drawable/clockdroid2_minute.png [new file with mode: 0644]
res/drawable/clockdroids_dial.png [new file with mode: 0644]
res/drawable/clockdroids_hour.png [new file with mode: 0644]
res/drawable/clockdroids_minute.png [new file with mode: 0644]
res/drawable/clockgoog_dial.png [new file with mode: 0644]
res/drawable/clockgoog_hour.png [new file with mode: 0644]
res/drawable/clockgoog_minute.png [new file with mode: 0644]
res/drawable/gadget_clock_dial.png [new file with mode: 0644]
res/drawable/gadget_clock_hour.png [new file with mode: 0644]
res/drawable/gadget_clock_minute.png [new file with mode: 0644]
res/drawable/ic_launcher_alarmclock.png [new file with mode: 0755]
res/drawable/ic_menu_clock_face.png [new file with mode: 0644]
res/layout-land/alarm_alert.xml [new file with mode: 0644]
res/layout-land/alarm_clock.xml [new file with mode: 0644]
res/layout/alarm_alert.xml [new file with mode: 0644]
res/layout/alarm_clock.xml [new file with mode: 0644]
res/layout/alarm_time.xml [new file with mode: 0644]
res/layout/analog_gadget.xml [new file with mode: 0644]
res/layout/clock_basic_bw.xml [new file with mode: 0644]
res/layout/clock_droid2.xml [new file with mode: 0644]
res/layout/clock_droids.xml [new file with mode: 0644]
res/layout/clock_googly.xml [new file with mode: 0644]
res/layout/clockpicker.xml [new file with mode: 0644]
res/layout/digital_clock.xml [new file with mode: 0644]
res/values-cs/strings.xml [new file with mode: 0644]
res/values-de/strings.xml [new file with mode: 0644]
res/values-es/strings.xml [new file with mode: 0644]
res/values-fr/strings.xml [new file with mode: 0644]
res/values-it/strings.xml [new file with mode: 0644]
res/values-ja/strings.xml [new file with mode: 0644]
res/values-ko/strings.xml [new file with mode: 0644]
res/values-nb/strings.xml [new file with mode: 0644]
res/values-nl/strings.xml [new file with mode: 0644]
res/values-pl/strings.xml [new file with mode: 0644]
res/values-ru/strings.xml [new file with mode: 0644]
res/values-zh-rCN/strings.xml [new file with mode: 0644]
res/values-zh-rTW/strings.xml [new file with mode: 0644]
res/values/colors.xml [new file with mode: 0644]
res/values/strings.xml [new file with mode: 0644]
res/values/styles.xml [new file with mode: 0644]
res/xml/alarm_prefs.xml [new file with mode: 0644]
res/xml/analog_gadget.xml [new file with mode: 0644]
src/com/android/alarmclock/AlarmAlert.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmAlertWakeLock.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmClock.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmInitReceiver.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmKlaxon.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmPreference.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmProvider.java [new file with mode: 0644]
src/com/android/alarmclock/AlarmReceiver.java [new file with mode: 0644]
src/com/android/alarmclock/Alarms.java [new file with mode: 0644]
src/com/android/alarmclock/AnalogGadgetProvider.java [new file with mode: 0644]
src/com/android/alarmclock/ClockPicker.java [new file with mode: 0644]
src/com/android/alarmclock/DigitalClock.java [new file with mode: 0644]
src/com/android/alarmclock/Log.java [new file with mode: 0644]
src/com/android/alarmclock/RepeatPreference.java [new file with mode: 0644]
src/com/android/alarmclock/SetAlarm.java [new file with mode: 0644]
src/com/android/alarmclock/ToastMaster.java [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..3b05373
--- /dev/null
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng development
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := AlarmClock
+
+include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..efcc882
--- /dev/null
@@ -0,0 +1,56 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.alarmclock">
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.WAKE_LOCK"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application android:label="@string/app_label"
+                 android:icon="@drawable/ic_launcher_alarmclock">
+
+        <provider android:name="AlarmProvider" android:authorities="com.android.alarmclock" />
+
+        <activity android:name="AlarmClock" android:label="@string/app_label">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="SetAlarm" android:label="@string/set_alarm" />
+
+        <activity android:name="AlarmAlert" android:label="@string/alert_title"
+                android:excludeFromRecents="true"
+                android:theme="@android:style/Theme.Dialog"
+                android:launchMode="singleTask"
+                android:taskAffinity=":AlarmAlert"
+                android:configChanges="orientation|keyboardHidden|keyboard|navigation" />
+
+        <activity android:name="ClockPicker" />
+
+        <receiver android:name="AlarmReceiver">
+            <intent-filter>
+               <action android:name="com.android.alarmclock.ALARM_ALERT" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="AlarmInitReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+                <action android:name="android.intent.action.TIME_SET" />
+                <action android:name="android.intent.action.TIMEZONE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="AnalogGadgetProvider" android:label="@string/analog_gadget">
+            <intent-filter>
+                <action android:name="android.gadget.action.GADGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.gadget.provider" android:resource="@xml/analog_gadget" />
+        </receiver>
+    </application>
+</manifest>
+
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..c5b1efa
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/res/drawable/animate_circle.xml b/res/drawable/animate_circle.xml
new file mode 100644 (file)
index 0000000..02dfd51
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!--  Chewie... the hyperdrive ain't working -->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:oneshot="false" android:visible="true">
+    <item android:drawable="@drawable/circle0" android:duration="80" />
+    <item android:drawable="@drawable/circle1" android:duration="80" />
+    <item android:drawable="@drawable/circle2" android:duration="80" />
+    <item android:drawable="@drawable/circle3" android:duration="80" />
+</animation-list>
+
+
+
diff --git a/res/drawable/circle0.png b/res/drawable/circle0.png
new file mode 100644 (file)
index 0000000..1386ed4
Binary files /dev/null and b/res/drawable/circle0.png differ
diff --git a/res/drawable/circle1.png b/res/drawable/circle1.png
new file mode 100644 (file)
index 0000000..fed0190
Binary files /dev/null and b/res/drawable/circle1.png differ
diff --git a/res/drawable/circle2.png b/res/drawable/circle2.png
new file mode 100644 (file)
index 0000000..9712976
Binary files /dev/null and b/res/drawable/circle2.png differ
diff --git a/res/drawable/circle3.png b/res/drawable/circle3.png
new file mode 100644 (file)
index 0000000..056bb45
Binary files /dev/null and b/res/drawable/circle3.png differ
diff --git a/res/drawable/clock_dial.png b/res/drawable/clock_dial.png
new file mode 100644 (file)
index 0000000..734e361
Binary files /dev/null and b/res/drawable/clock_dial.png differ
diff --git a/res/drawable/clock_hour.png b/res/drawable/clock_hour.png
new file mode 100644 (file)
index 0000000..023faa4
Binary files /dev/null and b/res/drawable/clock_hour.png differ
diff --git a/res/drawable/clock_minute.png b/res/drawable/clock_minute.png
new file mode 100644 (file)
index 0000000..104e2a2
Binary files /dev/null and b/res/drawable/clock_minute.png differ
diff --git a/res/drawable/clockdroid2_dial.png b/res/drawable/clockdroid2_dial.png
new file mode 100644 (file)
index 0000000..0996f09
Binary files /dev/null and b/res/drawable/clockdroid2_dial.png differ
diff --git a/res/drawable/clockdroid2_hour.png b/res/drawable/clockdroid2_hour.png
new file mode 100644 (file)
index 0000000..cf6268d
Binary files /dev/null and b/res/drawable/clockdroid2_hour.png differ
diff --git a/res/drawable/clockdroid2_minute.png b/res/drawable/clockdroid2_minute.png
new file mode 100644 (file)
index 0000000..a4fe782
Binary files /dev/null and b/res/drawable/clockdroid2_minute.png differ
diff --git a/res/drawable/clockdroids_dial.png b/res/drawable/clockdroids_dial.png
new file mode 100644 (file)
index 0000000..45e86d0
Binary files /dev/null and b/res/drawable/clockdroids_dial.png differ
diff --git a/res/drawable/clockdroids_hour.png b/res/drawable/clockdroids_hour.png
new file mode 100644 (file)
index 0000000..898d44d
Binary files /dev/null and b/res/drawable/clockdroids_hour.png differ
diff --git a/res/drawable/clockdroids_minute.png b/res/drawable/clockdroids_minute.png
new file mode 100644 (file)
index 0000000..4e59764
Binary files /dev/null and b/res/drawable/clockdroids_minute.png differ
diff --git a/res/drawable/clockgoog_dial.png b/res/drawable/clockgoog_dial.png
new file mode 100644 (file)
index 0000000..a83b7b8
Binary files /dev/null and b/res/drawable/clockgoog_dial.png differ
diff --git a/res/drawable/clockgoog_hour.png b/res/drawable/clockgoog_hour.png
new file mode 100644 (file)
index 0000000..7eff3c2
Binary files /dev/null and b/res/drawable/clockgoog_hour.png differ
diff --git a/res/drawable/clockgoog_minute.png b/res/drawable/clockgoog_minute.png
new file mode 100644 (file)
index 0000000..b1eaebd
Binary files /dev/null and b/res/drawable/clockgoog_minute.png differ
diff --git a/res/drawable/gadget_clock_dial.png b/res/drawable/gadget_clock_dial.png
new file mode 100644 (file)
index 0000000..eda3d17
Binary files /dev/null and b/res/drawable/gadget_clock_dial.png differ
diff --git a/res/drawable/gadget_clock_hour.png b/res/drawable/gadget_clock_hour.png
new file mode 100644 (file)
index 0000000..fcfd948
Binary files /dev/null and b/res/drawable/gadget_clock_hour.png differ
diff --git a/res/drawable/gadget_clock_minute.png b/res/drawable/gadget_clock_minute.png
new file mode 100644 (file)
index 0000000..afc0a3f
Binary files /dev/null and b/res/drawable/gadget_clock_minute.png differ
diff --git a/res/drawable/ic_launcher_alarmclock.png b/res/drawable/ic_launcher_alarmclock.png
new file mode 100755 (executable)
index 0000000..30ff267
Binary files /dev/null and b/res/drawable/ic_launcher_alarmclock.png differ
diff --git a/res/drawable/ic_menu_clock_face.png b/res/drawable/ic_menu_clock_face.png
new file mode 100644 (file)
index 0000000..678af24
Binary files /dev/null and b/res/drawable/ic_menu_clock_face.png differ
diff --git a/res/layout-land/alarm_alert.xml b/res/layout-land/alarm_alert.xml
new file mode 100644 (file)
index 0000000..a58bc56
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent"
+    android:paddingTop="2dp">
+
+    <LinearLayout
+        android:layout_width="wrap_content" 
+        android:layout_height="fill_parent"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/clockView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"/>
+
+        <TextView android:id="@+id/silencedText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingLeft="4dp"
+            android:paddingTop="2dp"
+            android:paddingBottom="2dp"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:visibility="gone"
+            android:gravity="center"
+            android:textColor="@color/red"
+            android:text="@string/alarm_alert_alert_silenced"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content" 
+        android:layout_height="fill_parent"
+        android:orientation="vertical">
+
+        <Button
+            android:id="@+id/snooze"
+            android:layout_width="108dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" 
+            android:text="@string/alarm_alert_snooze_text" />
+
+        <!-- blank stretchable view -->
+        <View
+            android:layout_width="2dip"
+            android:layout_gravity="fill_vertical" 
+            android:layout_weight="1" 
+            android:layout_height="2dip"/>
+
+        <Button
+            android:id="@+id/dismiss"
+            android:layout_width="108dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" 
+            android:text="@string/alarm_alert_dismiss_text" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout-land/alarm_clock.xml b/res/layout-land/alarm_clock.xml
new file mode 100644 (file)
index 0000000..5b51e53
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/base_layout"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="center_vertical"> 
+
+    <FrameLayout
+        android:id="@+id/clock_layout"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:layout_marginLeft="8dip"
+        android:layout_marginRight="8dip"/> 
+
+    <ListView
+        android:id="@+id/alarms_list"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/res/layout/alarm_alert.xml b/res/layout/alarm_alert.xml
new file mode 100644 (file)
index 0000000..f18d4ad
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/clockView"
+        android:layout_width="208dip"
+        android:layout_height="wrap_content"
+        android:gravity="center"/> 
+
+    <LinearLayout
+        android:layout_width="fill_parent" 
+        android:layout_height="wrap_content"
+        android:paddingTop="4dp">
+
+        <Button
+            android:id="@+id/snooze"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="16dp"
+            android:paddingBottom="24dp"
+            android:layout_weight="3"
+            android:text="@string/alarm_alert_snooze_text" />
+
+        <!-- blank stretchable view -->
+        <View
+            android:layout_width="2dip"
+            android:layout_height="2dip"
+            android:layout_gravity="fill_horizontal" 
+            android:layout_weight="1"/>
+        
+        <Button
+            android:id="@+id/dismiss"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="16dp"
+            android:paddingBottom="24dp"
+            android:layout_weight="3"
+            android:text="@string/alarm_alert_dismiss_text" />
+
+    </LinearLayout>
+
+    <TextView android:id="@+id/silencedText"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="2dp"
+        android:paddingBottom="2dp"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:visibility="gone"
+        android:gravity="center"
+        android:textColor="@color/red"/>
+
+</LinearLayout>
diff --git a/res/layout/alarm_clock.xml b/res/layout/alarm_clock.xml
new file mode 100644 (file)
index 0000000..a0ca8e3
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/base_layout"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:layout_marginTop="6dip"
+    android:orientation="vertical"> 
+
+    <LinearLayout
+        android:id="@+id/clock_layout"
+        android:layout_width="fill_parent"
+        android:layout_height="208dip"
+        android:layout_marginBottom="8dip"
+        android:gravity="center"/> 
+
+    <ListView
+        android:id="@+id/alarms_list"
+        android:layout_width="fill_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1.0" />
+
+</LinearLayout>
diff --git a/res/layout/alarm_time.xml b/res/layout/alarm_time.xml
new file mode 100644 (file)
index 0000000..aae6ef2
--- /dev/null
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content">
+
+    <!-- A layout that displays the time.  Shows time, am/pm (if 12-hour),
+         and an optional line below, used for day/days of week -->
+
+    <com.android.alarmclock.DigitalClock android:id="@+id/digitalClock"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:focusable="true"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:orientation="vertical"
+        android:paddingTop="4dp"
+        android:paddingLeft="8dp"
+        android:background="@android:drawable/menuitem_background">
+
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="left">
+
+            <TextView android:id="@+id/timeDisplay"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingTop="-4dp"
+                android:paddingBottom="-4dp"
+                android:textSize="28sp"
+                android:gravity="left"
+                android:textColor="@color/white"/>
+
+            <LinearLayout android:id="@+id/am_pm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="4dp"
+                android:orientation="vertical">
+
+                <TextView android:id="@+id/am"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="3dp"
+                    android:text="@string/am"
+                    android:textSize="12sp"/>
+                <TextView android:id="@+id/pm"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="-4dp"
+                    android:text="@string/pm"
+                    android:textSize="12sp"/>
+            </LinearLayout>
+        </LinearLayout>
+
+        <TextView android:id="@+id/daysOfWeek"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textSize="10sp"
+            android:textColor="@color/ltgrey"
+            android:layout_marginLeft="2dp"
+            android:gravity="left"/>
+
+    </com.android.alarmclock.DigitalClock>
+
+    <CheckBox android:id="@+id/alarmButton"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
+        android:layout_gravity="center_vertical"/>
+
+</LinearLayout>
diff --git a/res/layout/analog_gadget.xml b/res/layout/analog_gadget.xml
new file mode 100644 (file)
index 0000000..efa4789
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+    android:dial="@drawable/gadget_clock_dial"
+    android:hand_hour="@drawable/gadget_clock_hour"
+    android:hand_minute="@drawable/gadget_clock_minute"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
diff --git a/res/layout/clock_basic_bw.xml b/res/layout/clock_basic_bw.xml
new file mode 100644 (file)
index 0000000..b1593e9
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/clock"
+    style="@style/analogClock"
+    android:dial="@drawable/clock_dial"
+    android:hand_hour="@drawable/clock_hour"
+    android:hand_minute="@drawable/clock_minute"/>
diff --git a/res/layout/clock_droid2.xml b/res/layout/clock_droid2.xml
new file mode 100644 (file)
index 0000000..336efd3
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/clock"
+    style="@style/analogClock"
+    android:dial="@drawable/clockdroid2_dial"
+    android:hand_hour="@drawable/clockdroid2_hour"
+    android:hand_minute="@drawable/clockdroid2_minute"/>
diff --git a/res/layout/clock_droids.xml b/res/layout/clock_droids.xml
new file mode 100644 (file)
index 0000000..9ec79b6
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/clock"
+    style="@style/analogClock"
+    android:dial="@drawable/clockdroids_dial"
+    android:hand_hour="@drawable/clockdroids_hour"
+    android:hand_minute="@drawable/clockdroids_minute"/>
diff --git a/res/layout/clock_googly.xml b/res/layout/clock_googly.xml
new file mode 100644 (file)
index 0000000..cb09d85
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/clock"
+    style="@style/analogClock"
+    android:dial="@drawable/clockgoog_dial"
+    android:hand_hour="@drawable/clockgoog_hour"
+    android:hand_minute="@drawable/clockgoog_minute"/>
diff --git a/res/layout/clockpicker.xml b/res/layout/clockpicker.xml
new file mode 100644 (file)
index 0000000..2e2c3b9
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:layout_width="fill_parent" 
+    android:layout_height="fill_parent"> 
+    
+    <TextView
+        android:id="@+id/instructions"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="5dip"
+        android:background="#70000000"
+        android:text="@string/clock_instructions"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+    />
+    <LinearLayout
+        android:id="@+id/clock_layout"
+        android:layout_width="fill_parent"
+        android:layout_below="@+id/instructions"
+        android:layout_height="208dip"
+        android:gravity="center"/> 
+    
+    <Gallery android:id="@+id/gallery"
+        android:background="#70000000"
+        android:layout_width="fill_parent"
+        android:layout_height="80dip"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:gravity="center_vertical"
+        android:spacing="16dp"
+    />
+
+</RelativeLayout>
+   
diff --git a/res/layout/digital_clock.xml b/res/layout/digital_clock.xml
new file mode 100644 (file)
index 0000000..95d9f5e
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<com.android.alarmclock.DigitalClock android:id="@+id/digitalClock"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="208dip"
+    android:gravity="center">
+
+    <!-- Includes vertical padding so animated background doesn't
+         stretch much -->
+    <TextView android:id="@+id/timeDisplay"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="64sp"
+        android:paddingRight="4dip"
+        android:paddingTop="48dip"
+        android:paddingBottom="48dip"
+        android:textColor="@color/white"/>
+
+    <LinearLayout android:id="@+id/am_pm"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <TextView android:id="@+id/am"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-7dp"
+            android:text="@string/am"
+            android:textSize="28sp"/>
+        <TextView android:id="@+id/pm"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-4dp"
+            android:text="@string/pm"
+            android:textSize="28sp"/>
+    </LinearLayout>
+</com.android.alarmclock.DigitalClock>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
new file mode 100644 (file)
index 0000000..e0a1063
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Budík"</string>
+    <string name="add_alarm">"Přidat upozornění"</string>
+    <string name="delete_alarm">"Smazat upozornění"</string>
+    <string name="delete_alarm_confirm">"Toto upozornění bude odstraněno."</string>
+    <string name="show_clock">"Zobrazit hodiny"</string>
+    <string name="hide_clock">"Skrýt hodiny"</string>
+    <string name="set_alarm">"Nastavit upozornění"</string>
+    <string name="enable">"Zapnout upozornění"</string>
+    <string name="alarm_vibrate">"Vibrace"</string>
+    <string name="alarm_repeat">"Opakovat"</string>
+    <string name="alert">"Vyzváněcí tón"</string>
+    <string name="time">"Čas"</string>
+    <string name="alert_title">"Upozornění"</string>
+    <string name="alarm_alert_dismiss_text">"Zavřít"</string>
+    <string name="alarm_alert_alert_silenced">"Upozornění ztišeno po uplynutí <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+    <string name="alarm_alert_snooze_text">"Odložit"</string>
+    <string name="alarm_alert_snooze_set">"Upozornění odloženo o <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+    <string name="alarm_alert_snooze_not_set">"Upozornění nebylo odloženo – další upozornění v <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="alarm_set">"Toto upozornění bude aktivováno za: <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 den"</string>
+    <string name="days">"dní: <xliff:g id="DAYS">%s</xliff:g>"</string>
+    <string name="hour">"1 hodina"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> hod."</string>
+    <string name="and">" a "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"méně než 1 minuta"</string>
+    <string name="minute">"1 minuta"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> min"</string>
+    <string name="am">"dop."</string>
+    <string name="pm">"odp."</string>
+    <string name="every_day">"Každý den"</string>
+    <string name="never">"Nikdy"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Vyberte hodiny, které mají být zobrazeny."</string>
+    <string name="error">"Upozornění není nastaveno"</string>
+    <string name="dberror">"Upozornění bohužel nelze nastavit."</string>
+    <string name="analog_gadget">"Analogové hodiny"</string>
+  <string-array name="days_of_week">
+    <item>"Pondělí"</item>
+    <item>"Úterý"</item>
+    <item>"Středa"</item>
+    <item>"Čtvrtek"</item>
+    <item>"Pátek"</item>
+    <item>"Sobota"</item>
+    <item>"Neděle"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Po"</item>
+    <item>"Út"</item>
+    <item>"St"</item>
+    <item>"Čt"</item>
+    <item>"Pá"</item>
+    <item>"So"</item>
+    <item>"Ne"</item>
+  </string-array>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644 (file)
index 0000000..ee9823c
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Wecker"</string>
+    <string name="add_alarm">"Wecker hinzufügen"</string>
+    <string name="delete_alarm">"Wecker löschen"</string>
+    <string name="delete_alarm_confirm">"Dieser Alarm wird gelöscht."</string>
+    <string name="show_clock">"Uhr anzeigen"</string>
+    <string name="hide_clock">"Uhr ausblenden"</string>
+    <string name="set_alarm">"Wecker einstellen"</string>
+    <string name="enable">"Wecker aktivieren"</string>
+    <string name="alarm_vibrate">"Vibrieren"</string>
+    <string name="alarm_repeat">"Wiederholen"</string>
+    <string name="alert">"Klingelton"</string>
+    <string name="time">"Uhrzeit"</string>
+    <string name="alert_title">"Wecker"</string>
+    <string name="alarm_alert_dismiss_text">"Verwerfen"</string>
+    <string name="alarm_alert_alert_silenced">"Der Wecker verstummte nach <xliff:g id="MINUTES">%d</xliff:g> Minuten"</string>
+    <string name="alarm_alert_snooze_text">"Snooze-Funktion"</string>
+    <string name="alarm_alert_snooze_set">"Snooze-Funktion aktiviert für <xliff:g id="MINUTES">%d</xliff:g> Minuten"</string>
+    <string name="alarm_alert_snooze_not_set">"Snooze-Funktion nicht aktiviert - nächster Wecker klingelt <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="alarm_set">"Dieser Wecker klingelt in <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 Tag"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> Tagen"</string>
+    <string name="hour">"1 Stunde"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> Stunden"</string>
+    <string name="and">" und "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"weniger als 1 Minute"</string>
+    <string name="minute">"1 Minute"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> Minuten"</string>
+    <string name="am">"AM"</string>
+    <string name="pm">"PM"</string>
+    <string name="every_day">"Täglich"</string>
+    <string name="never">"Nie"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Wählen Sie die anzuzeigende Uhr aus."</string>
+    <string name="error">"Wecker nicht eingestellt"</string>
+    <string name="dberror">"Der Wecker konnte nicht eingestellt werden."</string>
+    <string name="analog_gadget">"Analoguhr"</string>
+  <string-array name="days_of_week">
+    <item>"Montag"</item>
+    <item>"Dienstag"</item>
+    <item>"Mittwoch"</item>
+    <item>"Donnerstag"</item>
+    <item>"Freitag"</item>
+    <item>"Samstag"</item>
+    <item>"Sonntag"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Mo"</item>
+    <item>"Di"</item>
+    <item>"Mi"</item>
+    <item>"Do"</item>
+    <item>"Fr"</item>
+    <item>"Sa"</item>
+    <item>"So"</item>
+  </string-array>
+</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
new file mode 100644 (file)
index 0000000..be6dd6a
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Alarma"</string>
+    <string name="add_alarm">"Añadir alarma"</string>
+    <string name="delete_alarm">"Eliminar alarma"</string>
+    <string name="delete_alarm_confirm">"Esta alarma se eliminará."</string>
+    <string name="show_clock">"Mostrar reloj"</string>
+    <string name="hide_clock">"Ocultar reloj"</string>
+    <string name="set_alarm">"Establecer alarma"</string>
+    <string name="enable">"Activar alarma"</string>
+    <string name="alarm_vibrate">"Vibración"</string>
+    <string name="alarm_repeat">"Repetir"</string>
+    <string name="alert">"Tono"</string>
+    <string name="time">"Hora"</string>
+    <string name="alert_title">"Alarma"</string>
+    <string name="alarm_alert_dismiss_text">"Descartar"</string>
+    <string name="alarm_alert_alert_silenced">"La alarma se ha silenciado después de <xliff:g id="MINUTES">%d</xliff:g> minutos."</string>
+    <string name="alarm_alert_snooze_text">"Posponer"</string>
+    <string name="alarm_alert_snooze_set">"La alarma volverá a sonar en <xliff:g id="MINUTES">%d</xliff:g> minutos."</string>
+    <string name="alarm_alert_snooze_not_set">"No se ha pospuesto la alarma, ya que la siguiente alarma sonará a las <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="alarm_set">"La alarma sonará en <xliff:g id="TIME_DELTA">%s</xliff:g> ."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 día"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> días"</string>
+    <string name="hour">"1 hora"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> horas"</string>
+    <string name="and">" y "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"menos de 1 minuto"</string>
+    <string name="minute">"1 minuto"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutos"</string>
+    <string name="am">"a.m."</string>
+    <string name="pm">"p.m."</string>
+    <string name="every_day">"todos los días"</string>
+    <string name="never">"Nunca"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Selecciona el reloj que quieras ver."</string>
+    <string name="error">"Alarma no establecida"</string>
+    <string name="dberror">"No se ha podido establecer la alarma."</string>
+    <string name="analog_gadget">"Reloj analógico"</string>
+  <string-array name="days_of_week">
+    <item>"Lunes"</item>
+    <item>"Martes"</item>
+    <item>"Miércoles"</item>
+    <item>"Jueves"</item>
+    <item>"Viernes"</item>
+    <item>"Sábado"</item>
+    <item>"Domingo"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Lun."</item>
+    <item>"Mar."</item>
+    <item>"Mié."</item>
+    <item>"Jue."</item>
+    <item>"Vie."</item>
+    <item>"Sáb."</item>
+    <item>"Dom."</item>
+  </string-array>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
new file mode 100644 (file)
index 0000000..929173b
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Réveil"</string>
+    <string name="add_alarm">"Ajouter alarme"</string>
+    <string name="delete_alarm">"Désactiver l\'alarme"</string>
+    <string name="delete_alarm_confirm">"Cette alarme va être supprimée."</string>
+    <string name="show_clock">"Afficher l\'horloge"</string>
+    <string name="hide_clock">"Masquer l\'horloge"</string>
+    <string name="set_alarm">"Régler l\'alarme"</string>
+    <string name="enable">"Activer l\'alarme"</string>
+    <string name="alarm_vibrate">"Vibreur"</string>
+    <string name="alarm_repeat">"Répéter"</string>
+    <string name="alert">"Sonnerie"</string>
+    <string name="time">"Heure"</string>
+    <string name="alert_title">"Alarme"</string>
+    <string name="alarm_alert_dismiss_text">"Quitter"</string>
+    <string name="alarm_alert_alert_silenced">"Alarme interrompue après <xliff:g id="MINUTES">%d</xliff:g> minutes"</string>
+    <string name="alarm_alert_snooze_text">"Répéter"</string>
+    <string name="alarm_alert_snooze_set">"Répétition dans <xliff:g id="MINUTES">%d</xliff:g> minutes."</string>
+    <string name="alarm_alert_snooze_not_set">"Répétition non activée : prochaine alarme à <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"Prochaine alarme dans <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 jour"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> jours"</string>
+    <string name="hour">"1 heure"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> heures"</string>
+    <string name="and">" et "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"moins d\'une minute"</string>
+    <string name="minute">"1 minute"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutes"</string>
+    <string name="am">"a.m."</string>
+    <string name="pm">"p.m."</string>
+    <string name="every_day">"Tous les jours"</string>
+    <string name="never">"Jamais"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Sélectionnez une horloge à afficher."</string>
+    <string name="error">"Alarme non activée"</string>
+    <string name="dberror">"Désolé, impossible de régler l\'alarme."</string>
+    <string name="analog_gadget">"Horloge analogique"</string>
+  <string-array name="days_of_week">
+    <item>"Lundi"</item>
+    <item>"Mardi"</item>
+    <item>"Mercredi"</item>
+    <item>"Jeudi"</item>
+    <item>"Vendredi"</item>
+    <item>"Samedi"</item>
+    <item>"Dimanche"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Lun"</item>
+    <item>"Mar"</item>
+    <item>"Mer"</item>
+    <item>"Jeu"</item>
+    <item>"Ven"</item>
+    <item>"Sam"</item>
+    <item>"Dim"</item>
+  </string-array>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
new file mode 100644 (file)
index 0000000..e5a5787
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Sveglia"</string>
+    <string name="add_alarm">"Aggiungi allarme"</string>
+    <string name="delete_alarm">"Elimina allarme"</string>
+    <string name="delete_alarm_confirm">"Questa sveglia verrà eliminata."</string>
+    <string name="show_clock">"Mostra orologio"</string>
+    <string name="hide_clock">"Nascondi orologio"</string>
+    <string name="set_alarm">"Imposta allarme"</string>
+    <string name="enable">"Attiva allarme"</string>
+    <string name="alarm_vibrate">"Vibrazione"</string>
+    <string name="alarm_repeat">"Ripeti"</string>
+    <string name="alert">"Suoneria"</string>
+    <string name="time">"Ora"</string>
+    <string name="alert_title">"Allarme"</string>
+    <string name="alarm_alert_dismiss_text">"Spegni"</string>
+    <string name="alarm_alert_alert_silenced">"Tono allarme disattivato dopo <xliff:g id="MINUTES">%d</xliff:g> minuti"</string>
+    <string name="alarm_alert_snooze_text">"Posponi"</string>
+    <string name="alarm_alert_snooze_set">"Sospensione per <xliff:g id="MINUTES">%d</xliff:g> minuti."</string>
+    <string name="alarm_alert_snooze_not_set">"Sospensione non impostata. Prossimo allarme alle <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"L\'allarme sarà attivato fra <xliff:g id="TIME_DELTA">%s</xliff:g>."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 giorno"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> giorni"</string>
+    <string name="hour">"1 ora"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> ore"</string>
+    <string name="and">" e "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"meno di 1 minuto"</string>
+    <string name="minute">"1 minuto"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minuti"</string>
+    <string name="am">"am"</string>
+    <string name="pm">"pm"</string>
+    <string name="every_day">"Ogni giorno"</string>
+    <string name="never">"Mai"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Seleziona un orologio."</string>
+    <string name="error">"Allarme non impostato"</string>
+    <string name="dberror">"Spiacenti. Impossibile impostare l\'allarme."</string>
+    <string name="analog_gadget">"Orologio analogico"</string>
+  <string-array name="days_of_week">
+    <item>"Lunedì"</item>
+    <item>"Martedì"</item>
+    <item>"Mercoledì"</item>
+    <item>"Giovedì"</item>
+    <item>"Venerdì"</item>
+    <item>"Sabato"</item>
+    <item>"Domenica"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Lun"</item>
+    <item>"Mar"</item>
+    <item>"Mer"</item>
+    <item>"Gio"</item>
+    <item>"Ven"</item>
+    <item>"Sab"</item>
+    <item>"Dom"</item>
+  </string-array>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644 (file)
index 0000000..72149bb
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"アラーム"</string>
+    <string name="add_alarm">"アラームの設定"</string>
+    <string name="delete_alarm">"アラームを削除"</string>
+    <string name="delete_alarm_confirm">"このアラームを削除します。"</string>
+    <string name="show_clock">"時計を表示"</string>
+    <string name="hide_clock">"時計を隠す"</string>
+    <string name="set_alarm">"アラームの設定"</string>
+    <string name="enable">"アラームをONにする"</string>
+    <string name="alarm_vibrate">"バイブレーション"</string>
+    <string name="alarm_repeat">"繰り返し"</string>
+    <string name="alert">"アラーム音"</string>
+    <string name="time">"時刻"</string>
+    <string name="alert_title">"アラーム"</string>
+    <string name="alarm_alert_dismiss_text">"停止"</string>
+    <string name="alarm_alert_alert_silenced">"アラームは<xliff:g id="MINUTES">%d</xliff:g>分間鳴って止まりました"</string>
+    <string name="alarm_alert_snooze_text">"スヌーズ"</string>
+    <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g>分間スヌーズ"</string>
+    <string name="alarm_alert_snooze_not_set">"スヌーズ設定エラー: <xliff:g id="TIME">%s</xliff:g>に次のアラームがセットされています"</string>
+    <string name="alarm_set">"<xliff:g id="TIME_DELTA">%s</xliff:g>後にセットしました"</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1日"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g>日"</string>
+    <string name="hour">"1時間"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g>時間"</string>
+    <string name="and">" と "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"1分未満"</string>
+    <string name="minute">"1分"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g>分"</string>
+    <string name="am">"AM"</string>
+    <string name="pm">"PM"</string>
+    <string name="every_day">"毎日"</string>
+    <string name="never">"繰り返しなし"</string>
+    <string name="day_concat">"、 "</string>
+    <string name="clock_instructions">"表示する時計を選択してください。"</string>
+    <string name="error">"アラームを設定できません"</string>
+    <string name="dberror">"アラームを設定できません"</string>
+    <string name="analog_gadget">"アナログ時計"</string>
+  <string-array name="days_of_week">
+    <item>"月曜日"</item>
+    <item>"火曜日"</item>
+    <item>"水曜日"</item>
+    <item>"木曜日"</item>
+    <item>"金曜日"</item>
+    <item>"土曜日"</item>
+    <item>"日曜日"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"(月)"</item>
+    <item>"(火)"</item>
+    <item>"(水)"</item>
+    <item>"(木)"</item>
+    <item>"(金)"</item>
+    <item>"(土)"</item>
+    <item>"(日)"</item>
+  </string-array>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
new file mode 100644 (file)
index 0000000..a4ecc99
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"알람 시계"</string>
+    <string name="add_alarm">"알람 추가"</string>
+    <string name="delete_alarm">"알람 삭제"</string>
+    <string name="delete_alarm_confirm">"알람이 삭제됩니다."</string>
+    <string name="show_clock">"시계 표시"</string>
+    <string name="hide_clock">"시계 숨기기"</string>
+    <string name="set_alarm">"알람 설정"</string>
+    <string name="enable">"알람 켜기"</string>
+    <string name="alarm_vibrate">"진동"</string>
+    <string name="alarm_repeat">"반복"</string>
+    <string name="alert">"벨소리"</string>
+    <string name="time">"시간"</string>
+    <string name="alert_title">"알람"</string>
+    <string name="alarm_alert_dismiss_text">"해제"</string>
+    <string name="alarm_alert_alert_silenced">"<xliff:g id="MINUTES">%d</xliff:g>분 후에 알람이 꺼집니다."</string>
+    <string name="alarm_alert_snooze_text">"스누즈"</string>
+    <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g>분 동안 스누즈"</string>
+    <string name="alarm_alert_snooze_not_set">"스누즈 설정되지 않음. <xliff:g id="TIME">%s</xliff:g>에 다음 알람이 설정되어 있음."</string>
+    <string name="alarm_set">"이 알람은 지금부터 <xliff:g id="TIME_DELTA">%s</xliff:g> 동안 설정됩니다."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1일"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g>일"</string>
+    <string name="hour">"1시간"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g>시간"</string>
+    <string name="and">" 및 "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"1분 미만"</string>
+    <string name="minute">"1분"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g>분"</string>
+    <string name="am">"am"</string>
+    <string name="pm">"pm"</string>
+    <string name="every_day">"매일"</string>
+    <string name="never">"안 함"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"표시할 시계를 선택하세요."</string>
+    <string name="error">"알람이 설정되지 않음"</string>
+    <string name="dberror">"죄송합니다. 알람을 설정할 수 없습니다."</string>
+    <string name="analog_gadget">"아날로그 시계"</string>
+  <string-array name="days_of_week">
+    <item>"월요일"</item>
+    <item>"화요일"</item>
+    <item>"수요일"</item>
+    <item>"목요일"</item>
+    <item>"금요일"</item>
+    <item>"토요일"</item>
+    <item>"일요일"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"월"</item>
+    <item>"화"</item>
+    <item>"수"</item>
+    <item>"목"</item>
+    <item>"금"</item>
+    <item>"토"</item>
+    <item>"일"</item>
+  </string-array>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
new file mode 100644 (file)
index 0000000..46f1ad7
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Alarm"</string>
+    <string name="add_alarm">"Legg til alarm"</string>
+    <string name="delete_alarm">"Slett alarm"</string>
+    <string name="delete_alarm_confirm">"Denne alarmen vil bli slettet."</string>
+    <string name="show_clock">"Vis klokke"</string>
+    <string name="hide_clock">"Fjern klokke"</string>
+    <string name="set_alarm">"Sett alarm"</string>
+    <string name="enable">"Slå på alarm"</string>
+    <string name="alarm_vibrate">"Vibrer"</string>
+    <string name="alarm_repeat">"Gjenta"</string>
+    <string name="alert">"Ringetone"</string>
+    <string name="time">"Tidspunkt"</string>
+    <string name="alert_title">"Alarm"</string>
+    <string name="alarm_alert_dismiss_text">"OK"</string>
+    <string name="alarm_alert_alert_silenced">"Alarmen ble stilnet etter <xliff:g id="MINUTES">%d</xliff:g> minutter"</string>
+    <string name="alarm_alert_snooze_text">"Slumre"</string>
+    <string name="alarm_alert_snooze_set">"Slumrer i <xliff:g id="MINUTES">%d</xliff:g> minutter."</string>
+    <string name="alarm_alert_snooze_not_set">"Slumrer ikke -- neste alarm vil gå av <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"Alarmen vil gå av <xliff:g id="TIME_DELTA">%s</xliff:g> fra nå."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"en dag"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dager"</string>
+    <string name="hour">"en time"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> timer"</string>
+    <string name="and">" og "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"mindre enn et minutt"</string>
+    <string name="minute">"et minutt"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minutter"</string>
+    <string name="am">"am"</string>
+    <string name="pm">"pm"</string>
+    <string name="every_day">"hver dag"</string>
+    <string name="never">"Aldri"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Velg klokken som skal vises."</string>
+    <string name="error">"Alarmen ble ikke satt"</string>
+    <string name="dberror">"Beklager, kunne ikke sette alarmen."</string>
+    <string name="analog_gadget">"Analog klokke"</string>
+  <string-array name="days_of_week">
+    <item>"Mandag"</item>
+    <item>"Tirsdag"</item>
+    <item>"Onsdag"</item>
+    <item>"Torsdag"</item>
+    <item>"Fredag"</item>
+    <item>"Lørdag"</item>
+    <item>"Søndag"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"man"</item>
+    <item>"tir"</item>
+    <item>"ons"</item>
+    <item>"tor"</item>
+    <item>"fre"</item>
+    <item>"lør"</item>
+    <item>"søn"</item>
+  </string-array>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
new file mode 100644 (file)
index 0000000..049a921
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Wekker"</string>
+    <string name="add_alarm">"Alarm toevoegen"</string>
+    <string name="delete_alarm">"Alarm verwijderen"</string>
+    <string name="delete_alarm_confirm">"Dit alarm wordt verwijderd."</string>
+    <string name="show_clock">"Klok weergeven"</string>
+    <string name="hide_clock">"Klok verbergen"</string>
+    <string name="set_alarm">"Alarm instellen"</string>
+    <string name="enable">"Alarm inschakelen"</string>
+    <string name="alarm_vibrate">"Trillen"</string>
+    <string name="alarm_repeat">"Herhalen"</string>
+    <string name="alert">"Beltoon"</string>
+    <string name="time">"Tijd"</string>
+    <string name="alert_title">"Alarm"</string>
+    <string name="alarm_alert_dismiss_text">"Negeren"</string>
+    <string name="alarm_alert_alert_silenced">"Alarm gaat uit na <xliff:g id="MINUTES">%d</xliff:g> minuten"</string>
+    <string name="alarm_alert_snooze_text">"Snooze"</string>
+    <string name="alarm_alert_snooze_set">"Snooze is ingesteld op <xliff:g id="MINUTES">%d</xliff:g> minuten."</string>
+    <string name="alarm_alert_snooze_not_set">"Snooze is niet ingesteld - volgende alarm is ingesteld op <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"Dit alarm is ingesteld op <xliff:g id="TIME_DELTA">%s</xliff:g> vanaf nu."</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 dag"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dagen"</string>
+    <string name="hour">"1 uur"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> uur"</string>
+    <string name="and">" en "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"minder dan 1 minuut"</string>
+    <string name="minute">"1 minuut"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> minuten"</string>
+    <string name="am">"am"</string>
+    <string name="pm">"pm"</string>
+    <string name="every_day">"elke dag"</string>
+    <string name="never">"Nooit"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Selecteer een klok die u wilt weergeven."</string>
+    <string name="error">"Alarm is niet ingesteld"</string>
+    <string name="dberror">"Het alarm kan niet worden ingesteld."</string>
+    <string name="analog_gadget">"Analoge klok"</string>
+  <string-array name="days_of_week">
+    <item>"Maandag"</item>
+    <item>"Dinsdag"</item>
+    <item>"Woensdag"</item>
+    <item>"Donderdag"</item>
+    <item>"Vrijdag"</item>
+    <item>"Zaterdag"</item>
+    <item>"Zondag"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Ma"</item>
+    <item>"Di"</item>
+    <item>"Wo"</item>
+    <item>"Do"</item>
+    <item>"Vr"</item>
+    <item>"Za"</item>
+    <item>"Zo"</item>
+  </string-array>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
new file mode 100644 (file)
index 0000000..b441993
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Budzik"</string>
+    <string name="add_alarm">"Dodaj alarm"</string>
+    <string name="delete_alarm">"Usuń alarm"</string>
+    <string name="delete_alarm_confirm">"Ten zegar zostanie usunięty."</string>
+    <string name="show_clock">"Pokaż zegar"</string>
+    <string name="hide_clock">"Ukryj zegar"</string>
+    <string name="set_alarm">"Ustaw alarm"</string>
+    <string name="enable">"Włącz alarm"</string>
+    <string name="alarm_vibrate">"Wibracje"</string>
+    <string name="alarm_repeat">"Powtarzanie"</string>
+    <string name="alert">"Dzwonek"</string>
+    <string name="time">"Godzina"</string>
+    <string name="alert_title">"Alarm"</string>
+    <string name="alarm_alert_dismiss_text">"Zamknij"</string>
+    <string name="alarm_alert_alert_silenced">"Alarm jest wyciszany po <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+    <string name="alarm_alert_snooze_text">"Drzemka"</string>
+    <string name="alarm_alert_snooze_set">"Drzemka przez <xliff:g id="MINUTES">%d</xliff:g> min."</string>
+    <string name="alarm_alert_snooze_not_set">"Nie ustawiono drzemki – następny alarm: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"Ustawiony alarm zadzwoni za <xliff:g id="TIME_DELTA">%s</xliff:g>"</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 dzień"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> dni"</string>
+    <string name="hour">"1 godz."</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> godz."</string>
+    <string name="and">" oraz "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"mniej niż 1 min"</string>
+    <string name="minute">"1 min"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> min"</string>
+    <string name="am">"AM"</string>
+    <string name="pm">"PM"</string>
+    <string name="every_day">"codziennie"</string>
+    <string name="never">"Nigdy"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Wybierz wyświetlany zegar."</string>
+    <string name="error">"Alarm nieustawiony"</string>
+    <string name="dberror">"Niestety, nie można ustawić alarmu."</string>
+    <string name="analog_gadget">"Zegar analogowy"</string>
+  <string-array name="days_of_week">
+    <item>"poniedziałek"</item>
+    <item>"wtorek"</item>
+    <item>"środa"</item>
+    <item>"czwartek"</item>
+    <item>"piątek"</item>
+    <item>"sobota"</item>
+    <item>"niedziela"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Pn"</item>
+    <item>"Wt"</item>
+    <item>"Śr"</item>
+    <item>"Cz"</item>
+    <item>"Pt"</item>
+    <item>"So"</item>
+    <item>"Ndz"</item>
+  </string-array>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
new file mode 100644 (file)
index 0000000..8b93a91
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"Будильник"</string>
+    <string name="add_alarm">"Добавить будильник"</string>
+    <string name="delete_alarm">"Удалить будильник"</string>
+    <string name="delete_alarm_confirm">"Сигнал будет удален."</string>
+    <string name="show_clock">"Показать часы"</string>
+    <string name="hide_clock">"Скрыть часы"</string>
+    <string name="set_alarm">"Установить будильник"</string>
+    <string name="enable">"Включить будильник"</string>
+    <string name="alarm_vibrate">"Вибрация"</string>
+    <string name="alarm_repeat">"Повтор"</string>
+    <string name="alert">"Мелодия звонка"</string>
+    <string name="time">"Время"</string>
+    <string name="alert_title">"Будильник"</string>
+    <string name="alarm_alert_dismiss_text">"Закрыть"</string>
+    <string name="alarm_alert_alert_silenced">"Будильник отключается через <xliff:g id="MINUTES">%d</xliff:g> минут(ы)"</string>
+    <string name="alarm_alert_snooze_text">"Отсрочка"</string>
+    <string name="alarm_alert_snooze_set">"Отсрочка на <xliff:g id="MINUTES">%d</xliff:g> минут(ы)."</string>
+    <string name="alarm_alert_snooze_not_set">"Отсрочка не установлена – следующий будильник установлен на <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"Будильник прозвонит через <xliff:g id="TIME_DELTA">%s</xliff:g>"</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 день"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> дня(ей)"</string>
+    <string name="hour">"1 час"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> часа(ов)"</string>
+    <string name="and">" и "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"менее 1 минуты"</string>
+    <string name="minute">"1 минута"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> минут(ы)"</string>
+    <string name="am">"до полудня"</string>
+    <string name="pm">"после полудня"</string>
+    <string name="every_day">"ежедневно"</string>
+    <string name="never">"Никогда"</string>
+    <string name="day_concat">", "</string>
+    <string name="clock_instructions">"Выберите часы для отображения"</string>
+    <string name="error">"Будильник не установлен"</string>
+    <string name="dberror">"К сожалению, установить будильник не удалось."</string>
+    <string name="analog_gadget">"Часы со стрелками"</string>
+  <string-array name="days_of_week">
+    <item>"Понедельник"</item>
+    <item>"Вторник"</item>
+    <item>"Среда"</item>
+    <item>"Четверг"</item>
+    <item>"Пятница"</item>
+    <item>"Суббота"</item>
+    <item>"Воскресенье"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"Пн"</item>
+    <item>"Вт"</item>
+    <item>"Ср"</item>
+    <item>"Чт"</item>
+    <item>"Пт"</item>
+    <item>"Сб"</item>
+    <item>"Вс"</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
new file mode 100644 (file)
index 0000000..a84de73
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"闹钟时钟"</string>
+    <string name="add_alarm">"添加闹钟"</string>
+    <string name="delete_alarm">"取消闹钟"</string>
+    <string name="delete_alarm_confirm">"将会删除此警报。"</string>
+    <string name="show_clock">"显示时钟"</string>
+    <string name="hide_clock">"隐藏时钟"</string>
+    <string name="set_alarm">"设置闹钟"</string>
+    <string name="enable">"开启闹钟"</string>
+    <string name="alarm_vibrate">"振动"</string>
+    <string name="alarm_repeat">"重复"</string>
+    <string name="alert">"铃声"</string>
+    <string name="time">"时间"</string>
+    <string name="alert_title">"闹钟"</string>
+    <string name="alarm_alert_dismiss_text">"取消"</string>
+    <string name="alarm_alert_alert_silenced">"闹钟在 <xliff:g id="MINUTES">%d</xliff:g> 分钟后静音"</string>
+    <string name="alarm_alert_snooze_text">"再响"</string>
+    <string name="alarm_alert_snooze_set">"<xliff:g id="MINUTES">%d</xliff:g> 分钟后再响。"</string>
+    <string name="alarm_alert_snooze_not_set">"未设置再响 - 下次闹钟设置在 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"该闹钟设置为从现在起 <xliff:g id="TIME_DELTA">%s</xliff:g> 后再提醒。"</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 天"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> 天"</string>
+    <string name="hour">"1 小时"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> 小时"</string>
+    <string name="and">" 和 "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"短于 1 分钟"</string>
+    <string name="minute">"1 分钟"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> 分钟"</string>
+    <string name="am">"上午"</string>
+    <string name="pm">"下午"</string>
+    <string name="every_day">"每天"</string>
+    <string name="never">"永不"</string>
+    <string name="day_concat">"、 "</string>
+    <string name="clock_instructions">"选择要显示的时钟。"</string>
+    <string name="error">"未设置闹钟"</string>
+    <string name="dberror">"抱歉,无法设置该闹钟。"</string>
+    <string name="analog_gadget">"模拟时钟"</string>
+  <string-array name="days_of_week">
+    <item>"周一"</item>
+    <item>"周二"</item>
+    <item>"周三"</item>
+    <item>"周四"</item>
+    <item>"周五"</item>
+    <item>"周六"</item>
+    <item>"周日"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"周一"</item>
+    <item>"周二"</item>
+    <item>"周三"</item>
+    <item>"周四"</item>
+    <item>"周五"</item>
+    <item>"周六"</item>
+    <item>"周日"</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
new file mode 100644 (file)
index 0000000..04b08fe
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label">"鬧鐘"</string>
+    <string name="add_alarm">"新增鬧鐘"</string>
+    <string name="delete_alarm">"刪除鬧鐘"</string>
+    <string name="delete_alarm_confirm">"將刪除此鬧鐘。"</string>
+    <string name="show_clock">"顯示時鐘"</string>
+    <string name="hide_clock">"隱藏時鐘"</string>
+    <string name="set_alarm">"設定鬧鐘"</string>
+    <string name="enable">"開啟鬧鐘"</string>
+    <string name="alarm_vibrate">"震動"</string>
+    <string name="alarm_repeat">"重複"</string>
+    <string name="alert">"鈴聲"</string>
+    <string name="time">"時間"</string>
+    <string name="alert_title">"鬧鐘"</string>
+    <string name="alarm_alert_dismiss_text">"關閉"</string>
+    <string name="alarm_alert_alert_silenced">"鬧鐘 <xliff:g id="MINUTES">%d</xliff:g> 分鐘後靜音"</string>
+    <string name="alarm_alert_snooze_text">"貪睡"</string>
+    <string name="alarm_alert_snooze_set">"再貪睡 <xliff:g id="MINUTES">%d</xliff:g> 分鐘。"</string>
+    <string name="alarm_alert_snooze_not_set">"未設定貪睡鬧鐘 -- 下一次鬧鐘時間為 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="alarm_set">"還有 <xliff:g id="TIME_DELTA">%s</xliff:g> 會啟動鬧鐘。"</string>
+    <!-- no translation found for combiner (3170916241487451546) -->
+    <skip />
+    <string name="day">"1 天"</string>
+    <string name="days">"<xliff:g id="DAYS">%s</xliff:g> 天"</string>
+    <string name="hour">"1 小時"</string>
+    <string name="hours">"<xliff:g id="HOURS">%s</xliff:g> 小時"</string>
+    <string name="and">" 又 "</string>
+    <!-- no translation found for space (5294521584675021576) -->
+    <skip />
+    <string name="subminute">"少於 1 分鐘"</string>
+    <string name="minute">"1 分鐘"</string>
+    <string name="minutes">"<xliff:g id="MINUTES">%s</xliff:g> 分鐘"</string>
+    <string name="am">"am"</string>
+    <string name="pm">"pm"</string>
+    <string name="every_day">"每天"</string>
+    <string name="never">"從不"</string>
+    <string name="day_concat">"、 "</string>
+    <string name="clock_instructions">"選取顯示的時鐘。"</string>
+    <string name="error">"鬧鐘未設定"</string>
+    <string name="dberror">"抱歉,無法設定鬧鐘。"</string>
+    <string name="analog_gadget">"類比時鐘"</string>
+  <string-array name="days_of_week">
+    <item>"星期一"</item>
+    <item>"星期二"</item>
+    <item>"星期三"</item>
+    <item>"星期四"</item>
+    <item>"星期五"</item>
+    <item>"星期六"</item>
+    <item>"星期日"</item>
+  </string-array>
+  <string-array name="days_of_week_short">
+    <item>"週一"</item>
+    <item>"週二"</item>
+    <item>"週三"</item>
+    <item>"週四"</item>
+    <item>"週五"</item>
+    <item>"週六"</item>
+    <item>"週日"</item>
+  </string-array>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644 (file)
index 0000000..e61b6c3
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<resources>
+    <color name="ampm_off">#ff404040</color>
+    <color name="ampm_on">#ffffffff</color>
+
+    <color name="white">#ffffffff</color>
+    <color name="red">#ffee0000</color>
+    <color name="ltgrey">#ffe0e0e0</color>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644 (file)
index 0000000..30b8fe2
--- /dev/null
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- -->
+    <!-- Label shown on launcher icon -->
+    <string name="app_label">Alarm Clock</string>
+
+    <!-- Menu item on Alarm Clock screen: Add alarm -->
+    <string name="add_alarm">Add alarm</string>
+
+    <!-- Context Menu Item on Alarm Settings screen: Delete alarm -->
+    <string name="delete_alarm">Delete alarm</string>
+
+    <!-- Delete alarm confirmation dialog message. -->
+    <string name="delete_alarm_confirm">This alarm will be deleted.</string>
+
+    <!-- Menu item on Alarm Clock screen: Show clock -->
+    <string name="show_clock">Show clock</string>
+
+    <!-- Menu item on Alarm Clock screen: Hide clock -->
+    <string name="hide_clock">Hide clock</string>
+
+    <!-- Preference category on Alarm Settings screen: Set alarm -->
+    <string name="set_alarm">Set alarm</string>
+
+    <!-- Setting labels on Set alarm screen: Enable alarm -->
+    <string name="enable">Turn on alarm</string>
+
+    <!-- Setting labels on Set alarm screen: Vibration on or off -->
+    <string name="alarm_vibrate">Vibrate</string>
+
+    <!-- Setting labels on Set alarm screen: Repeat -->
+    <string name="alarm_repeat">Repeat</string>
+
+    <!-- Setting labels on Set alarm screen: Select alarm ringtone  -->
+    <string name="alert">Ringtone</string>
+
+    <!-- Setting labels on Set alarm screen: Set time  -->
+    <string name="time">Time</string>
+
+
+    <!-- Title of the alarm alert -->
+    <string name="alert_title">Alarm</string>
+    
+    <!-- Button labels on the alarm dialog: Dismiss -->
+    <string name="alarm_alert_dismiss_text">Dismiss</string>
+
+    <!-- Alarm Alert screen: this message is shown after an alarm rung
+         unattended for a number of minutes.  It tells the user that
+         the alarm has been silenced.-->
+    <string name="alarm_alert_alert_silenced">Alarm silenced after <xliff:g id="minutes">%d</xliff:g> minutes</string>
+
+    <!-- Button labels on the alarm dialog: Snooze -->
+    <string name="alarm_alert_snooze_text">Snooze</string>
+
+    <!-- Toast that appears after Alarm is snoozed from the Alarm
+         dialog. Says the alarm will snooze for xxx minutes.  -->
+    <string name="alarm_alert_snooze_set">Snoozing for <xliff:g id="minutes">%d</xliff:g> minutes.</string>
+
+    <!-- Toast that appears after Alarm is snoozed from the Alarm
+         dialog. Shown if snooze cannot be set because the next alarm
+         would fire before the snooze alrm.  "Snooze not set - next
+         alarm set for xxx."  -->
+    <string name="alarm_alert_snooze_not_set">Snooze not set -- next alarm set for <xliff:g id="time">%s</xliff:g></string>
+
+
+    <!-- Alarm confirmation toast: Describes how long from now until
+         alarm fires -->
+    <string name="alarm_set">This alarm is set for <xliff:g id="time_delta">%s</xliff:g> from now.</string>
+
+    <!-- Alarm confirmation toast: A combiner that orders the segments
+         that follow -->
+    <string name="combiner"><xliff:g id="xxx">%1$s</xliff:g><xliff:g id="xxx">%2$s</xliff:g><xliff:g id="xxx">%3$s</xliff:g><xliff:g id="xxx">%4$s</xliff:g><xliff:g id="xxx">%5$s</xliff:g></string>
+
+    <!-- Alarm confirmation toast: singular day -->
+    <string name="day">"1 day"</string>
+
+    <!-- Alarm confirmation toast: plural days -->
+    <string name="days">"<xliff:g id="days">%s</xliff:g> days"</string>
+
+    <!-- Alarm confirmation toast: singular hour -->
+    <string name="hour">1 hour</string>
+
+    <!-- Alarm confirmation toast: plural hours -->
+    <string name="hours"><xliff:g id="hours">%s</xliff:g> hours</string>
+
+    <!-- Alarm confirmation toast: "and" to join hours and minutes -->
+    <string name="and">" and "</string>
+
+    <!-- Alarm confirmation toast: space  -->
+    <string name="space">" "</string>
+
+    <!-- Alarm confirmation toast: time less than one minute  -->
+    <string name="subminute">"less than 1 minute"</string>
+
+    <!-- Alarm confirmation toast: singular minute  -->
+    <string name="minute">"1 minute"</string>
+
+    <!-- Alarm confirmation toast: plural minutes  -->
+    <string name="minutes">"<xliff:g id="minutes">%s</xliff:g> minutes"</string>
+
+    <!-- Alarm confirmation toast: Ante Meridiem, or am  -->
+    <string name="am">am</string>
+
+    <!-- Alarm confirmation toast: Post Meridiem, or pm  -->
+    <string name="pm">pm</string>
+
+    <!-- Repeat options that appear under an alarm on main Alarm Clock
+         screen to identify repetition schedule: special case for when
+         the alarm is set to repeat every day -->
+    <string name="every_day">every day</string>
+
+    <!-- Repeat options that appear under an alarm on main Alarm Clock
+         screen to identify repetition schedule: special case for when
+         the alarm is set to never repeat -->
+    <string name="never">Never</string>
+
+    <!-- Repeat options that appear under an alarm on main Alarm Clock
+         screen to identify repetition schedule: concatenate days with
+         this character, i.e. "Mon, Tue, Wed" -->
+    <string name="day_concat">", "</string>
+
+    <!-- Appears at the top of the Clock Picker screen: Tell user to
+         select a clock to display -->
+    <string name="clock_instructions">Select a clock to display.</string>
+
+    <!-- Error dialog title: Alarm not set.  Appears only on critical
+         failure -->
+    <string name="error">Alarm not set</string>
+
+    <!-- Error dialog message.  Appears only on critical
+         failure -->
+    <string name="dberror">Sorry, the alarm could not be set.</string>
+
+    <!-- Label for analog clock gadget, shown in list of all gadgets -->
+    <string name="analog_gadget">Analog clock</string>
+
+    <!-- Days of week -->
+    <string-array name="days_of_week">
+        <!-- Day of week: Monday -->
+        <item>Monday</item>
+        <!-- Day of week: Tuesday -->
+        <item>Tuesday</item>
+        <!-- Day of week: Wednesday -->
+        <item>Wednesday</item>
+        <!-- Day of week: Thursday -->
+        <item>Thursday</item>
+        <!-- Day of week: Friday  -->
+        <item>Friday</item>
+        <!-- Day of week: Saturday -->
+        <item>Saturday</item>
+        <!-- Day of week: Sunday -->
+        <item>Sunday</item>
+    </string-array>
+    
+    <!-- Short Day of week  -->
+    <string-array name="days_of_week_short">
+        <!-- Short Day of week: Mon -->
+        <item>Mon</item>
+        <!-- Short Day of week: Tue -->
+        <item>Tue</item>
+        <!-- Short Day of week: Wed -->
+        <item>Wed</item>
+        <!-- Short Day of week: Thu -->
+        <item>Thu</item>
+        <!-- Short Day of week: Fri  -->
+        <item>Fri</item>
+        <!-- Short Day of week: Sat -->
+        <item>Sat</item>
+        <!-- Short Day of week: Sun -->
+        <item>Sun</item>
+    </string-array>
+
+</resources>
+
+
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644 (file)
index 0000000..c00c6f5
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<resources>
+    <style name="analogClock">
+        <item name="android:layout_width">fill_parent</item>
+        <item name="android:layout_height">fill_parent</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+    </style>
+</resources>
diff --git a/res/xml/alarm_prefs.xml b/res/xml/alarm_prefs.xml
new file mode 100644 (file)
index 0000000..bdcf6b7
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/set_alarm">
+    <CheckBoxPreference android:key="on" 
+        android:title="@string/enable"/>
+    <Preference android:key="time" 
+        android:title="@string/time"/>
+    <com.android.alarmclock.AlarmPreference
+        android:key="alarm" 
+        android:title="@string/alert"
+        android:ringtoneType="alarm"
+        android:showDefault="false"
+        android:showSilent="false" />
+    <CheckBoxPreference android:key="vibrate" 
+        android:title="@string/alarm_vibrate"/>
+    <com.android.alarmclock.RepeatPreference
+        android:key="setRepeat" 
+        android:title="@string/alarm_repeat"
+        android:entries="@array/days_of_week"
+        android:entryValues="@array/days_of_week"/>
+</PreferenceScreen>
diff --git a/res/xml/analog_gadget.xml b/res/xml/analog_gadget.xml
new file mode 100644 (file)
index 0000000..72724ec
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="146dip"
+    android:minHeight="146dip"
+    android:updatePeriodMillis="0"
+    android:initialLayout="@layout/analog_gadget"
+    >
+</gadget-provider>
diff --git a/src/com/android/alarmclock/AlarmAlert.java b/src/com/android/alarmclock/AlarmAlert.java
new file mode 100644 (file)
index 0000000..eefd5bb
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.Toast;
+import android.widget.TextView;
+
+import java.util.Calendar;
+
+/**
+ * Alarm Clock alarm alert: pops visible indicator and plays alarm
+ * tone
+ */
+public class AlarmAlert extends Activity {
+
+    private static final int SNOOZE_MINUTES = 10;
+    private static final int UNKNOWN = 0;
+    private static final int SNOOZE = 1;
+    private static final int DISMISS = 2;
+    private static final int KILLED = 3;
+
+    private KeyguardManager mKeyguardManager;
+    private KeyguardManager.KeyguardLock mKeyguardLock = null;
+    private Button mSnoozeButton;
+    private int mState = UNKNOWN;
+
+    private AlarmKlaxon mKlaxon;
+    private int mAlarmId;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        /* FIXME Intentionally verbose: always log this until we've
+           fully debugged the app failing to start up */
+        Log.v("AlarmAlert.onCreate()");
+
+        mKlaxon = AlarmKlaxon.getInstance();
+
+        // Popup alert over black screen
+        WindowManager.LayoutParams lp = getWindow().getAttributes();
+        lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+        lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        // XXX DO NOT COPY THIS!!!  THIS IS BOGUS!  Making an activity have
+        // a system alert type is completely broken, because the activity
+        // manager will still hide/show it as if it is part of the normal
+        // activity stack.  If this is really what you want and you want it
+        // to work correctly, you should create and show your own custom window.
+        lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+        lp.token = null;
+        getWindow().setAttributes(lp);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+
+        mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+
+        mAlarmId = getIntent().getIntExtra(Alarms.ID, -1);
+
+        /* allow next alarm to trigger while this activity is
+           active */
+        Alarms.disableSnoozeAlert(AlarmAlert.this);
+        Alarms.disableAlert(AlarmAlert.this, mAlarmId);
+        Alarms.setNextAlert(this);
+
+        mKlaxon.setKillerCallback(new AlarmKlaxon.KillerCallback() {
+            public void onKilled() {
+                if (Log.LOGV) Log.v("onKilled()");
+                updateSilencedText();
+
+                /* don't allow snooze */
+                mSnoozeButton.setEnabled(false);
+
+                // Dismiss the alarm but mark the state as killed so if the
+                // config changes, we show the silenced message and disable
+                // snooze.
+                dismiss();
+                mState = KILLED;
+            }
+        });
+
+        updateLayout();
+    }
+
+    private void updateSilencedText() {
+        TextView silenced = (TextView) findViewById(R.id.silencedText);
+        silenced.setText(getString(R.string.alarm_alert_alert_silenced,
+                    AlarmKlaxon.ALARM_TIMEOUT_SECONDS / 60));
+        silenced.setVisibility(View.VISIBLE);
+    }
+
+    private void updateLayout() {
+        setContentView(R.layout.alarm_alert);
+
+        /* set clock face */
+        LayoutInflater mFactory = LayoutInflater.from(this);
+        SharedPreferences settings =
+                getSharedPreferences(AlarmClock.PREFERENCES, 0);
+        int face = settings.getInt(AlarmClock.PREF_CLOCK_FACE, 0);
+        if (face < 0 || face >= AlarmClock.CLOCKS.length) {
+            face = 0;
+        }
+        View clockLayout =
+                (View) mFactory.inflate(AlarmClock.CLOCKS[face], null);
+        ViewGroup clockView = (ViewGroup) findViewById(R.id.clockView);
+        clockView.addView(clockLayout);
+        if (clockLayout instanceof DigitalClock) {
+            ((DigitalClock) clockLayout).setAnimate();
+        }
+
+        /* snooze behavior: pop a snooze confirmation view, kick alarm
+           manager. */
+        mSnoozeButton = (Button) findViewById(R.id.snooze);
+        mSnoozeButton.requestFocus();
+        // If this was a configuration change, keep the silenced text if the
+        // alarm was killed.
+        if (mState == KILLED) {
+            updateSilencedText();
+            mSnoozeButton.setEnabled(false);
+        } else {
+            mSnoozeButton.setOnClickListener(new Button.OnClickListener() {
+                public void onClick(View v) {
+                    snooze();
+                    finish();
+                }
+            });
+        }
+
+        /* dismiss button: close notification */
+        findViewById(R.id.dismiss).setOnClickListener(
+                new Button.OnClickListener() {
+                    public void onClick(View v) {
+                        dismiss();
+                        finish();
+                    }
+                });
+    }
+
+    // Attempt to snooze this alert.
+    private void snooze() {
+        if (mState != UNKNOWN) {
+            return;
+        }
+        // If the next alarm is set for sooner than the snooze interval, don't
+        // snooze. Instead, toast the user that the snooze will not be set.
+        final long snoozeTime = System.currentTimeMillis()
+                + (1000 * 60 * SNOOZE_MINUTES);
+        final long nextAlarm =
+                Alarms.calculateNextAlert(AlarmAlert.this).getAlert();
+        String displayTime = null;
+        if (nextAlarm < snoozeTime) {
+            final Calendar c = Calendar.getInstance();
+            c.setTimeInMillis(nextAlarm);
+            displayTime = getString(R.string.alarm_alert_snooze_not_set,
+                    Alarms.formatTime(AlarmAlert.this, c));
+            mState = DISMISS;
+        } else {
+            Alarms.saveSnoozeAlert(AlarmAlert.this, mAlarmId, snoozeTime);
+            Alarms.setNextAlert(AlarmAlert.this);
+            displayTime = getString(R.string.alarm_alert_snooze_set,
+                    SNOOZE_MINUTES);
+            mState = SNOOZE;
+        }
+        // Intentionally log the snooze time for debugging.
+        Log.v(displayTime);
+        // Display the snooze minutes in a toast.
+        Toast.makeText(AlarmAlert.this, displayTime, Toast.LENGTH_LONG).show();
+        mKlaxon.stop(this, mState == SNOOZE);
+        releaseLocks();
+    }
+
+    // Dismiss the alarm.
+    private void dismiss() {
+        if (mState != UNKNOWN) {
+            return;
+        }
+        mState = DISMISS;
+        mKlaxon.stop(this, false);
+        releaseLocks();
+    }
+
+    /**
+     * this is called when a second alarm is triggered while a
+     * previous alert window is still active.
+     */
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        if (Log.LOGV) Log.v("AlarmAlert.OnNewIntent()");
+        mState = UNKNOWN;
+        mSnoozeButton.setEnabled(true);
+        disableKeyguard();
+
+        mAlarmId = intent.getIntExtra(Alarms.ID, -1);
+
+        /* unset silenced message */
+        TextView silenced = (TextView)findViewById(R.id.silencedText);
+        silenced.setVisibility(View.GONE);
+
+        Alarms.setNextAlert(this);
+        setIntent(intent);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (Log.LOGV) Log.v("AlarmAlert.onResume()");
+        disableKeyguard();
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        if (Log.LOGV) Log.v("AlarmAlert.onStop()");
+        // As a last resort, try to snooze if this activity is stopped.
+        snooze();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration config) {
+        super.onConfigurationChanged(config);
+        updateLayout();
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        // Do this on key down to handle a few of the system keys. Only handle
+        // the snooze and dismiss this alert if the state is unknown.
+        boolean up = event.getAction() == KeyEvent.ACTION_UP;
+        boolean dismiss = false;
+        switch (event.getKeyCode()) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            // Ignore ENDCALL because we do not receive the event if the screen
+            // is on. However, we do receive the key up for ENDCALL if the
+            // screen was off.
+            case KeyEvent.KEYCODE_ENDCALL:
+                break;
+            // Volume keys dismiss the alarm
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                dismiss = true;
+            // All other keys will snooze the alarm
+            default:
+                // Check for UNKNOWN here so that we intercept both key events
+                // and prevent the volume keys from triggering their default
+                // behavior.
+                if (mState == UNKNOWN && up) {
+                    if (dismiss) {
+                        dismiss();
+                    } else {
+                        snooze();
+                    }
+                    finish();
+                }
+                return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    private synchronized void enableKeyguard() {
+        if (mKeyguardLock != null) {
+            mKeyguardLock.reenableKeyguard();
+            mKeyguardLock = null;
+        }
+    }
+
+    private synchronized void disableKeyguard() {
+        if (mKeyguardLock == null) {
+            mKeyguardLock = mKeyguardManager.newKeyguardLock(Log.LOGTAG);
+            mKeyguardLock.disableKeyguard();
+        }
+    }
+
+    /**
+     * release wake and keyguard locks
+     */
+    private synchronized void releaseLocks() {
+        AlarmAlertWakeLock.release();
+        enableKeyguard();
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmAlertWakeLock.java b/src/com/android/alarmclock/AlarmAlertWakeLock.java
new file mode 100644 (file)
index 0000000..083996e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.content.Context;
+import android.os.PowerManager;
+
+/**
+ * Hold a wakelock that can be acquired in the AlarmReceiver and
+ * released in the AlarmAlert activity
+ */
+class AlarmAlertWakeLock {
+
+    private static PowerManager.WakeLock sWakeLock;
+
+    static void acquire(Context context) {
+        if (sWakeLock != null) {
+            sWakeLock.release();
+        }
+
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+        sWakeLock = pm.newWakeLock(
+                PowerManager.FULL_WAKE_LOCK |
+                PowerManager.ACQUIRE_CAUSES_WAKEUP |
+                PowerManager.ON_AFTER_RELEASE, Log.LOGTAG);
+        sWakeLock.acquire();
+    }
+
+    static void release() {
+        if (Log.LOGV) Log.v("AlarmAlertWakeLock release");
+        if (sWakeLock != null) {
+            sWakeLock.release();
+            sWakeLock = null;
+        }
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmClock.java b/src/com/android/alarmclock/AlarmClock.java
new file mode 100644 (file)
index 0000000..6230d16
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.CheckBox;
+
+import java.util.Calendar;
+
+/**
+ * AlarmClock application.
+ */
+public class AlarmClock extends Activity {
+
+    final static String PREFERENCES = "AlarmClock";
+    final static int SET_ALARM = 1;
+    final static String PREF_CLOCK_FACE = "face";
+    final static String PREF_SHOW_CLOCK = "show_clock";
+
+    /** Cap alarm count at this number */
+    final static int MAX_ALARM_COUNT = 12;
+
+    /** This must be false for production.  If true, turns on logging,
+        test code, etc. */
+    final static boolean DEBUG = false;
+
+    private SharedPreferences mPrefs;
+    private LayoutInflater mFactory;
+    private ViewGroup mClockLayout;
+    private View mClock = null;
+    private MenuItem mAddAlarmItem;
+    private MenuItem mToggleClockItem;
+    private ListView mAlarmsList;
+    private Cursor mCursor;
+
+    /**
+     * Which clock face to show
+     */
+    private int mFace = -1;
+
+    /*
+     * FIXME: it would be nice for this to live in an xml config file.
+     */
+    final static int[] CLOCKS = {
+        R.layout.clock_basic_bw,
+        R.layout.clock_googly,
+        R.layout.clock_droid2,
+        R.layout.clock_droids,
+        R.layout.digital_clock
+    };
+
+    private class AlarmTimeAdapter extends CursorAdapter {
+        public AlarmTimeAdapter(Context context, Cursor cursor) {
+            super(context, cursor);
+        }
+
+        public View newView(Context context, Cursor cursor, ViewGroup parent) {
+            View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
+            DigitalClock digitalClock = (DigitalClock)ret.findViewById(R.id.digitalClock);
+            digitalClock.setLive(false);
+            if (Log.LOGV) Log.v("newView " + cursor.getPosition());
+            return ret;
+        }
+
+        public void bindView(View view, Context context, Cursor cursor) {
+            final int id = cursor.getInt(Alarms.AlarmColumns.ALARM_ID_INDEX);
+            final int hour = cursor.getInt(Alarms.AlarmColumns.ALARM_HOUR_INDEX);
+            final int minutes = cursor.getInt(Alarms.AlarmColumns.ALARM_MINUTES_INDEX);
+            final Alarms.DaysOfWeek daysOfWeek = new Alarms.DaysOfWeek(
+                    cursor.getInt(Alarms.AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX));
+            final boolean enabled = cursor.getInt(Alarms.AlarmColumns.ALARM_ENABLED_INDEX) == 1;
+
+            CheckBox onButton = (CheckBox)view.findViewById(R.id.alarmButton);
+            onButton.setChecked(enabled);
+            onButton.setOnClickListener(new OnClickListener() {
+                    public void onClick(View v) {
+                        boolean isChecked = ((CheckBox) v).isChecked();
+                        Alarms.enableAlarm(AlarmClock.this, id, isChecked);
+                        if (isChecked) {
+                            SetAlarm.popAlarmSetToast(
+                                    AlarmClock.this, hour, minutes, daysOfWeek);
+                        }
+                    }
+            });
+
+            DigitalClock digitalClock = (DigitalClock)view.findViewById(R.id.digitalClock);
+            if (Log.LOGV) Log.v("bindView " + cursor.getPosition() + " " + id + " " + hour +
+                                ":" + minutes + " " + daysOfWeek.toString(context, true) + " dc " + digitalClock);
+
+            digitalClock.setOnClickListener(new OnClickListener() {
+                    public void onClick(View v) {
+                        if (true) {
+                            Intent intent = new Intent(AlarmClock.this, SetAlarm.class);
+                            intent.putExtra(Alarms.ID, id);
+                            startActivityForResult(intent, SET_ALARM);
+                        } else {
+                            // TESTING: immediately pop alarm
+                            Intent fireAlarm = new Intent(AlarmClock.this, AlarmAlert.class);
+                            fireAlarm.putExtra(Alarms.ID, id);
+                            fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                            startActivity(fireAlarm);
+                        }
+                    }
+                });
+
+            // set the alarm text
+            final Calendar c = Calendar.getInstance();
+            c.set(Calendar.HOUR_OF_DAY, hour);
+            c.set(Calendar.MINUTE, minutes);
+            digitalClock.updateTime(c);
+            TextView daysOfWeekView = (TextView) digitalClock.findViewById(R.id.daysOfWeek);
+            daysOfWeekView.setText(daysOfWeek.toString(AlarmClock.this, false));
+
+            // Build context menu
+            digitalClock.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
+                    public void onCreateContextMenu(ContextMenu menu, View view,
+                                                    ContextMenuInfo menuInfo) {
+                        menu.setHeaderTitle(Alarms.formatTime(AlarmClock.this, c));
+                        MenuItem deleteAlarmItem = menu.add(0, id, 0, R.string.delete_alarm);
+                    }
+                });
+        }
+    };
+
+    @Override
+    public boolean onContextItemSelected(final MenuItem item) {
+        // Confirm that the alarm will be deleted.
+        new AlertDialog.Builder(this)
+                .setTitle(getString(R.string.delete_alarm))
+                .setMessage(getString(R.string.delete_alarm_confirm))
+                .setPositiveButton(android.R.string.ok,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface d, int w) {
+                                Alarms.deleteAlarm(AlarmClock.this,
+                                        item.getItemId());
+                            }
+                        })
+                .setNegativeButton(android.R.string.cancel, null)
+                .show();
+        return true;
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // sanity check -- no database, no clock
+        if (getContentResolver() == null) {
+            new AlertDialog.Builder(this)
+                    .setTitle(getString(R.string.error))
+                    .setMessage(getString(R.string.dberror))
+                    .setPositiveButton(
+                            android.R.string.ok,
+                            new DialogInterface.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    finish();
+                                }
+                            })
+                    .setOnCancelListener(
+                            new DialogInterface.OnCancelListener() {
+                                public void onCancel(DialogInterface dialog) {
+                                    finish();
+                                }})
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .create().show();
+            return;
+        }
+
+        setContentView(R.layout.alarm_clock);
+        mFactory = LayoutInflater.from(this);
+        mPrefs = getSharedPreferences(PREFERENCES, 0);
+
+        mCursor = Alarms.getAlarmsCursor(getContentResolver());
+        mAlarmsList = (ListView) findViewById(R.id.alarms_list);
+        mAlarmsList.setAdapter(new AlarmTimeAdapter(this, mCursor));
+        mAlarmsList.setVerticalScrollBarEnabled(true);
+        mAlarmsList.setItemsCanFocus(true);
+
+        mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
+        mClockLayout.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    final Intent intent = new Intent(AlarmClock.this, ClockPicker.class);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivity(intent);
+                }
+            });
+
+        setClockVisibility(mPrefs.getBoolean(PREF_SHOW_CLOCK, true));
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        int face = mPrefs.getInt(PREF_CLOCK_FACE, 0);
+        if (mFace != face) {
+            if (face < 0 || face >= AlarmClock.CLOCKS.length)
+                mFace = 0;
+            else
+                mFace = face;
+            inflateClock();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        ToastMaster.cancelToast();
+        mCursor.deactivate();
+    }
+
+    protected void inflateClock() {
+        if (mClock != null) {
+            mClockLayout.removeView(mClock);
+        }
+        mClock = mFactory.inflate(CLOCKS[mFace], null);
+        mClockLayout.addView(mClock, 0);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+
+        mAddAlarmItem = menu.add(0, 0, 0, R.string.add_alarm);
+        mAddAlarmItem.setIcon(android.R.drawable.ic_menu_add);
+
+        mToggleClockItem = menu.add(0, 0, 0, R.string.hide_clock);
+        mToggleClockItem.setIcon(R.drawable.ic_menu_clock_face);
+
+        return true;
+    }
+
+    /**
+     * Only allow user to add a new alarm if there are fewer than
+     * MAX_ALARM_COUNT
+     */
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        mAddAlarmItem.setVisible(mAlarmsList.getChildCount() < MAX_ALARM_COUNT);
+        mToggleClockItem.setTitle(getClockVisibility() ? R.string.hide_clock :
+                                  R.string.show_clock);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item == mAddAlarmItem) {
+            Uri uri = Alarms.addAlarm(getContentResolver());
+            // FIXME: scroll to new item.  mAlarmsList.requestChildRectangleOnScreen() ?
+            String segment = uri.getPathSegments().get(1);
+            int newId = Integer.parseInt(segment);
+            if (Log.LOGV) Log.v("In AlarmClock, new alarm id = " + newId);
+            Intent intent = new Intent(AlarmClock.this, SetAlarm.class);
+            intent.putExtra(Alarms.ID, newId);
+            startActivityForResult(intent, SET_ALARM);
+            return true;
+        } else if (item == mToggleClockItem) {
+            setClockVisibility(!getClockVisibility());
+            saveClockVisibility();
+            return true;
+        }
+
+        return false;
+    }
+
+
+    private boolean getClockVisibility() {
+        return mClockLayout.getVisibility() == View.VISIBLE;
+    }
+
+    private void setClockVisibility(boolean visible) {
+        mClockLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    private void saveClockVisibility() {
+        mPrefs.edit().putBoolean(PREF_SHOW_CLOCK, getClockVisibility()).commit();
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmInitReceiver.java b/src/com/android/alarmclock/AlarmInitReceiver.java
new file mode 100644 (file)
index 0000000..77549b0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+
+public class AlarmInitReceiver extends BroadcastReceiver {
+
+    /**
+     * Sets alarm on ACTION_BOOT_COMPLETED.  Resets alarm on
+     * TIME_SET, TIMEZONE_CHANGED
+     */
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        if (Log.LOGV) Log.v("AlarmInitReceiver" + action);
+
+        if (context.getContentResolver() == null) {
+            Log.e("AlarmInitReceiver: FAILURE unable to get content resolver.  Alarms inactive.");
+            return;
+        }
+        if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+            Alarms.disableSnoozeAlert(context);
+            Alarms.disableExpiredAlarms(context);
+        }
+        Alarms.setNextAlert(context);
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmKlaxon.java b/src/com/android/alarmclock/AlarmKlaxon.java
new file mode 100644 (file)
index 0000000..c862292
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnErrorListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Vibrator;
+
+/**
+ * Manages alarms and vibe.  Singleton, so it can be initiated in
+ * AlarmReceiver and shut down in the AlarmAlert activity
+ */
+class AlarmKlaxon implements Alarms.AlarmSettings {
+
+    interface KillerCallback {
+        public void onKilled();
+    }
+
+    /** Play alarm up to 10 minutes before silencing */
+    final static int ALARM_TIMEOUT_SECONDS = 10 * 60;
+
+    private static long[] sVibratePattern = new long[] { 500, 500 };
+
+    private static AlarmKlaxon sInstance;
+
+    private int mAlarmId;
+    private String mAlert;
+    private Alarms.DaysOfWeek mDaysOfWeek;
+    private boolean mVibrate;
+
+    private boolean mPlaying = false;
+
+    private Vibrator mVibrator;
+    private MediaPlayer mMediaPlayer;
+
+    private Handler mTimeout;
+    private KillerCallback mKillerCallback;
+
+
+    static synchronized AlarmKlaxon getInstance() {
+        if (sInstance == null) sInstance = new AlarmKlaxon();
+        return sInstance;
+    }
+
+    private AlarmKlaxon() {
+        mVibrator = new Vibrator();
+    }
+
+    public void reportAlarm(
+            int idx, boolean enabled, int hour, int minutes,
+            Alarms.DaysOfWeek daysOfWeek, boolean vibrate, String message,
+            String alert) {
+        if (Log.LOGV) Log.v("AlarmKlaxon.reportAlarm: " + idx + " " + hour +
+                            " " + minutes + " dow " + daysOfWeek);
+        mAlert = alert;
+        mDaysOfWeek = daysOfWeek;
+        mVibrate = vibrate;
+    }
+
+    synchronized void play(Context context, int alarmId) {
+        ContentResolver contentResolver = context.getContentResolver();
+
+        if (mPlaying) stop(context, false);
+
+        mAlarmId = alarmId;
+
+        /* this will call reportAlarm() callback */
+        Alarms.getAlarm(contentResolver, this, mAlarmId);
+
+        if (Log.LOGV) Log.v("AlarmKlaxon.play() " + mAlarmId + " alert " + mAlert);
+
+        /* play audio alert */
+        if (mAlert == null) {
+            Log.e("Unable to play alarm: no audio file available");
+        } else {
+            /* we need a new MediaPlayer when we change media URLs */
+            mMediaPlayer = new MediaPlayer();
+            mMediaPlayer.setOnErrorListener(new OnErrorListener() {
+                public boolean onError(MediaPlayer mp, int what, int extra) {
+                    Log.e("Error occurred while playing audio.");
+                    mp.stop();
+                    mp.release();
+                    mMediaPlayer = null;
+                    return true;
+                }
+            });
+
+            try {
+                mMediaPlayer.setDataSource(context, Uri.parse(mAlert));
+            } catch (Exception ex) {
+                Log.v("Using the fallback ringtone");
+                /* The alert may be on the sd card which could be busy right
+                 * now. Use the fallback ringtone. */
+                AssetFileDescriptor afd =
+                        context.getResources().openRawResourceFd(
+                                com.android.internal.R.raw.fallbackring);
+                if (afd != null) {
+                    try {
+                        mMediaPlayer.setDataSource(afd.getFileDescriptor(),
+                                afd.getStartOffset(), afd.getLength());
+                        afd.close();
+                    } catch (Exception ex2) {
+                        Log.e("Failed to play fallback ringtone", ex2);
+                        /* At this point we just don't play anything */
+                    }
+                }
+            }
+            /* Now try to play the alert. */
+            try {
+                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
+                mMediaPlayer.setLooping(true);
+                mMediaPlayer.prepare();
+                mMediaPlayer.start();
+            } catch (Exception ex) {
+                Log.e("Error playing alarm: " + mAlert, ex);
+            }
+        }
+
+        /* Start the vibrator after everything is ok with the media player */
+        if (mVibrate) {
+            mVibrator.vibrate(sVibratePattern, 0);
+        } else {
+            mVibrator.cancel();
+        }
+
+        enableKiller();
+        mPlaying = true;
+    }
+
+
+    /**
+     * Stops alarm audio and disables alarm if it not snoozed and not
+     * repeating
+     */
+    synchronized void stop(Context context, boolean snoozed) {
+        if (Log.LOGV) Log.v("AlarmKlaxon.stop() " + mAlarmId);
+        if (mPlaying) {
+            mPlaying = false;
+
+            // Stop audio playing
+            if (mMediaPlayer != null) {
+                mMediaPlayer.stop();
+                mMediaPlayer.release();
+                mMediaPlayer = null;
+            }
+
+            // Stop vibrator
+            mVibrator.cancel();
+
+            /* disable alarm only if it is not set to repeat */
+            if (!snoozed && ((mDaysOfWeek == null || !mDaysOfWeek.isRepeatSet()))) {
+                Alarms.enableAlarm(context, mAlarmId, false);
+            }
+        }
+        disableKiller();
+    }
+
+    /**
+     * This callback called when alarm killer times out unattended
+     * alarm
+     */
+    void setKillerCallback(KillerCallback killerCallback) {
+        mKillerCallback = killerCallback;
+    }
+
+    /**
+     * Kills alarm audio after ALARM_TIMEOUT_SECONDS, so the alarm
+     * won't run all day.
+     *
+     * This just cancels the audio, but leaves the notification
+     * popped, so the user will know that the alarm tripped.
+     */
+    private void enableKiller() {
+        mTimeout = new Handler();
+        mTimeout.postDelayed(new Runnable() {
+                public void run() {
+                    if (Log.LOGV) Log.v("*********** Alarm killer triggered *************");
+                    if (mKillerCallback != null) mKillerCallback.onKilled();
+                }
+            }, 1000 * ALARM_TIMEOUT_SECONDS);
+    }
+
+    private void disableKiller() {
+        if (mTimeout != null) {
+            mTimeout.removeCallbacksAndMessages(null);
+            mTimeout = null;
+        }
+    }
+
+
+}
diff --git a/src/com/android/alarmclock/AlarmPreference.java b/src/com/android/alarmclock/AlarmPreference.java
new file mode 100644 (file)
index 0000000..0fd4f89
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.content.Context;
+import android.net.Uri;
+import android.preference.RingtonePreference;
+import android.util.AttributeSet;
+
+public class AlarmPreference extends RingtonePreference {
+    public Uri mAlert;
+    private IRingtoneChangedListener mRingtoneChangedListener;
+
+    public interface IRingtoneChangedListener {
+        public void onRingtoneChanged(Uri ringtoneUri);
+    };
+
+    public AlarmPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setRingtoneChangedListener(IRingtoneChangedListener listener) {
+        mRingtoneChangedListener = listener;
+    }
+
+    @Override
+    protected void onSaveRingtone(Uri ringtoneUri) {
+        if (ringtoneUri != null) {
+            mAlert = ringtoneUri;
+            if (mRingtoneChangedListener != null) {
+                mRingtoneChangedListener.onRingtoneChanged(ringtoneUri);
+            }
+        }
+    }
+
+    @Override
+    protected Uri onRestoreRingtone() {
+        return mAlert;
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmProvider.java b/src/com/android/alarmclock/AlarmProvider.java
new file mode 100644 (file)
index 0000000..74fdd2e
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+public class AlarmProvider extends ContentProvider {
+    private SQLiteOpenHelper mOpenHelper;
+
+    private static final int ALARMS = 1;
+    private static final int ALARMS_ID = 2;
+    private static final UriMatcher sURLMatcher = new UriMatcher(
+            UriMatcher.NO_MATCH);
+
+    static {
+        sURLMatcher.addURI("com.android.alarmclock", "alarm", ALARMS);
+        sURLMatcher.addURI("com.android.alarmclock", "alarm/#", ALARMS_ID);
+    }
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+        private static final String DATABASE_NAME = "alarms.db";
+        private static final int DATABASE_VERSION = 5;
+
+        public DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE alarms (" +
+                       "_id INTEGER PRIMARY KEY," +
+                       "hour INTEGER, " +
+                       "minutes INTEGER, " +
+                       "daysofweek INTEGER, " +
+                       "alarmtime INTEGER, " +
+                       "enabled INTEGER, " +
+                       "vibrate INTEGER, " +
+                       "message TEXT, " +
+                       "alert TEXT);");
+
+            // insert default alarms
+            String insertMe = "INSERT INTO alarms " +
+                    "(hour, minutes, daysofweek, alarmtime, enabled, vibrate, message, alert) " +
+                    "VALUES ";
+            db.execSQL(insertMe + "(7, 0, 127, 0, 0, 1, '', '');");
+            db.execSQL(insertMe + "(8, 30, 31, 0, 0, 1, '', '');");
+            db.execSQL(insertMe + "(9, 00, 0, 0, 0, 1, '', '');");
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+            if (Log.LOGV) Log.v(
+                    "Upgrading alarms database from version " +
+                    oldVersion + " to " + currentVersion +
+                    ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS alarms");
+            onCreate(db);
+        }
+    }
+
+    public AlarmProvider() {
+    }
+
+    @Override
+    public boolean onCreate() {
+        mOpenHelper = new DatabaseHelper(getContext());
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri url, String[] projectionIn, String selection,
+            String[] selectionArgs, String sort) {
+        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+        // Generate the body of the query
+        int match = sURLMatcher.match(url);
+        switch (match) {
+            case ALARMS:
+                qb.setTables("alarms");
+                break;
+            case ALARMS_ID:
+                qb.setTables("alarms");
+                qb.appendWhere("_id=");
+                qb.appendWhere(url.getPathSegments().get(1));
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown URL " + url);
+        }
+
+        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        Cursor ret = qb.query(db, projectionIn, selection, selectionArgs,
+                              null, null, sort);
+
+        if (ret == null) {
+            if (Log.LOGV) Log.v("Alarms.query: failed");
+        } else {
+            ret.setNotificationUri(getContext().getContentResolver(), url);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public String getType(Uri url) {
+        int match = sURLMatcher.match(url);
+        switch (match) {
+            case ALARMS:
+                return "vnd.android.cursor.dir/alarms";
+            case ALARMS_ID:
+                return "vnd.android.cursor.item/alarms";
+            default:
+                throw new IllegalArgumentException("Unknown URL");
+        }
+    }
+
+    @Override
+    public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
+        int count;
+        long rowId = 0;
+        int match = sURLMatcher.match(url);
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        switch (match) {
+            case ALARMS_ID: {
+                String segment = url.getPathSegments().get(1);
+                rowId = Long.parseLong(segment);
+                count = db.update("alarms", values, "_id=" + rowId, null);
+                break;
+            }
+            default: {
+                throw new UnsupportedOperationException(
+                        "Cannot update URL: " + url);
+            }
+        }
+        if (Log.LOGV) Log.v("*** notifyChange() rowId: " + rowId + " url " + url);
+        getContext().getContentResolver().notifyChange(url, null);
+        return count;
+    }
+
+    @Override
+    public Uri insert(Uri url, ContentValues initialValues) {
+        if (sURLMatcher.match(url) != ALARMS) {
+            throw new IllegalArgumentException("Cannot insert into URL: " + url);
+        }
+
+        ContentValues values;
+        if (initialValues != null)
+            values = new ContentValues(initialValues);
+        else
+            values = new ContentValues();
+
+        if (!values.containsKey(Alarms.AlarmColumns.HOUR))
+            values.put(Alarms.AlarmColumns.HOUR, 0);
+
+        if (!values.containsKey(Alarms.AlarmColumns.MINUTES))
+            values.put(Alarms.AlarmColumns.MINUTES, 0);
+
+        if (!values.containsKey(Alarms.AlarmColumns.DAYS_OF_WEEK))
+            values.put(Alarms.AlarmColumns.DAYS_OF_WEEK, 0);
+
+        if (!values.containsKey(Alarms.AlarmColumns.ALARM_TIME))
+            values.put(Alarms.AlarmColumns.ALARM_TIME, 0);
+
+        if (!values.containsKey(Alarms.AlarmColumns.ENABLED))
+            values.put(Alarms.AlarmColumns.ENABLED, 0);
+
+        if (!values.containsKey(Alarms.AlarmColumns.VIBRATE))
+            values.put(Alarms.AlarmColumns.VIBRATE, 1);
+
+        if (!values.containsKey(Alarms.AlarmColumns.MESSAGE))
+            values.put(Alarms.AlarmColumns.MESSAGE, "");
+
+        if (!values.containsKey(Alarms.AlarmColumns.ALERT))
+            values.put(Alarms.AlarmColumns.ALERT, "");
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        long rowId = db.insert("alarms", Alarms.AlarmColumns.MESSAGE, values);
+        if (rowId < 0) {
+            throw new SQLException("Failed to insert row into " + url);
+        }
+        if (Log.LOGV) Log.v("Added alarm rowId = " + rowId);
+
+        Uri newUrl = ContentUris.withAppendedId(Alarms.AlarmColumns.CONTENT_URI, rowId);
+        getContext().getContentResolver().notifyChange(newUrl, null);
+        return newUrl;
+    }
+
+    public int delete(Uri url, String where, String[] whereArgs) {
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        int count;
+        long rowId = 0;
+        switch (sURLMatcher.match(url)) {
+            case ALARMS:
+                count = db.delete("alarms", where, whereArgs);
+                break;
+            case ALARMS_ID:
+                String segment = url.getPathSegments().get(1);
+                rowId = Long.parseLong(segment);
+                if (TextUtils.isEmpty(where)) {
+                    where = "_id=" + segment;
+                } else {
+                    where = "_id=" + segment + " AND (" + where + ")";
+                }
+                count = db.delete("alarms", where, whereArgs);
+                break;
+            default:
+                throw new IllegalArgumentException("Cannot delete from URL: " + url);
+        }
+
+        getContext().getContentResolver().notifyChange(url, null);
+        return count;
+    }
+}
diff --git a/src/com/android/alarmclock/AlarmReceiver.java b/src/com/android/alarmclock/AlarmReceiver.java
new file mode 100644 (file)
index 0000000..af18b7b
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+
+/**
+ * Glue class: connects AlarmAlert IntentReceiver to AlarmAlert
+ * activity.  Passes through Alarm ID.
+ */
+public class AlarmReceiver extends BroadcastReceiver {
+
+    /** If the alarm is older than STALE_WINDOW seconds, ignore.  It
+        is probably the result of a time or timezone change */
+    private final static int STALE_WINDOW = 60 * 30;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        long now = System.currentTimeMillis();
+        int id = intent.getIntExtra(Alarms.ID, 0);
+        long setFor = intent.getLongExtra(Alarms.TIME, 0);
+
+        /* FIXME Intentionally verbose: always log this until we've
+           fully debugged the app failing to start up */
+        Log.v("AlarmReceiver.onReceive() id " + id + " setFor " + setFor +
+              " now " + now);
+
+        if (now > setFor + STALE_WINDOW * 1000) {
+            if (Log.LOGV) Log.v("AlarmReceiver ignoring stale alarm intent id"
+                                + id + " setFor " + setFor + " now " + now);
+            return;
+        }
+
+        /* wake device */
+        AlarmAlertWakeLock.acquire(context);
+
+        /* start audio/vibe */
+        AlarmKlaxon klaxon = AlarmKlaxon.getInstance();
+        klaxon.play(context, id);
+
+        /* Close dialogs and window shade */
+        Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        context.sendBroadcast(i);
+
+        /* launch UI, explicitly stating that this is not due to user action
+         * so that the current app's notification management is not disturbed */
+        Intent fireAlarm = new Intent(context, AlarmAlert.class);
+        fireAlarm.putExtra(Alarms.ID, id);
+        fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
+        context.startActivity(fireAlarm);
+   }
+}
diff --git a/src/com/android/alarmclock/Alarms.java b/src/com/android/alarmclock/Alarms.java
new file mode 100644 (file)
index 0000000..56af9b3
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+
+import java.util.Calendar;
+
+/**
+ * The Alarms provider supplies info about Alarm Clock settings
+ */
+public class Alarms {
+
+    public final static String ALARM_ALERT_ACTION = "com.android.alarmclock.ALARM_ALERT";
+    public final static String ID = "alarm_id";
+    public final static String TIME = "alarm_time";
+
+    final static String PREF_SNOOZE_ID = "snooze_id";
+    final static String PREF_SNOOZE_TIME = "snooze_time";
+
+    private final static String DM12 = "E h:mm aa";
+    private final static String DM24 = "E k:mm";
+
+    private final static String M12 = "h:mm aa";
+    private final static String M24 = "k:mm";
+
+    static class DaysOfWeek {
+
+        int mDays;
+
+        /**
+         * Days of week coded as single int, convenient for DB
+         * storage:
+         *
+         * 0x00:  no day
+         * 0x01:  Monday
+         * 0x02:  Tuesday
+         * 0x04:  Wednesday
+         * 0x08:  Thursday
+         * 0x10:  Friday
+         * 0x20:  Saturday
+         * 0x40:  Sunday
+         */
+        DaysOfWeek() {
+            this(0);
+        }
+
+        DaysOfWeek(int days) {
+            mDays = days;
+        }
+
+        public String toString(Context context, boolean showNever) {
+            StringBuilder ret = new StringBuilder();
+
+            /* no days */
+            if (mDays == 0) return showNever ? context.getText(
+                    R.string.never).toString() : "";
+
+            /* every day */
+            if (mDays == 0x7f) {
+                return context.getText(R.string.every_day).toString();
+            }
+
+            /* count selected days */
+            int dayCount = 0, days = mDays;
+            while (days > 0) {
+                if ((days & 1) == 1) dayCount++;
+                days >>= 1;
+            }
+
+            /* short or long form? */
+            CharSequence[] strings =
+                    context.getResources().getTextArray(
+                            (dayCount > 1) ? R.array.days_of_week_short :
+                            R.array.days_of_week);
+
+            /* selected days */
+            for (int i = 0; i < 7; i++) {
+                if ((mDays & (1 << i)) != 0) {
+                    ret.append(strings[i]);
+                    dayCount -= 1;
+                    if (dayCount > 0) ret.append(
+                            context.getText(R.string.day_concat));
+                }
+            }
+            return ret.toString();
+        }
+
+        /**
+         * @param day Mon=0 ... Sun=6
+         * @return true if given day is set
+         */
+        public boolean isSet(int day) {
+            return ((mDays & (1 << day)) > 0);
+        }
+
+        public void set(int day, boolean set) {
+            if (set) {
+                mDays |= (1 << day);
+            } else {
+                mDays &= ~(1 << day);
+            }
+        }
+
+        public void set(DaysOfWeek dow) {
+            mDays = dow.mDays;
+        }
+
+        public int getCoded() {
+            return mDays;
+        }
+
+        public boolean equals(DaysOfWeek dow) {
+            return mDays == dow.mDays;
+        }
+
+        // Returns days of week encoded in an array of booleans.
+        public boolean[] getBooleanArray() {
+            boolean[] ret = new boolean[7];
+            for (int i = 0; i < 7; i++) {
+                ret[i] = isSet(i);
+            }
+            return ret;
+        }
+
+        public void setCoded(int days) {
+            mDays = days;
+        }
+
+        /**
+         * @return true if alarm is set to repeat
+         */
+        public boolean isRepeatSet() {
+            return mDays != 0;
+        }
+
+        /**
+         * @return true if alarm is set to repeat every day
+         */
+        public boolean isEveryDaySet() {
+            return mDays == 0x7f;
+        }
+
+
+        /**
+         * returns number of days from today until next alarm
+         * @param c must be set to today
+         */
+        public int getNextAlarm(Calendar c) {
+            if (mDays == 0) return -1;
+            int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;
+
+            int day, dayCount;
+            for (dayCount = 0; dayCount < 7; dayCount++) {
+                day = (today + dayCount) % 7;
+                if ((mDays & (1 << day)) > 0) {
+                    break;
+                }
+            }
+            return dayCount;
+        }
+    }
+
+    public static class AlarmColumns implements BaseColumns {
+
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://com.android.alarmclock/alarm");
+
+        public static final String _ID = "_id";
+
+        /**
+         * The default sort order for this table
+         */
+        public static final String DEFAULT_SORT_ORDER = "_id ASC";
+
+        /**
+         * Hour in 24-hour localtime 0 - 23.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String HOUR = "hour";
+
+        /**
+         * Minutes in localtime 0 - 59
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MINUTES = "minutes";
+
+        /**
+         * Days of week coded as integer
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DAYS_OF_WEEK = "daysofweek";
+
+        /**
+         * Alarm time in UTC milliseconds from the epoch.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String ALARM_TIME = "alarmtime";
+
+        /**
+         * True if alarm is active
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String ENABLED = "enabled";
+
+        /**
+         * True if alarm should vibrate
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String VIBRATE = "vibrate";
+
+        /**
+         * Message to show when alarm triggers
+         * Note: not currently used
+         * <P>Type: STRING</P>
+         */
+        public static final String MESSAGE = "message";
+
+        /**
+         * Audio alert to play when alarm triggers
+         * <P>Type: STRING</P>
+         */
+        public static final String ALERT = "alert";
+
+        static final String[] ALARM_QUERY_COLUMNS = {
+            _ID, HOUR, MINUTES, DAYS_OF_WEEK, ALARM_TIME,
+            ENABLED, VIBRATE, MESSAGE, ALERT};
+
+        /**
+         * These save calls to cursor.getColumnIndexOrThrow()
+         * THEY MUST BE KEPT IN SYNC WITH ABOVE QUERY COLUMNS
+         */
+        public static final int ALARM_ID_INDEX = 0;
+        public static final int ALARM_HOUR_INDEX = 1;
+        public static final int ALARM_MINUTES_INDEX = 2;
+        public static final int ALARM_DAYS_OF_WEEK_INDEX = 3;
+        public static final int ALARM_TIME_INDEX = 4;
+        public static final int ALARM_ENABLED_INDEX = 5;
+        public static final int ALARM_VIBRATE_INDEX = 6;
+        public static final int ALARM_MESSAGE_INDEX = 7;
+        public static final int ALARM_ALERT_INDEX = 8;
+    }
+
+    /**
+     * getAlarm and getAlarms call this interface to report alarms in
+     * the database
+     */
+    static interface AlarmSettings {
+        void reportAlarm(
+                int idx, boolean enabled, int hour, int minutes,
+                DaysOfWeek daysOfWeek, boolean vibrate, String message,
+                String alert);
+    }
+
+    /**
+     * Creates a new Alarm.
+     */
+    public synchronized static Uri addAlarm(ContentResolver contentResolver) {
+        ContentValues values = new ContentValues();
+        values.put(Alarms.AlarmColumns.HOUR, 8);
+        return contentResolver.insert(AlarmColumns.CONTENT_URI, values);
+    }
+
+    /**
+     * Removes an existing Alarm.  If this alarm is snoozing, disables
+     * snooze.  Sets next alert.
+     */
+    public synchronized static void deleteAlarm(
+            Context context, int alarmId) {
+
+        ContentResolver contentResolver = context.getContentResolver();
+        /* If alarm is snoozing, lose it */
+        int snoozeId = getSnoozeAlarmId(context);
+        if (snoozeId == alarmId) disableSnoozeAlert(context);
+
+        Uri uri = ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, alarmId);
+        deleteAlarm(contentResolver, uri);
+
+        setNextAlert(context);
+    }
+
+    private synchronized static void deleteAlarm(
+            ContentResolver contentResolver, Uri uri) {
+        contentResolver.delete(uri, "", null);
+    }
+
+    /**
+     * Queries all alarms
+     * @return cursor over all alarms
+     */
+    public synchronized static Cursor getAlarmsCursor(
+            ContentResolver contentResolver) {
+        return contentResolver.query(
+                AlarmColumns.CONTENT_URI, AlarmColumns.ALARM_QUERY_COLUMNS,
+                null, null, AlarmColumns.DEFAULT_SORT_ORDER);
+    }
+
+    /**
+     * Calls the AlarmSettings.reportAlarm interface on all alarms found in db.
+     */
+    public synchronized static void getAlarms(
+            ContentResolver contentResolver, AlarmSettings alarmSettings) {
+        Cursor cursor = getAlarmsCursor(contentResolver);
+        getAlarms(alarmSettings, cursor);
+        cursor.close();
+    }
+
+    private synchronized static void getAlarms(
+            AlarmSettings alarmSettings, Cursor cur) {
+        if (cur.moveToFirst()) {
+            do {
+                // Get the field values
+                int id = cur.getInt(AlarmColumns.ALARM_ID_INDEX);
+                int hour = cur.getInt(AlarmColumns.ALARM_HOUR_INDEX);
+                int minutes = cur.getInt(AlarmColumns.ALARM_MINUTES_INDEX);
+                int daysOfWeek = cur.getInt(AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX);
+                boolean enabled = cur.getInt(AlarmColumns.ALARM_ENABLED_INDEX) == 1 ? true : false;
+                boolean vibrate = cur.getInt(AlarmColumns.ALARM_VIBRATE_INDEX) == 1 ? true : false;
+                String message = cur.getString(AlarmColumns.ALARM_MESSAGE_INDEX);
+                String alert = cur.getString(AlarmColumns.ALARM_ALERT_INDEX);
+                alarmSettings.reportAlarm(
+                        id, enabled, hour, minutes, new DaysOfWeek(daysOfWeek),
+                        vibrate, message, alert);
+            } while (cur.moveToNext());
+        }
+    }
+
+    /**
+     * Calls the AlarmSettings.reportAlarm interface on alarm with given
+     * alarmId
+     */
+    public synchronized static void getAlarm(
+            ContentResolver contentResolver, AlarmSettings alarmSetting,
+            int alarmId) {
+        Cursor cursor = contentResolver.query(
+                ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, alarmId),
+                AlarmColumns.ALARM_QUERY_COLUMNS,
+                null, null, AlarmColumns.DEFAULT_SORT_ORDER);
+
+        getAlarms(alarmSetting, cursor);
+        cursor.close();
+    }
+
+
+    /**
+     * A convenience method to set an alarm in the Alarms
+     * content provider.
+     *
+     * @param id             corresponds to the _id column
+     * @param enabled        corresponds to the ENABLED column
+     * @param hour           corresponds to the HOUR column
+     * @param minutes        corresponds to the MINUTES column
+     * @param daysOfWeek     corresponds to the DAYS_OF_WEEK column
+     * @param time           corresponds to the ALARM_TIME column
+     * @param vibrate        corresponds to the VIBRATE column
+     * @param message        corresponds to the MESSAGE column
+     * @param alert          corresponds to the ALERT column
+     */
+    public synchronized static void setAlarm(
+            Context context, int id, boolean enabled, int hour, int minutes,
+            DaysOfWeek daysOfWeek, boolean vibrate, String message,
+            String alert) {
+
+        ContentValues values = new ContentValues(8);
+        ContentResolver resolver = context.getContentResolver();
+        long time = calculateAlarm(hour, minutes, daysOfWeek).getTimeInMillis();
+
+        if (Log.LOGV) Log.v(
+                "**  setAlarm * idx " + id + " hour " + hour + " minutes " +
+                minutes + " enabled " + enabled + " time " + time);
+
+        values.put(AlarmColumns.ENABLED, enabled ? 1 : 0);
+        values.put(AlarmColumns.HOUR, hour);
+        values.put(AlarmColumns.MINUTES, minutes);
+        values.put(AlarmColumns.ALARM_TIME, time);
+        values.put(AlarmColumns.DAYS_OF_WEEK, daysOfWeek.getCoded());
+        values.put(AlarmColumns.VIBRATE, vibrate);
+        values.put(AlarmColumns.MESSAGE, message);
+        values.put(AlarmColumns.ALERT, alert);
+        resolver.update(ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, id),
+                        values, null, null);
+
+        int aid = disableSnoozeAlert(context);
+        if (aid != -1 && aid != id) enableAlarmInternal(context, aid, false);
+        setNextAlert(context);
+    }
+
+    /**
+     * A convenience method to enable or disable an alarm.
+     *
+     * @param id             corresponds to the _id column
+     * @param enabled        corresponds to the ENABLED column
+     */
+
+    public synchronized static void enableAlarm(
+            final Context context, final int id, boolean enabled) {
+        int aid = disableSnoozeAlert(context);
+        if (aid != -1 && aid != id) enableAlarmInternal(context, aid, false);
+        enableAlarmInternal(context, id, enabled);
+        setNextAlert(context);
+    }
+
+    private synchronized static void enableAlarmInternal(
+            final Context context, final int id, boolean enabled) {
+        ContentResolver resolver = context.getContentResolver();
+
+        class EnableAlarm implements AlarmSettings {
+            public int mHour;
+            public int mMinutes;
+            public DaysOfWeek mDaysOfWeek;
+
+            public void reportAlarm(
+                    int idx, boolean enabled, int hour, int minutes,
+                    DaysOfWeek daysOfWeek, boolean vibrate, String message,
+                    String alert) {
+                mHour = hour;
+                mMinutes = minutes;
+                mDaysOfWeek = daysOfWeek;
+            }
+        }
+
+        ContentValues values = new ContentValues(2);
+        values.put(AlarmColumns.ENABLED, enabled ? 1 : 0);
+
+        /* If we are enabling the alarm, load hour/minutes/daysOfWeek
+           from db, so we can calculate alarm time */
+        if (enabled) {
+            EnableAlarm enableAlarm = new EnableAlarm();
+            getAlarm(resolver, enableAlarm, id);
+            if (enableAlarm.mDaysOfWeek == null) {
+                /* Under monkey, sometimes reportAlarm is never
+                   called */
+                Log.e("** enableAlarmInternal failed " + id + " h " +
+                      enableAlarm.mHour + " m " + enableAlarm.mMinutes);
+                return;
+            }
+
+            long time = calculateAlarm(enableAlarm.mHour, enableAlarm.mMinutes,
+                                       enableAlarm.mDaysOfWeek).getTimeInMillis();
+            values.put(AlarmColumns.ALARM_TIME, time);
+        }
+
+        resolver.update(ContentUris.withAppendedId(AlarmColumns.CONTENT_URI, id),
+                        values, null, null);
+    }
+
+
+    /**
+     * Calculates next scheduled alert
+     */
+    static class AlarmCalculator implements AlarmSettings {
+        public long mMinAlert = Long.MAX_VALUE;
+        public int mMinIdx = -1;
+
+        /**
+         * returns next scheduled alert, MAX_VALUE if none
+         */
+        public long getAlert() {
+            return mMinAlert;
+        }
+        public int getIndex() {
+            return mMinIdx;
+        }
+
+        public void reportAlarm(
+                int idx, boolean enabled, int hour, int minutes,
+                DaysOfWeek daysOfWeek, boolean vibrate, String message,
+                String alert) {
+            if (enabled) {
+                long atTime = calculateAlarm(hour, minutes,
+                                             daysOfWeek).getTimeInMillis();
+                /* Log.i("**  SET ALERT* idx " + idx + " hour " + hour + " minutes " +
+                   minutes + " enabled " + enabled + " calc " + atTime); */
+                if (atTime < mMinAlert) {
+                    mMinIdx = idx;
+                    mMinAlert = atTime;
+                }
+            }
+        }
+    }
+
+    static AlarmCalculator calculateNextAlert(final Context context) {
+        ContentResolver resolver = context.getContentResolver();
+        AlarmCalculator alarmCalc = new AlarmCalculator();
+        getAlarms(resolver, alarmCalc);
+        return alarmCalc;
+    }
+
+    /**
+     * Disables non-repeating alarms that have passed.  Called at
+     * boot.
+     */
+    public static void disableExpiredAlarms(final Context context) {
+        Cursor cur = getAlarmsCursor(context.getContentResolver());
+        long now = System.currentTimeMillis();
+
+        if (cur.moveToFirst()) {
+            do {
+                // Get the field values
+                int id = cur.getInt(AlarmColumns.ALARM_ID_INDEX);
+                boolean enabled = cur.getInt(
+                        AlarmColumns.ALARM_ENABLED_INDEX) == 1 ? true : false;
+                DaysOfWeek daysOfWeek = new DaysOfWeek(
+                        cur.getInt(AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX));
+                long time = cur.getLong(AlarmColumns.ALARM_TIME_INDEX);
+
+                if (enabled && !daysOfWeek.isRepeatSet() && time < now) {
+                    if (Log.LOGV) Log.v(
+                            "** DISABLE " + id + " now " + now +" set " + time);
+                    enableAlarmInternal(context, id, false);
+                }
+            } while (cur.moveToNext());
+        }
+        cur.close();
+    }
+
+    private static NotificationManager getNotificationManager(
+            final Context context) {
+        return (NotificationManager) context.getSystemService(
+                context.NOTIFICATION_SERVICE);
+    }
+
+    /**
+     * Called at system startup, on time/timezone change, and whenever
+     * the user changes alarm settings.  Activates snooze if set,
+     * otherwise loads all alarms, activates next alert.
+     */
+    public static void setNextAlert(final Context context) {
+        int snoozeId = getSnoozeAlarmId(context);
+        if (snoozeId == -1) {
+            AlarmCalculator ac = calculateNextAlert(context);
+            int id = ac.getIndex();
+            long atTime = ac.getAlert();
+
+            if (atTime < Long.MAX_VALUE) {
+                enableAlert(context, id, atTime);
+            } else {
+                disableAlert(context, id);
+            }
+        } else {
+            enableSnoozeAlert(context);
+        }
+    }
+
+    /**
+     * Sets alert in AlarmManger and StatusBar.  This is what will
+     * actually launch the alert when the alarm triggers.
+     *
+     * Note: In general, apps should call setNextAlert() instead of
+     * this method.  setAlert() is only used outside this class when
+     * the alert is not to be driven by the state of the db.  "Snooze"
+     * uses this API, as we do not want to alter the alarm in the db
+     * with each snooze.
+     *
+     * @param id Alarm ID.
+     * @param atTimeInMillis milliseconds since epoch
+     */
+    static void enableAlert(Context context, int id, long atTimeInMillis) {
+        AlarmManager am = (AlarmManager)
+                context.getSystemService(Context.ALARM_SERVICE);
+
+        Intent intent = new Intent(ALARM_ALERT_ACTION);
+        if (Log.LOGV) Log.v("** setAlert id " + id + " atTime " + atTimeInMillis);
+        intent.putExtra(ID, id);
+        intent.putExtra(TIME, atTimeInMillis);
+        PendingIntent sender = PendingIntent.getBroadcast(
+                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+        if (true) {
+            am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
+        } else {
+            // a five-second alarm, for testing
+            am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000,
+                   sender);
+        }
+
+        setStatusBarIcon(context, true);
+
+        Calendar c = Calendar.getInstance();
+        c.setTime(new java.util.Date(atTimeInMillis));
+        String timeString = formatDayAndTime(context, c);
+        saveNextAlarm(context, timeString);
+    }
+
+    /**
+     * Disables alert in AlarmManger and StatusBar.
+     *
+     * @param id Alarm ID.
+     */
+    static void disableAlert(Context context, int id) {
+        AlarmManager am = (AlarmManager)
+                context.getSystemService(Context.ALARM_SERVICE);
+        Intent intent = new Intent(ALARM_ALERT_ACTION);
+        intent.putExtra(ID, id);
+        PendingIntent sender = PendingIntent.getBroadcast(
+                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+        am.cancel(sender);
+        setStatusBarIcon(context, false);
+        saveNextAlarm(context, "");
+    }
+
+    static void saveSnoozeAlert(final Context context, int id,
+                                long atTimeInMillis) {
+        SharedPreferences prefs = context.getSharedPreferences(
+                AlarmClock.PREFERENCES, 0);
+        SharedPreferences.Editor ed = prefs.edit();
+        ed.putInt(PREF_SNOOZE_ID, id);
+        ed.putLong(PREF_SNOOZE_TIME, atTimeInMillis);
+        ed.commit();
+    }
+
+    /**
+     * @return ID of alarm disabled, if disabled, -1 otherwise
+     */
+    static int disableSnoozeAlert(final Context context) {
+        int id = getSnoozeAlarmId(context);
+        if (id == -1) return -1;
+        saveSnoozeAlert(context, -1, 0);
+        return id;
+    }
+
+    /**
+     * @return alarm ID of snoozing alarm, -1 if snooze unset
+     */
+    private static int getSnoozeAlarmId(final Context context) {
+        SharedPreferences prefs = context.getSharedPreferences(
+                AlarmClock.PREFERENCES, 0);
+        return prefs.getInt(PREF_SNOOZE_ID, -1);
+    }
+
+    /**
+     * If there is a snooze set, enable it in AlarmManager
+     * @return true if snooze is set
+     */
+    private static boolean enableSnoozeAlert(final Context context) {
+        SharedPreferences prefs = context.getSharedPreferences(
+                AlarmClock.PREFERENCES, 0);
+
+        int id = prefs.getInt(PREF_SNOOZE_ID, -1);
+        if (id == -1) return false;
+        long atTimeInMillis = prefs.getLong(PREF_SNOOZE_TIME, -1);
+        if (id == -1) return false;
+        enableAlert(context, id, atTimeInMillis);
+        return true;
+    }
+
+
+    /**
+     * Tells the StatusBar whether the alarm is enabled or disabled
+     */
+    private static void setStatusBarIcon(Context context, boolean enabled) {
+        Intent alarmChanged = new Intent(Intent.ACTION_ALARM_CHANGED);
+        alarmChanged.putExtra("alarmSet", enabled);
+        context.sendBroadcast(alarmChanged);
+    }
+
+    /**
+     * Given an alarm in hours and minutes, return a time suitable for
+     * setting in AlarmManager.
+     * @param hour Always in 24 hour 0-23
+     * @param minute 0-59
+     * @param daysOfWeek 0-59
+     */
+    static Calendar calculateAlarm(int hour, int minute, DaysOfWeek daysOfWeek) {
+
+        // start with now
+        Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(System.currentTimeMillis());
+
+        int nowHour = c.get(Calendar.HOUR_OF_DAY);
+        int nowMinute = c.get(Calendar.MINUTE);
+
+        // if alarm is behind current time, advance one day
+        if (hour < nowHour  ||
+            hour == nowHour && minute <= nowMinute) {
+            c.add(Calendar.DAY_OF_YEAR, 1);
+        }
+        c.set(Calendar.HOUR_OF_DAY, hour);
+        c.set(Calendar.MINUTE, minute);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+
+        int addDays = daysOfWeek.getNextAlarm(c);
+        /* Log.v("** TIMES * " + c.getTimeInMillis() + " hour " + hour +
+           " minute " + minute + " dow " + c.get(Calendar.DAY_OF_WEEK) + " from now " +
+           addDays); */
+        if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays);
+        return c;
+    }
+
+    static String formatTime(final Context context, int hour, int minute,
+                             DaysOfWeek daysOfWeek) {
+        Calendar c = calculateAlarm(hour, minute, daysOfWeek);
+        return formatTime(context, c);
+    }
+
+    /* used by AlarmAlert */
+    static String formatTime(final Context context, Calendar c) {
+        String format = get24HourMode(context) ? M24 : M12;
+        return (c == null) ? "" : (String)DateFormat.format(format, c);
+    }
+
+    /**
+     * Shows day and time -- used for lock screen
+     */
+    private static String formatDayAndTime(final Context context, Calendar c) {
+        String format = get24HourMode(context) ? DM24 : DM12;
+        return (c == null) ? "" : (String)DateFormat.format(format, c);
+    }
+
+    /**
+     * Save time of the next alarm, as a formatted string, into the system
+     * settings so those who care can make use of it.
+     */
+    static void saveNextAlarm(final Context context, String timeString) {
+        Settings.System.putString(context.getContentResolver(),
+                                  Settings.System.NEXT_ALARM_FORMATTED,
+                                  timeString);
+    }
+
+    /**
+     * @return true if clock is set to 24-hour mode
+     */
+    static boolean get24HourMode(final Context context) {
+        return android.text.format.DateFormat.is24HourFormat(context);
+    }
+}
diff --git a/src/com/android/alarmclock/AnalogGadgetProvider.java b/src/com/android/alarmclock/AnalogGadgetProvider.java
new file mode 100644 (file)
index 0000000..1143da5
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 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.alarmclock;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.gadget.GadgetManager;
+import android.graphics.PorterDuff;
+import android.net.Uri;
+import android.provider.Calendar;
+import android.provider.Calendar.Attendees;
+import android.provider.Calendar.Calendars;
+import android.provider.Calendar.EventsColumns;
+import android.provider.Calendar.Instances;
+import android.provider.Calendar.Reminders;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.Config;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import java.util.Arrays;
+
+/**
+ * Simple gadget to show analog clock.
+ */
+public class AnalogGadgetProvider extends BroadcastReceiver {
+    static final String TAG = "AnalogGadgetProvider";
+
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        
+        if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
+            RemoteViews views = new RemoteViews(context.getPackageName(),
+                    R.layout.analog_gadget);
+            
+            int[] gadgetIds = intent.getIntArrayExtra(GadgetManager.EXTRA_GADGET_IDS);
+            
+            GadgetManager gm = GadgetManager.getInstance(context);
+            gm.updateGadget(gadgetIds, views);
+        }
+    }
+}
+
diff --git a/src/com/android/alarmclock/ClockPicker.java b/src/com/android/alarmclock/ClockPicker.java
new file mode 100644 (file)
index 0000000..039f5b8
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+
+/**
+ * Clock face picker for the Alarm Clock application.
+ */
+public class ClockPicker extends Activity implements
+        AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+    private LayoutInflater mFactory;
+    private Gallery mGallery;
+
+    private SharedPreferences mPrefs;
+    private View mClock;
+    private ViewGroup mClockLayout;
+    private int mPosition;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+        mFactory = LayoutInflater.from(this);
+        setContentView(R.layout.clockpicker);
+
+        mGallery = (Gallery) findViewById(R.id.gallery);
+        mGallery.setAdapter(new ClockAdapter());
+        mGallery.setOnItemSelectedListener(this);
+        mGallery.setOnItemClickListener(this);
+
+        mPrefs = getSharedPreferences(AlarmClock.PREFERENCES, 0);
+        int face = mPrefs.getInt(AlarmClock.PREF_CLOCK_FACE, 0);
+        if (face < 0 || face >= AlarmClock.CLOCKS.length) face = 0;
+
+        mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
+        mClockLayout.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    selectClock(mPosition);
+                }
+        });
+
+        mGallery.setSelection(face, false);
+    }
+
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        if (mClock != null) {
+            mClockLayout.removeView(mClock);
+        }
+        mClock = mFactory.inflate(AlarmClock.CLOCKS[position], null);
+        mClockLayout.addView(mClock, 0);
+        mPosition = position;
+    }
+
+    public void onItemClick(AdapterView parent, View v, int position, long id) {
+        selectClock(position);
+    }
+
+    private synchronized void selectClock(int position) {
+        SharedPreferences.Editor ed = mPrefs.edit();
+        ed.putInt("face", position);
+        ed.commit();
+
+        setResult(RESULT_OK);
+        finish();
+    }
+
+    public void onNothingSelected(AdapterView parent) {
+    }
+
+    class ClockAdapter extends BaseAdapter {
+
+        public ClockAdapter() {
+        }
+
+        public int getCount() {
+            return AlarmClock.CLOCKS.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(final int position, View convertView, ViewGroup parent) {
+            View clock = mFactory.inflate(AlarmClock.CLOCKS[position], null);
+            return clock;
+        }
+
+    }
+}
diff --git a/src/com/android/alarmclock/DigitalClock.java b/src/com/android/alarmclock/DigitalClock.java
new file mode 100644 (file)
index 0000000..65dcc2c
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.Calendar;
+
+/**
+ * Displays the time
+ */
+public class DigitalClock extends LinearLayout {
+
+    private final static String M12 = "h:mm";
+    private final static String M24 = "k:mm";
+
+    private Calendar mCalendar;
+    private String mFormat;
+    private TextView mTimeDisplay;
+    private AmPm mAmPm;
+    private boolean mAnimate;
+    private ContentObserver mFormatChangeObserver;
+    private boolean mLive = true;
+    private boolean mAttached;
+
+    /* called by system on minute ticks */
+    private final Handler mHandler = new Handler();
+    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (mLive && intent.getAction().equals(
+                            Intent.ACTION_TIMEZONE_CHANGED)) {
+                    mCalendar = Calendar.getInstance();
+                }
+                updateTime();
+            }
+        };
+
+    static class AmPm {
+        private int mColorOn, mColorOff;
+
+        private LinearLayout mAmPmLayout;
+        private TextView mAm, mPm;
+
+        AmPm(View parent) {
+            mAmPmLayout = (LinearLayout) parent.findViewById(R.id.am_pm);
+            mAm = (TextView)mAmPmLayout.findViewById(R.id.am);
+            mPm = (TextView)mAmPmLayout.findViewById(R.id.pm);
+
+            Resources r = parent.getResources();
+            mColorOn = r.getColor(R.color.ampm_on);
+            mColorOff = r.getColor(R.color.ampm_off);
+        }
+
+        void setShowAmPm(boolean show) {
+            mAmPmLayout.setVisibility(show ? View.VISIBLE : View.GONE);
+        }
+
+        void setIsMorning(boolean isMorning) {
+            mAm.setTextColor(isMorning ? mColorOn : mColorOff);
+            mPm.setTextColor(isMorning ? mColorOff : mColorOn);
+        }
+    }
+
+    private class FormatChangeObserver extends ContentObserver {
+        public FormatChangeObserver() {
+            super(new Handler());
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            setDateFormat();
+            updateTime();
+        }
+    }
+
+    public DigitalClock(Context context) {
+        this(context, null);
+    }
+
+    public DigitalClock(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
+        mAmPm = new AmPm(this);
+        mCalendar = Calendar.getInstance();
+
+        setDateFormat();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        if (Log.LOGV) Log.v("onAttachedToWindow " + this);
+
+        if (mAttached) return;
+        mAttached = true;
+
+        if (mAnimate) {
+            AnimationDrawable frameAnimation =
+                    (AnimationDrawable) mContext.getResources().getDrawable(
+                            R.drawable.animate_circle);
+            View digitalClock = findViewById(R.id.digitalClock);
+            digitalClock.setBackgroundDrawable(frameAnimation);
+            /* Start the animation (looped playback by default). */
+            ((AnimationDrawable) digitalClock.getBackground()).start();
+            /* No luck wrapping animation or individual bitmaps in a
+               ScaleDrawable */
+            digitalClock.requestLayout();
+        }
+
+        if (mLive) {
+            /* monitor time ticks, time changed, timezone */
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_TIME_TICK);
+            filter.addAction(Intent.ACTION_TIME_CHANGED);
+            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+            mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
+        }
+
+        /* monitor 12/24-hour display preference */
+        mFormatChangeObserver = new FormatChangeObserver();
+        mContext.getContentResolver().registerContentObserver(
+                Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+
+        updateTime();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (!mAttached) return;
+        mAttached = false;
+
+        Drawable background = getBackground();
+        if (background instanceof AnimationDrawable) {
+            ((AnimationDrawable) background).stop();
+        }
+
+        if (mLive) {
+            mContext.unregisterReceiver(mIntentReceiver);
+        }
+        mContext.getContentResolver().unregisterContentObserver(
+                mFormatChangeObserver);
+    }
+
+
+    void updateTime(Calendar c) {
+        mCalendar = c;
+        updateTime();
+    }
+
+    private void updateTime() {
+        if (mLive) {
+            mCalendar.setTimeInMillis(System.currentTimeMillis());
+        }
+
+        CharSequence newTime = DateFormat.format(mFormat, mCalendar);
+        mTimeDisplay.setText(newTime);
+        mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
+    }
+
+    private void setDateFormat() {
+        mFormat = Alarms.get24HourMode(mContext) ? M24 : M12;
+        mAmPm.setShowAmPm(mFormat == M12);
+    }
+
+    void setAnimate() {
+        mAnimate = true;
+    }
+
+    void setLive(boolean live) {
+        mLive = live;
+    }
+}
diff --git a/src/com/android/alarmclock/Log.java b/src/com/android/alarmclock/Log.java
new file mode 100644 (file)
index 0000000..18cc391
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 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-level logging flag
+ */
+
+package com.android.alarmclock;
+
+import android.os.SystemClock;
+import android.util.Config;
+
+class Log {
+    public final static String LOGTAG = "AlarmClock";
+
+    static final boolean LOGV = AlarmClock.DEBUG ? Config.LOGD : Config.LOGV;
+
+    static void v(String logMe) {
+        android.util.Log.v(LOGTAG, /* SystemClock.uptimeMillis() + " " + */ logMe);
+    }
+
+    static void e(String logMe) {
+        android.util.Log.e(LOGTAG, logMe);
+    }
+
+    static void e(String logMe, Exception ex) {
+        android.util.Log.e(LOGTAG, logMe, ex);
+    }
+}
diff --git a/src/com/android/alarmclock/RepeatPreference.java b/src/com/android/alarmclock/RepeatPreference.java
new file mode 100644 (file)
index 0000000..8313858
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+
+public class RepeatPreference extends ListPreference {
+
+    private Alarms.DaysOfWeek mDaysOfWeek = new Alarms.DaysOfWeek();
+    private OnRepeatChangedObserver mOnRepeatChangedObserver;
+
+    public interface OnRepeatChangedObserver {
+        /** RepeatPrefrence calls this to get initial state */
+        public Alarms.DaysOfWeek getDaysOfWeek();
+
+        /** Called when this preference has changed */
+        public void onRepeatChanged(Alarms.DaysOfWeek daysOfWeek);
+    }
+
+    public RepeatPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    void setOnRepeatChangedObserver(OnRepeatChangedObserver onRepeatChangedObserver) {
+        mOnRepeatChangedObserver = onRepeatChangedObserver;
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        if (positiveResult) {
+            mOnRepeatChangedObserver.onRepeatChanged(mDaysOfWeek);
+        } else {
+            /* no change -- reset to initial state */
+            mDaysOfWeek.set(mOnRepeatChangedObserver.getDaysOfWeek());
+        }
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(Builder builder) {
+        CharSequence[] entries = getEntries();
+        CharSequence[] entryValues = getEntryValues();
+
+        if (entries == null || entryValues == null) {
+            throw new IllegalStateException(
+                    "RepeatPreference requires an entries array and an entryValues array.");
+        }
+
+        mDaysOfWeek.set(mOnRepeatChangedObserver.getDaysOfWeek());
+
+        builder.setMultiChoiceItems(
+                entries, mDaysOfWeek.getBooleanArray(),
+                new DialogInterface.OnMultiChoiceClickListener() {
+                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+                        mDaysOfWeek.set(which, isChecked);
+                    }
+                });
+    }
+}
diff --git a/src/com/android/alarmclock/SetAlarm.java b/src/com/android/alarmclock/SetAlarm.java
new file mode 100644 (file)
index 0000000..d8c9b46
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2007 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.alarmclock;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.CheckBoxPreference;
+import android.preference.PreferenceScreen;
+import android.text.format.DateFormat;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TimePicker;
+import android.widget.Toast;
+
+/**
+ * Manages each alarm
+ */
+public class SetAlarm extends PreferenceActivity
+        implements Alarms.AlarmSettings, TimePickerDialog.OnTimeSetListener {
+
+    private CheckBoxPreference mAlarmOnPref;
+    private Preference mTimePref;
+    private AlarmPreference mAlarmPref;
+    private CheckBoxPreference mVibratePref;
+    private RepeatPreference mRepeatPref;
+    private ContentObserver mAlarmsChangeObserver;
+    private MenuItem mDeleteAlarmItem;
+    private MenuItem mTestAlarmItem;
+
+    private int mId;
+    private int mHour;
+    private int mMinutes;
+    private Alarms.DaysOfWeek mDaysOfWeek = new Alarms.DaysOfWeek();
+
+    private boolean mReportAlarmCalled;
+
+    private static final int DIALOG_TIMEPICKER = 0;
+
+    private class RingtoneChangedListener implements AlarmPreference.IRingtoneChangedListener {
+        public void onRingtoneChanged(Uri ringtoneUri) {
+            saveAlarm(false);
+        }
+    }
+
+    private class OnRepeatChangedObserver implements RepeatPreference.OnRepeatChangedObserver {
+        public void onRepeatChanged(Alarms.DaysOfWeek daysOfWeek) {
+            if (!mDaysOfWeek.equals(daysOfWeek)) {
+                mDaysOfWeek.set(daysOfWeek);
+                saveAlarm(true);
+            }
+        }
+        public Alarms.DaysOfWeek getDaysOfWeek() {
+            return mDaysOfWeek;
+        }
+    }
+
+    private class AlarmsChangeObserver extends ContentObserver {
+        public AlarmsChangeObserver() {
+            super(new Handler());
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            Alarms.getAlarm(getContentResolver(), SetAlarm.this, mId);
+        }
+    }
+
+    /**
+     * Set an alarm.  Requires an Alarms.ID to be passed in as an
+     * extra
+     */
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        addPreferencesFromResource(R.xml.alarm_prefs);
+        mAlarmOnPref = (CheckBoxPreference)findPreference("on");
+        mTimePref = findPreference("time");
+        mAlarmPref = (AlarmPreference) findPreference("alarm");
+        mVibratePref = (CheckBoxPreference) findPreference("vibrate");
+        mRepeatPref = (RepeatPreference) findPreference("setRepeat");
+
+        Intent i = getIntent();
+        mId = i.getIntExtra(Alarms.ID, -1);
+        if (Log.LOGV) Log.v("In SetAlarm, alarm id = " + mId);
+
+        mReportAlarmCalled = false;
+        /* load alarm details from database */
+        Alarms.getAlarm(getContentResolver(), this, mId);
+        /* This should never happen, but does occasionally with the monkey.
+         * I believe it's a race condition where a deleted alarm is opened
+         * before the alarm list is refreshed. */
+        if (!mReportAlarmCalled) {
+            Log.e("reportAlarm never called!");
+            finish();
+        }
+
+        mAlarmsChangeObserver = new AlarmsChangeObserver();
+        getContentResolver().registerContentObserver(
+                Alarms.AlarmColumns.CONTENT_URI, true, mAlarmsChangeObserver);
+
+        mAlarmPref.setRingtoneChangedListener(new RingtoneChangedListener());
+        mRepeatPref.setOnRepeatChangedObserver(new OnRepeatChangedObserver());
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        getContentResolver().unregisterContentObserver(mAlarmsChangeObserver);
+    }
+
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        Dialog d;
+
+        switch (id) {
+        case DIALOG_TIMEPICKER:
+            d = new TimePickerDialog(
+                    SetAlarm.this,
+                    this,
+                    0,
+                    0,
+                    DateFormat.is24HourFormat(SetAlarm.this));
+            d.setTitle(getResources().getString(R.string.time));
+            break;
+        default:
+            d = null;
+        }
+
+        return d;
+    }
+
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog) {
+        super.onPrepareDialog(id, dialog);
+
+        switch (id) {
+        case DIALOG_TIMEPICKER:
+            TimePickerDialog timePicker = (TimePickerDialog)dialog;
+            timePicker.updateTime(mHour, mMinutes);
+            break;
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+
+        if (preference == mTimePref) {
+            showDialog(DIALOG_TIMEPICKER);
+        } else if (preference == mAlarmOnPref) {
+            saveAlarm(true);
+        } else if (preference == mVibratePref) {
+            saveAlarm(false);
+        }
+
+        return super.onPreferenceTreeClick(preferenceScreen, preference);
+    }
+
+    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+        mHour = hourOfDay;
+        mMinutes = minute;
+        mAlarmOnPref.setChecked(true);
+        saveAlarm(true);
+    }
+
+    /**
+     * Alarms.AlarmSettings implementation.  Database feeds current
+     * settings in through this call
+     */
+    public void reportAlarm(
+            int idx, boolean enabled, int hour, int minutes,
+            Alarms.DaysOfWeek daysOfWeek, boolean vibrate,String message,
+            String alert) {
+
+        mHour = hour;
+        mMinutes = minutes;
+        mAlarmOnPref.setChecked(enabled);
+        mDaysOfWeek.set(daysOfWeek);
+        mVibratePref.setChecked(vibrate);
+
+        if (alert == null || alert.length() == 0) {
+            if (Log.LOGV) Log.v("****** reportAlarm null or 0-length alert");
+            mAlarmPref.mAlert = getDefaultAlarm();
+            if (mAlarmPref.mAlert == null) {
+                Log.e("****** Default Alarm null");
+            }
+        } else {
+            mAlarmPref.mAlert = Uri.parse(alert);
+            if (mAlarmPref.mAlert == null) {
+                Log.e("****** Parsed null alarm. URI: " + alert);
+            }
+        }
+        if (Log.LOGV) Log.v("****** reportAlarm uri " + alert + " alert " +
+                            mAlarmPref.mAlert);
+        updateTime();
+        updateRepeat();
+        updateAlarm(mAlarmPref.mAlert);
+
+        mReportAlarmCalled = true;
+    }
+
+    /**
+     * picks the first alarm available
+     */
+    private Uri getDefaultAlarm() {
+        RingtoneManager ringtoneManager = new RingtoneManager(this);
+        ringtoneManager.setType(RingtoneManager.TYPE_ALARM);
+        return ringtoneManager.getRingtoneUri(0);
+    }
+
+    private void updateTime() {
+        if (Log.LOGV) Log.v("updateTime " + mId);
+        mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinutes, mDaysOfWeek));
+    }
+
+    private void updateAlarm(Uri ringtoneUri) {
+        if (Log.LOGV) Log.v("updateAlarm " + mId);
+        Ringtone ringtone = RingtoneManager.getRingtone(SetAlarm.this, ringtoneUri);
+        if (ringtone != null) {
+            mAlarmPref.setSummary(ringtone.getTitle(SetAlarm.this));
+        }
+    }
+
+    private void updateRepeat() {
+        if (Log.LOGV) Log.v("updateRepeat " + mId);
+        mRepeatPref.setSummary(mDaysOfWeek.toString(this, true));
+    }
+
+    private void saveAlarm(boolean popToast) {
+        if (mReportAlarmCalled && mAlarmPref.mAlert != null) {
+            String alertString = mAlarmPref.mAlert.toString();
+            saveAlarm(this, mId, mAlarmOnPref.isChecked(), mHour, mMinutes,
+                      mDaysOfWeek, mVibratePref.isChecked(), alertString,
+                      popToast);
+        }
+    }
+
+    /**
+     * Write alarm out to persistent store and pops toast if alarm
+     * enabled
+     */
+    private static void saveAlarm(
+            Context context, int id, boolean enabled, int hour, int minute,
+            Alarms.DaysOfWeek daysOfWeek, boolean vibrate, String alert,
+            boolean popToast) {
+        if (Log.LOGV) Log.v("** saveAlarm " + id + " " + enabled + " " + hour +
+                            " " + minute + " vibe " + vibrate);
+
+        // Fix alert string first
+        Alarms.setAlarm(context, id, enabled, hour, minute, daysOfWeek, vibrate,
+                        "", alert);
+
+        if (enabled && popToast) {
+            popAlarmSetToast(context, hour, minute, daysOfWeek);
+        }
+    }
+
+    /**
+     * Display a toast that tells the user how long until the alarm
+     * goes off.  This helps prevent "am/pm" mistakes.
+     */
+    static void popAlarmSetToast(Context context, int hour, int minute,
+                                 Alarms.DaysOfWeek daysOfWeek) {
+
+        String toastText = formatToast(context, hour, minute, daysOfWeek);
+        Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG);
+        ToastMaster.setToast(toast);
+        toast.show();
+    }
+
+    /**
+     * format "Alarm set for 2 days 7 hours and 53 minutes from
+     * now"
+     */
+    static String formatToast(Context context, int hour, int minute,
+                              Alarms.DaysOfWeek daysOfWeek) {
+        long alarm = Alarms.calculateAlarm(hour, minute,
+                                           daysOfWeek).getTimeInMillis();
+        long delta = alarm - System.currentTimeMillis();;
+        long hours = delta / (1000 * 60 * 60);
+        long minutes = delta / (1000 * 60) % 60;
+        long days = hours / 24;
+        hours = hours % 24;
+
+        String daySeq = (days == 0) ? "" :
+                (days == 1) ? context.getString(R.string.day) :
+                context.getString(R.string.days, Long.toString(days));
+
+        String minSeq = (minutes == 0) ? "" :
+                (minutes == 1) ? context.getString(R.string.minute) :
+                context.getString(R.string.minutes, Long.toString(minutes));
+
+        String hourSeq = (hours == 0) ? "" :
+                (hours == 1) ? context.getString(R.string.hour) :
+                context.getString(R.string.hours, Long.toString(hours));
+
+        boolean dispDays = days > 0;
+        boolean dispHour = hours > 0;
+        boolean dispMinute = minutes > 0;
+
+        String ret;
+        if (!(dispDays || dispHour || dispMinute)) {
+            ret = context.getString(R.string.subminute);
+        } else {
+            String parts[] = new String[5];
+            parts[0] = daySeq;
+            parts[1] = !dispDays ? "" :
+                    dispHour && dispMinute ? context.getString(R.string.space) :
+                    !dispHour && !dispMinute ? "" :
+                    context.getString(R.string.and);
+            parts[2] = dispHour ? hourSeq : "";
+            parts[3] = dispHour && dispMinute ? context.getString(R.string.and) : "";
+            parts[4] = dispMinute ? minSeq : "";
+            ret = context.getString(R.string.combiner, (Object[])parts);
+        }
+
+        ret = context.getString(R.string.alarm_set, ret);
+        /* if (Log.LOGV) Log.v("** TOAST daySeq " + daySeq + " hourSeq " + hourSeq +
+           " minSeq " + minSeq + " ret " + ret); */
+        return ret;
+    }
+
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+
+        mDeleteAlarmItem = menu.add(0, 0, 0, R.string.delete_alarm);
+        mDeleteAlarmItem.setIcon(android.R.drawable.ic_menu_delete);
+
+        if (AlarmClock.DEBUG) {
+            mTestAlarmItem = menu.add(0, 0, 0, "test alarm");
+        }
+
+
+        return true;
+    }
+
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item == mDeleteAlarmItem) {
+            Alarms.deleteAlarm(this, mId);
+            finish();
+            return true;
+        }
+        if (AlarmClock.DEBUG) {
+            if (item == mTestAlarmItem) {
+                setTestAlarm();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Test code: this is disabled for production build.  Sets
+     * this alarm to go off on the next minute
+     */
+    void setTestAlarm() {
+
+        // start with now
+        java.util.Calendar c = java.util.Calendar.getInstance();
+        c.setTimeInMillis(System.currentTimeMillis());
+
+        int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY);
+        int nowMinute = c.get(java.util.Calendar.MINUTE);
+
+        int minutes = (nowMinute + 1) % 60;
+        int hour = nowHour + (nowMinute == 0? 1 : 0);
+
+        saveAlarm(this, mId, true, hour, minutes, mDaysOfWeek, true,
+                  mAlarmPref.mAlert.toString(), true);
+    }
+
+}
diff --git a/src/com/android/alarmclock/ToastMaster.java b/src/com/android/alarmclock/ToastMaster.java
new file mode 100644 (file)
index 0000000..c4c2815
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 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.alarmclock;
+
+import android.widget.Toast;
+
+public class ToastMaster {
+
+    private static Toast sToast = null;
+
+    private ToastMaster() {
+
+    }
+
+    public static void setToast(Toast toast) {
+        if (sToast != null)
+            sToast.cancel();
+        sToast = toast;
+    }
+
+    public static void cancelToast() {
+        if (sToast != null)
+            sToast.cancel();
+        sToast = null;
+    }
+
+}