134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux/* 234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * Copyright (C) 2015 The Android Open Source Project 334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * 434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * Licensed under the Apache License, Version 2.0 (the "License"); 534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * you may not use this file except in compliance with the License. 634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * You may obtain a copy of the License at 734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * 834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * http://www.apache.org/licenses/LICENSE-2.0 934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * 1034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * Unless required by applicable law or agreed to in writing, software 1134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * distributed under the License is distributed on an "AS IS" BASIS, 1234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * See the License for the specific language governing permissions and 1434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * limitations under the License. 1534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 1634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 1734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuxpackage com.android.deskclock.data; 1834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 190dd0cac610cd59762c8b604da6c437b18a29246bJames Lemieuximport android.app.Service; 2034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuximport android.content.Context; 2125384711e3c2894a84642c49953594930dd078abJames Lemieuximport android.content.Intent; 2223629266834a251cb937a885e5223e5ae37cc6faChristine Franksimport android.content.SharedPreferences; 2325384711e3c2894a84642c49953594930dd078abJames Lemieuximport android.media.AudioManager; 24856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieuximport android.net.Uri; 25d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phanimport android.os.Handler; 26d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phanimport android.os.Looper; 276d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieuximport android.support.annotation.StringRes; 2825384711e3c2894a84642c49953594930dd078abJames Lemieuximport android.view.View; 2934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 302a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieuximport com.android.deskclock.Predicate; 3125384711e3c2894a84642c49953594930dd078abJames Lemieuximport com.android.deskclock.R; 3225384711e3c2894a84642c49953594930dd078abJames Lemieuximport com.android.deskclock.Utils; 330a3313e231702cc9944e9a17e52aea62eb25afabSean Stoutimport com.android.deskclock.timer.TimerService; 340a3313e231702cc9944e9a17e52aea62eb25afabSean Stout 35458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieuximport java.util.Calendar; 3634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuximport java.util.Collection; 3734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuximport java.util.Comparator; 3834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuximport java.util.List; 3934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 4025384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.content.Context.AUDIO_SERVICE; 4125384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 4225384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.media.AudioManager.FLAG_SHOW_UI; 4325384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.media.AudioManager.STREAM_ALARM; 4425384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS; 4525384711e3c2894a84642c49953594930dd078abJames Lemieuximport static android.provider.Settings.ACTION_SOUND_SETTINGS; 4634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuximport static com.android.deskclock.Utils.enforceMainLooper; 47c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieuximport static com.android.deskclock.Utils.enforceNotMainLooper; 4834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 4934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux/** 5034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * All application-wide data is accessible through this singleton. 5134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 5234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieuxpublic final class DataModel { 5334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 5434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** Indicates the display style of clocks. */ 5534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public enum ClockStyle {ANALOG, DIGITAL} 5634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 5734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** Indicates the preferred sort order of cities. */ 5834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public enum CitySort {NAME, UTC_OFFSET} 5934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 600777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** Indicates the preferred behavior of hardware volume buttons when firing alarms. */ 610777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public enum AlarmVolumeButtonBehavior {NOTHING, SNOOZE, DISMISS} 620777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 6325384711e3c2894a84642c49953594930dd078abJames Lemieux /** Indicates the reason alarms may not fire or may fire silently. */ 6425384711e3c2894a84642c49953594930dd078abJames Lemieux public enum SilentSetting { 6563669870c5677e73c61ae81dd7469abccb51d629James Lemieux @SuppressWarnings("unchecked") 662a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux DO_NOT_DISTURB(R.string.alarms_blocked_by_dnd, 0, Predicate.FALSE, null), 6763669870c5677e73c61ae81dd7469abccb51d629James Lemieux @SuppressWarnings("unchecked") 6825384711e3c2894a84642c49953594930dd078abJames Lemieux MUTED_VOLUME(R.string.alarm_volume_muted, 6925384711e3c2894a84642c49953594930dd078abJames Lemieux R.string.unmute_alarm_volume, 702a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux Predicate.TRUE, 7125384711e3c2894a84642c49953594930dd078abJames Lemieux new UnmuteAlarmVolumeListener()), 7225384711e3c2894a84642c49953594930dd078abJames Lemieux SILENT_RINGTONE(R.string.silent_default_alarm_ringtone, 7325384711e3c2894a84642c49953594930dd078abJames Lemieux R.string.change_setting_action, 742a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux new ChangeSoundActionPredicate(), 7525384711e3c2894a84642c49953594930dd078abJames Lemieux new ChangeSoundSettingsListener()), 7663669870c5677e73c61ae81dd7469abccb51d629James Lemieux @SuppressWarnings("unchecked") 7725384711e3c2894a84642c49953594930dd078abJames Lemieux BLOCKED_NOTIFICATIONS(R.string.app_notifications_blocked, 7825384711e3c2894a84642c49953594930dd078abJames Lemieux R.string.change_setting_action, 792a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux Predicate.TRUE, 8025384711e3c2894a84642c49953594930dd078abJames Lemieux new ChangeAppNotificationSettingsListener()); 8125384711e3c2894a84642c49953594930dd078abJames Lemieux 8225384711e3c2894a84642c49953594930dd078abJames Lemieux private final @StringRes int mLabelResId; 8325384711e3c2894a84642c49953594930dd078abJames Lemieux private final @StringRes int mActionResId; 842a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux private final Predicate<Context> mActionEnabled; 8525384711e3c2894a84642c49953594930dd078abJames Lemieux private final View.OnClickListener mActionListener; 8625384711e3c2894a84642c49953594930dd078abJames Lemieux 872a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux SilentSetting(int labelResId, int actionResId, Predicate<Context> actionEnabled, 882a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux View.OnClickListener actionListener) { 8925384711e3c2894a84642c49953594930dd078abJames Lemieux mLabelResId = labelResId; 9025384711e3c2894a84642c49953594930dd078abJames Lemieux mActionResId = actionResId; 912a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux mActionEnabled = actionEnabled; 9225384711e3c2894a84642c49953594930dd078abJames Lemieux mActionListener = actionListener; 9325384711e3c2894a84642c49953594930dd078abJames Lemieux } 9425384711e3c2894a84642c49953594930dd078abJames Lemieux 9525384711e3c2894a84642c49953594930dd078abJames Lemieux public @StringRes int getLabelResId() { return mLabelResId; } 9625384711e3c2894a84642c49953594930dd078abJames Lemieux public @StringRes int getActionResId() { return mActionResId; } 9725384711e3c2894a84642c49953594930dd078abJames Lemieux public View.OnClickListener getActionListener() { return mActionListener; } 982a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux public boolean isActionEnabled(Context context) { 992a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux return mLabelResId != 0 && mActionEnabled.apply(context); 1002a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux } 10125384711e3c2894a84642c49953594930dd078abJames Lemieux 10225384711e3c2894a84642c49953594930dd078abJames Lemieux private static class UnmuteAlarmVolumeListener implements View.OnClickListener { 10325384711e3c2894a84642c49953594930dd078abJames Lemieux @Override 10425384711e3c2894a84642c49953594930dd078abJames Lemieux public void onClick(View v) { 105df466cea0899b6dd2efd3ebd961c614486b639d0James Lemieux // Set the alarm volume to 11/16th of max and show the slider UI. 106df466cea0899b6dd2efd3ebd961c614486b639d0James Lemieux // 11/16th of max is the initial volume of the alarm stream on a fresh install. 10725384711e3c2894a84642c49953594930dd078abJames Lemieux final Context context = v.getContext(); 10825384711e3c2894a84642c49953594930dd078abJames Lemieux final AudioManager am = (AudioManager) context.getSystemService(AUDIO_SERVICE); 109df466cea0899b6dd2efd3ebd961c614486b639d0James Lemieux final int index = Math.round(am.getStreamMaxVolume(STREAM_ALARM) * 11f / 16f); 11025384711e3c2894a84642c49953594930dd078abJames Lemieux am.setStreamVolume(STREAM_ALARM, index, FLAG_SHOW_UI); 11125384711e3c2894a84642c49953594930dd078abJames Lemieux } 112ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux } 11325384711e3c2894a84642c49953594930dd078abJames Lemieux 11425384711e3c2894a84642c49953594930dd078abJames Lemieux private static class ChangeSoundSettingsListener implements View.OnClickListener { 11525384711e3c2894a84642c49953594930dd078abJames Lemieux @Override 11625384711e3c2894a84642c49953594930dd078abJames Lemieux public void onClick(View v) { 11725384711e3c2894a84642c49953594930dd078abJames Lemieux final Context context = v.getContext(); 11825384711e3c2894a84642c49953594930dd078abJames Lemieux context.startActivity(new Intent(ACTION_SOUND_SETTINGS) 11925384711e3c2894a84642c49953594930dd078abJames Lemieux .addFlags(FLAG_ACTIVITY_NEW_TASK)); 12025384711e3c2894a84642c49953594930dd078abJames Lemieux } 121ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux } 12225384711e3c2894a84642c49953594930dd078abJames Lemieux 1232a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux private static class ChangeSoundActionPredicate implements Predicate<Context> { 1242a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux @Override 1252a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux public boolean apply(Context context) { 1262a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux final Intent intent = new Intent(ACTION_SOUND_SETTINGS); 1272a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux return intent.resolveActivity(context.getPackageManager()) != null; 1282a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux } 1292a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux } 1302a138d4a772ad8cf1d3e9cd9682d69f4f8d49db6James Lemieux 13125384711e3c2894a84642c49953594930dd078abJames Lemieux private static class ChangeAppNotificationSettingsListener implements View.OnClickListener { 13225384711e3c2894a84642c49953594930dd078abJames Lemieux @Override 13325384711e3c2894a84642c49953594930dd078abJames Lemieux public void onClick(View v) { 13425384711e3c2894a84642c49953594930dd078abJames Lemieux final Context context = v.getContext(); 13525384711e3c2894a84642c49953594930dd078abJames Lemieux if (Utils.isLOrLater()) { 13625384711e3c2894a84642c49953594930dd078abJames Lemieux try { 13725384711e3c2894a84642c49953594930dd078abJames Lemieux // Attempt to open the notification settings for this app. 13825384711e3c2894a84642c49953594930dd078abJames Lemieux context.startActivity( 13925384711e3c2894a84642c49953594930dd078abJames Lemieux new Intent("android.settings.APP_NOTIFICATION_SETTINGS") 14025384711e3c2894a84642c49953594930dd078abJames Lemieux .putExtra("app_package", context.getPackageName()) 14125384711e3c2894a84642c49953594930dd078abJames Lemieux .putExtra("app_uid", context.getApplicationInfo().uid) 14225384711e3c2894a84642c49953594930dd078abJames Lemieux .addFlags(FLAG_ACTIVITY_NEW_TASK)); 14325384711e3c2894a84642c49953594930dd078abJames Lemieux return; 14425384711e3c2894a84642c49953594930dd078abJames Lemieux } catch (Exception ignored) { 14525384711e3c2894a84642c49953594930dd078abJames Lemieux // best attempt only; recovery code below 14625384711e3c2894a84642c49953594930dd078abJames Lemieux } 14725384711e3c2894a84642c49953594930dd078abJames Lemieux } 14825384711e3c2894a84642c49953594930dd078abJames Lemieux 14925384711e3c2894a84642c49953594930dd078abJames Lemieux // Fall back to opening the app settings page. 15025384711e3c2894a84642c49953594930dd078abJames Lemieux context.startActivity(new Intent(ACTION_APPLICATION_DETAILS_SETTINGS) 15125384711e3c2894a84642c49953594930dd078abJames Lemieux .setData(Uri.fromParts("package", context.getPackageName(), null)) 15225384711e3c2894a84642c49953594930dd078abJames Lemieux .addFlags(FLAG_ACTIVITY_NEW_TASK)); 15325384711e3c2894a84642c49953594930dd078abJames Lemieux } 154ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux } 15525384711e3c2894a84642c49953594930dd078abJames Lemieux } 15625384711e3c2894a84642c49953594930dd078abJames Lemieux 1578bf1c3ba34724773b92242effec8330e1852bb7bJames Lemieux public static final String ACTION_WORLD_CITIES_CHANGED = 1588bf1c3ba34724773b92242effec8330e1852bb7bJames Lemieux "com.android.deskclock.WORLD_CITIES_CHANGED"; 1598bf1c3ba34724773b92242effec8330e1852bb7bJames Lemieux 16034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** The single instance of this data model that exists for the life of the application. */ 16134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux private static final DataModel sDataModel = new DataModel(); 16234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 163d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private Handler mHandler; 164d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 16534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux private Context mContext; 16634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 16734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** The model from which settings are fetched. */ 16834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux private SettingsModel mSettingsModel; 16934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 170856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux /** The model from which city data are fetched. */ 17134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux private CityModel mCityModel; 17234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 173856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux /** The model from which timer data are fetched. */ 174856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux private TimerModel mTimerModel; 175856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux 1766a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux /** The model from which alarm data are fetched. */ 1776a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux private AlarmModel mAlarmModel; 1786a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux 179592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux /** The model from which widget data are fetched. */ 180592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux private WidgetModel mWidgetModel; 181592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux 18225384711e3c2894a84642c49953594930dd078abJames Lemieux /** The model from which data about settings that silence alarms are fetched. */ 18325384711e3c2894a84642c49953594930dd078abJames Lemieux private SilentSettingsModel mSilentSettingsModel; 18425384711e3c2894a84642c49953594930dd078abJames Lemieux 18524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** The model from which stopwatch data are fetched. */ 18624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux private StopwatchModel mStopwatchModel; 18724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 18824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** The model from which notification data are fetched. */ 18924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux private NotificationModel mNotificationModel; 19024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 191be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout /** The model from which time data are fetched. */ 192be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout private TimeModel mTimeModel; 193be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout 19433781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux /** The model from which ringtone data are fetched. */ 19533781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux private RingtoneModel mRingtoneModel; 19633781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 19734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public static DataModel getDataModel() { 19834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return sDataModel; 19934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 20034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 20134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux private DataModel() {} 20234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 20334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 204ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux * Initializes the data model with the context and shared preferences to be used. 20534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 206ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux public void init(Context context, SharedPreferences prefs) { 207310f96ed002219067d2e652e27d64d256e315832James Lemieux if (mContext != context) { 208310f96ed002219067d2e652e27d64d256e315832James Lemieux mContext = context.getApplicationContext(); 209310f96ed002219067d2e652e27d64d256e315832James Lemieux 2100b19985ecfa0f43acb8ededc173f643843098a95James Lemieux mTimeModel = new TimeModel(mContext); 211ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux mWidgetModel = new WidgetModel(prefs); 212310f96ed002219067d2e652e27d64d256e315832James Lemieux mNotificationModel = new NotificationModel(); 21384b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux mRingtoneModel = new RingtoneModel(mContext, prefs); 21484b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux mSettingsModel = new SettingsModel(mContext, prefs, mTimeModel); 215ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux mCityModel = new CityModel(mContext, prefs, mSettingsModel); 216310f96ed002219067d2e652e27d64d256e315832James Lemieux mAlarmModel = new AlarmModel(mContext, mSettingsModel); 21725384711e3c2894a84642c49953594930dd078abJames Lemieux mSilentSettingsModel = new SilentSettingsModel(mContext, mNotificationModel); 218ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux mStopwatchModel = new StopwatchModel(mContext, prefs, mNotificationModel); 219ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux mTimerModel = new TimerModel(mContext, prefs, mSettingsModel, mRingtoneModel, 220ff62e7fa903e3b6b11d0443543725c1351ab289dJames Lemieux mNotificationModel); 22123629266834a251cb937a885e5223e5ae37cc6faChristine Franks } 22223629266834a251cb937a885e5223e5ae37cc6faChristine Franks } 22323629266834a251cb937a885e5223e5ae37cc6faChristine Franks 22423629266834a251cb937a885e5223e5ae37cc6faChristine Franks /** 225a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen * Convenience for {@code run(runnable, 0)}, i.e. waits indefinitely. 226a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen */ 227a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen public void run(Runnable runnable) { 228a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen try { 229a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen run(runnable, 0 /* waitMillis */); 230a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen } catch (InterruptedException ignored) { 231a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen } 232a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen } 233a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen 234a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen /** 2352a07ae3286fd5c76f71546890e0f02af99065825Sean Stout * Updates all timers and the stopwatch after the device has shutdown and restarted. 2362a07ae3286fd5c76f71546890e0f02af99065825Sean Stout */ 2372a07ae3286fd5c76f71546890e0f02af99065825Sean Stout public void updateAfterReboot() { 2382a07ae3286fd5c76f71546890e0f02af99065825Sean Stout enforceMainLooper(); 2392a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.updateTimersAfterReboot(); 2402a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mStopwatchModel.setStopwatch(getStopwatch().updateAfterReboot()); 2412a07ae3286fd5c76f71546890e0f02af99065825Sean Stout } 2422a07ae3286fd5c76f71546890e0f02af99065825Sean Stout 2432a07ae3286fd5c76f71546890e0f02af99065825Sean Stout /** 2442a07ae3286fd5c76f71546890e0f02af99065825Sean Stout * Updates all timers and the stopwatch after the device's time has changed. 2452a07ae3286fd5c76f71546890e0f02af99065825Sean Stout */ 2462a07ae3286fd5c76f71546890e0f02af99065825Sean Stout public void updateAfterTimeSet() { 2472a07ae3286fd5c76f71546890e0f02af99065825Sean Stout enforceMainLooper(); 2482a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.updateTimersAfterTimeSet(); 2492a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mStopwatchModel.setStopwatch(getStopwatch().updateAfterTimeSet()); 2502a07ae3286fd5c76f71546890e0f02af99065825Sean Stout } 2512a07ae3286fd5c76f71546890e0f02af99065825Sean Stout 2522a07ae3286fd5c76f71546890e0f02af99065825Sean Stout /** 253d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan * Posts a runnable to the main thread and blocks until the runnable executes. Used to access 254d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan * the data model from the main thread. 255d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan */ 256a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen public void run(Runnable runnable, long waitMillis) throws InterruptedException { 257d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan if (Looper.myLooper() == Looper.getMainLooper()) { 258d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan runnable.run(); 259d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan return; 260d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 261d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 262d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan final ExecutedRunnable er = new ExecutedRunnable(runnable); 263d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan getHandler().post(er); 264d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 265d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan // Wait for the data to arrive, if it has not. 266d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan synchronized (er) { 267d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan if (!er.isExecuted()) { 268a5c107781dc8f8239bc980d19e1e31ed262e8829Justin Klaassen er.wait(waitMillis); 269d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 270d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 271d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 272d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 273d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan /** 274d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan * @return a handler associated with the main thread 275d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan */ 276d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private synchronized Handler getHandler() { 277d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan if (mHandler == null) { 278d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan mHandler = new Handler(Looper.getMainLooper()); 279d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 280d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan return mHandler; 281d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 282d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 28324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // 28424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // Application 28524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // 28624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 28724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 28824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @param inForeground {@code true} to indicate the application is open in the foreground 28924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 29024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public void setApplicationInForeground(boolean inForeground) { 29124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 29224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 29324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux if (mNotificationModel.isApplicationInForeground() != inForeground) { 29424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux mNotificationModel.setApplicationInForeground(inForeground); 29524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 29624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // Refresh all notifications in response to a change in app open state. 2976d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.updateNotification(); 2982a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.updateMissedNotification(); 29924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux mStopwatchModel.updateNotification(); 30025384711e3c2894a84642c49953594930dd078abJames Lemieux mSilentSettingsModel.updateSilentState(); 30124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 30224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 30324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 30424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 30524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return {@code true} when the application is open in the foreground; {@code false} otherwise 30624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 30724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public boolean isApplicationInForeground() { 3083101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan enforceMainLooper(); 30924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mNotificationModel.isApplicationInForeground(); 31034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 31134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 312ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux /** 313ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux * Called when the notifications may be stale or absent from the notification manager and must 314ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux * be rebuilt. e.g. after upgrading the application 315ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux */ 316ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux public void updateAllNotifications() { 317376b0f51995803a93d7a6907f8ed30aff06e2aaeJames Lemieux enforceMainLooper(); 318ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux mTimerModel.updateNotification(); 3192a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.updateMissedNotification(); 320ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux mStopwatchModel.updateNotification(); 321ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux } 322ac1506f175631e2b2f52ff9142cbdc6c725ef447James Lemieux 32334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // 32434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // Cities 32534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // 32634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 32734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 32834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return a list of all cities in their display order 32934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 33034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public List<City> getAllCities() { 33134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 33234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getAllCities(); 33334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 33434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 33534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 33634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return a city representing the user's home timezone 33734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 33834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public City getHomeCity() { 33934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 34034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getHomeCity(); 34134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 34234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 34334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 34434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return a list of cities not selected for display 34534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 34634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public List<City> getUnselectedCities() { 34734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 34834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getUnselectedCities(); 34934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 35034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 35134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 35234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return a list of cities selected for display 35334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 35434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public List<City> getSelectedCities() { 35534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 35634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getSelectedCities(); 35734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 35834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 35934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 36034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @param cities the new collection of cities selected for display by the user 36134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 36234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public void setSelectedCities(Collection<City> cities) { 36334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 36434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux mCityModel.setSelectedCities(cities); 36534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 36634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 36734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 36834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return a comparator used to locate index positions 36934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 37034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public Comparator<City> getCityIndexComparator() { 37134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 37234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getCityIndexComparator(); 37334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 37434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 37534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 37634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return the order in which cities are sorted 37734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 37834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public CitySort getCitySort() { 37934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 38034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mCityModel.getCitySort(); 38134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 38234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 38334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 38434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * Adjust the order in which cities are sorted. 38534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 38634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public void toggleCitySort() { 38734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 38834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux mCityModel.toggleCitySort(); 38934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 39034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 391a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout /** 392a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout * @param cityListener listener to be notified when the world city list changes 393a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout */ 394a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout public void addCityListener(CityListener cityListener) { 395a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout enforceMainLooper(); 396a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout mCityModel.addCityListener(cityListener); 397a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout } 398a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout 399a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout /** 400a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout * @param cityListener listener that no longer needs to be notified of world city list changes 401a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout */ 402a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout public void removeCityListener(CityListener cityListener) { 403a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout enforceMainLooper(); 404a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout mCityModel.removeCityListener(cityListener); 405a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout } 406a10158df7b7e056ec5c63df9cfaacd88d0e79c7fSean Stout 40734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // 408856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux // Timers 409856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux // 410856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux 411856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux /** 4126d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timerListener to be notified when timers are added, updated and removed 4136d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4146d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void addTimerListener(TimerListener timerListener) { 4156d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4166d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.addTimerListener(timerListener); 4176d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4186d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4196d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4206d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timerListener to no longer be notified when timers are added, updated and removed 4216d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4226d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void removeTimerListener(TimerListener timerListener) { 4236d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4246d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.removeTimerListener(timerListener); 4256d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4266d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4276d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4286d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @return a list of timers for display 4296d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4306d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public List<Timer> getTimers() { 4316d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4326d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux return mTimerModel.getTimers(); 4336d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4346d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4356d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4366d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @return a list of expired timers for display 4376d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4386d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public List<Timer> getExpiredTimers() { 4396d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4406d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux return mTimerModel.getExpiredTimers(); 4416d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4426d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4436d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4446d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timerId identifies the timer to return 4456d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @return the timer with the given {@code timerId} 4466d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4476d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public Timer getTimer(int timerId) { 4486d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4496d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux return mTimerModel.getTimer(timerId); 4506d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4516d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4526d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4536d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @return the timer that last expired and is still expired now; {@code null} if no timers are 4546d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * expired 4556d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4566d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public Timer getMostRecentExpiredTimer() { 4576d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4586d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux return mTimerModel.getMostRecentExpiredTimer(); 4596d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4606d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4616d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4626d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param length the length of the timer in milliseconds 4636d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param label describes the purpose of the timer 464437da3b08ce9ce1b32f4e544816cb3431ceb8d4eJames Lemieux * @param deleteAfterUse {@code true} indicates the timer should be deleted when it is reset 4656d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @return the newly added timer 4666d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 467437da3b08ce9ce1b32f4e544816cb3431ceb8d4eJames Lemieux public Timer addTimer(long length, String label, boolean deleteAfterUse) { 4686d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 469437da3b08ce9ce1b32f4e544816cb3431ceb8d4eJames Lemieux return mTimerModel.addTimer(length, label, deleteAfterUse); 4706d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4716d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4726d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4736d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to be removed 4746d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4756d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void removeTimer(Timer timer) { 4766d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4776d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.removeTimer(timer); 4786d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 4796d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 4806d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 4816d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to be started 4826d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 4836d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void startTimer(Timer timer) { 4840a3313e231702cc9944e9a17e52aea62eb25afabSean Stout startTimer(null, timer); 4850a3313e231702cc9944e9a17e52aea62eb25afabSean Stout } 4860a3313e231702cc9944e9a17e52aea62eb25afabSean Stout 4870a3313e231702cc9944e9a17e52aea62eb25afabSean Stout /** 4880a3313e231702cc9944e9a17e52aea62eb25afabSean Stout * @param service used to start foreground notifications for expired timers 4890a3313e231702cc9944e9a17e52aea62eb25afabSean Stout * @param timer the timer to be started 4900a3313e231702cc9944e9a17e52aea62eb25afabSean Stout */ 4910a3313e231702cc9944e9a17e52aea62eb25afabSean Stout public void startTimer(Service service, Timer timer) { 4926d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 4930a3313e231702cc9944e9a17e52aea62eb25afabSean Stout final Timer started = timer.start(); 4940a3313e231702cc9944e9a17e52aea62eb25afabSean Stout mTimerModel.updateTimer(started); 4950a3313e231702cc9944e9a17e52aea62eb25afabSean Stout if (timer.getRemainingTime() <= 0) { 4960a3313e231702cc9944e9a17e52aea62eb25afabSean Stout if (service != null) { 4970a3313e231702cc9944e9a17e52aea62eb25afabSean Stout expireTimer(service, started); 4980a3313e231702cc9944e9a17e52aea62eb25afabSean Stout } else { 4990a3313e231702cc9944e9a17e52aea62eb25afabSean Stout mContext.startService(TimerService.createTimerExpiredIntent(mContext, started)); 5000a3313e231702cc9944e9a17e52aea62eb25afabSean Stout } 5010a3313e231702cc9944e9a17e52aea62eb25afabSean Stout } 5026d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5036d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5046d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5056d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to be paused 5066d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5076d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void pauseTimer(Timer timer) { 5086d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5096d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.updateTimer(timer.pause()); 5106d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5116d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5126d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5130dd0cac610cd59762c8b604da6c437b18a29246bJames Lemieux * @param service used to start foreground notifications for expired timers 5146d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to be expired 5156d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5160dd0cac610cd59762c8b604da6c437b18a29246bJames Lemieux public void expireTimer(Service service, Timer timer) { 5176d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5180dd0cac610cd59762c8b604da6c437b18a29246bJames Lemieux mTimerModel.expireTimer(service, timer); 5196d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5206d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5216d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 52212540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen * @param timer the timer to be reset 52312540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen * @return the reset {@code timer} 52412540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen */ 52512540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen public Timer resetTimer(Timer timer) { 52612540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen enforceMainLooper(); 52712540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen return mTimerModel.resetTimer(timer, false /* allowDelete */, 0 /* eventLabelId */); 52812540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen } 52912540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen 53012540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen /** 5316d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * If the given {@code timer} is expired and marked for deletion after use then this method 5326d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * removes the the timer. The timer is otherwise transitioned to the reset state and continues 5336d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * to exist. 5346d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * 5356d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to be reset 5366d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param eventLabelId the label of the timer event to send; 0 if no event should be sent 537b10e1abe917de457e9cb3be12ffd5d2634d8f79cJames Lemieux * @return the reset {@code timer} or {@code null} if the timer was deleted 5386d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 539b10e1abe917de457e9cb3be12ffd5d2634d8f79cJames Lemieux public Timer resetOrDeleteTimer(Timer timer, @StringRes int eventLabelId) { 5406d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 54112540ba3d8802d36c3893c6b88300c6a391d7d22Justin Klaassen return mTimerModel.resetTimer(timer, true /* allowDelete */, eventLabelId); 5426d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5436d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5446d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5452a07ae3286fd5c76f71546890e0f02af99065825Sean Stout * Resets all expired timers. 5466d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * 5476d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param eventLabelId the label of the timer event to send; 0 if no event should be sent 5486d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5492cfca77929657240f985a26ee59c389998cf3ab6Christine Franks public void resetOrDeleteExpiredTimers(@StringRes int eventLabelId) { 5506d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5512cfca77929657240f985a26ee59c389998cf3ab6Christine Franks mTimerModel.resetOrDeleteExpiredTimers(eventLabelId); 5526d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5536d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5546d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5552a07ae3286fd5c76f71546890e0f02af99065825Sean Stout * Resets all unexpired timers. 5566d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * 5576d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param eventLabelId the label of the timer event to send; 0 if no event should be sent 5586d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5592a07ae3286fd5c76f71546890e0f02af99065825Sean Stout public void resetUnexpiredTimers(@StringRes int eventLabelId) { 5606d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5612a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.resetUnexpiredTimers(eventLabelId); 5626d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5636d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5646d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5652a07ae3286fd5c76f71546890e0f02af99065825Sean Stout * Resets all missed timers. 5666d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * 5676d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param eventLabelId the label of the timer event to send; 0 if no event should be sent 5686d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5692a07ae3286fd5c76f71546890e0f02af99065825Sean Stout public void resetMissedTimers(@StringRes int eventLabelId) { 5706d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5712a07ae3286fd5c76f71546890e0f02af99065825Sean Stout mTimerModel.resetMissedTimers(eventLabelId); 5726d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5736d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5746d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5756d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to which a minute should be added to the remaining time 5766d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5776d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void addTimerMinute(Timer timer) { 5786d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5796d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.updateTimer(timer.addMinute()); 5806d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5816d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5826d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 5836d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param timer the timer to which the new {@code label} belongs 5846d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * @param label the new label to store for the {@code timer} 5856d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 5866d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void setTimerLabel(Timer timer, String label) { 5876d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 5886d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.updateTimer(timer.setLabel(label)); 5896d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 5906d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 5916d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 59258d9315aed4f645eb60c22be117b074e18c0982fJames Lemieux * @param timer the timer whose {@code length} to change 593705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen * @param length the new length of the timer in milliseconds 594705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen */ 595705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen public void setTimerLength(Timer timer, long length) { 596705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen enforceMainLooper(); 597705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen mTimerModel.updateTimer(timer.setLength(length)); 598705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen } 599705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen 600705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen /** 60158d9315aed4f645eb60c22be117b074e18c0982fJames Lemieux * @param timer the timer whose {@code remainingTime} to change 602705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen * @param remainingTime the new remaining time of the timer in milliseconds 603705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen */ 604705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen public void setRemainingTime(Timer timer, long remainingTime) { 605705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen enforceMainLooper(); 606705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen 607705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen final Timer updated = timer.setRemainingTime(remainingTime); 608705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen mTimerModel.updateTimer(updated); 609705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen if (timer.isRunning() && timer.getRemainingTime() <= 0) { 610705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen mContext.startService(TimerService.createTimerExpiredIntent(mContext, updated)); 611705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen } 612705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen } 613705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen 614705928dc4b0ed61e28d7f2807d5af3aaa9075806Justin Klaassen /** 6156d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux * Updates the timer notifications to be current. 6166d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux */ 6176d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux public void updateTimerNotification() { 6186d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux enforceMainLooper(); 6196d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux mTimerModel.updateNotification(); 6206d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux } 6216d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux 6226d603b7c62bb38d763a681a8bf20fadb1442e833James Lemieux /** 623bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux * @return the uri of the default ringtone to play for all timers when no user selection exists 624bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux */ 625bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux public Uri getDefaultTimerRingtoneUri() { 626bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux enforceMainLooper(); 627bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux return mTimerModel.getDefaultTimerRingtoneUri(); 628bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux } 629bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux 630bd9eae10b13e015d1997d06f13e9abe06a7f306bJames Lemieux /** 631f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux * @return {@code true} iff the ringtone to play for all timers is the silent ringtone 632f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux */ 633f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux public boolean isTimerRingtoneSilent() { 634f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux enforceMainLooper(); 635f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux return mTimerModel.isTimerRingtoneSilent(); 636f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux } 637f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux 638f8faca1961278db2797d122351885ce6e32e4f3dJames Lemieux /** 639856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux * @return the uri of the ringtone to play for all timers 640856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux */ 641856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux public Uri getTimerRingtoneUri() { 642856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux enforceMainLooper(); 643856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux return mTimerModel.getTimerRingtoneUri(); 644856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux } 645856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux 646856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux /** 6473101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan * @param uri the uri of the ringtone to play for all timers 6483101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan */ 6493101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan public void setTimerRingtoneUri(Uri uri) { 6503101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan enforceMainLooper(); 6513101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan mTimerModel.setTimerRingtoneUri(uri); 6523101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan } 6533101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan 6543101fcf76ff5c228d2e643395be03d6cbf97d47eDylan Phan /** 655856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux * @return the title of the ringtone that is played for all timers 656856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux */ 657856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux public String getTimerRingtoneTitle() { 658856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux enforceMainLooper(); 659856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux return mTimerModel.getTimerRingtoneTitle(); 660856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux } 661856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux 66209c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin /** 6630777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the duration, in milliseconds, of the crescendo to apply to timer ringtone playback; 6640777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * {@code 0} implies no crescendo should be applied 6650777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 6660777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public long getTimerCrescendoDuration() { 6670777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux enforceMainLooper(); 6680777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mTimerModel.getTimerCrescendoDuration(); 6690777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 6700777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 6710777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 67209c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin * @return whether vibrate is enabled for all timers. 67309c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin */ 67409c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin public boolean getTimerVibrate() { 67509c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin enforceMainLooper(); 67609c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin return mTimerModel.getTimerVibrate(); 67709c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin } 67809c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin 67909c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin /** 68009c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin * @param enabled whether vibrate is enabled for all timers. 68109c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin */ 68209c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin public void setTimerVibrate(boolean enabled) { 68309c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin enforceMainLooper(); 68409c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin mTimerModel.setTimerVibrate(enabled); 68509c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin } 68609c1f0e96743fcde110ecd1160ab55cdfaec12c0Annie Chin 687856483e7e18d5f042a338f7b3d472e28a386c4adJames Lemieux // 6886a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux // Alarms 6896a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux // 6906a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux 6916a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux /** 6926a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * @return the uri of the ringtone to which all new alarms default 6936a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux */ 6946a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux public Uri getDefaultAlarmRingtoneUri() { 6956a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux enforceMainLooper(); 6966a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux return mAlarmModel.getDefaultAlarmRingtoneUri(); 6976a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux } 6986a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux 6996a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux /** 7006a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * @param uri the uri of the ringtone to which future new alarms will default 7016a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux */ 7026a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux public void setDefaultAlarmRingtoneUri(Uri uri) { 7036a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux enforceMainLooper(); 7046a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux mAlarmModel.setDefaultAlarmRingtoneUri(uri); 7056a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux } 7066a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux 7070777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 7080777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the duration, in milliseconds, of the crescendo to apply to alarm ringtone playback; 7090777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * {@code 0} implies no crescendo should be applied 7100777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 7110777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public long getAlarmCrescendoDuration() { 7120777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux enforceMainLooper(); 7130777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mAlarmModel.getAlarmCrescendoDuration(); 7140777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 7150777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 7160777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 7170777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the behavior to execute when volume buttons are pressed while firing an alarm 7180777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 7190777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public AlarmVolumeButtonBehavior getAlarmVolumeButtonBehavior() { 7200777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux enforceMainLooper(); 7210777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mAlarmModel.getAlarmVolumeButtonBehavior(); 7220777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 7230777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 7240777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 7250777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the number of minutes an alarm may ring before it has timed out and becomes missed 7260777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 7270777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public int getAlarmTimeout() { 7280777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mAlarmModel.getAlarmTimeout(); 7290777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 7300777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 7310777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 7320777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the number of minutes an alarm will remain snoozed before it rings again 7330777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 7340777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public int getSnoozeLength() { 7350777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mAlarmModel.getSnoozeLength(); 7360777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 7370777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 7386a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux // 73924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // Stopwatch 74024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // 74124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 74224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 7439042b0b548db623f7f465767008a27d305299aa9James Lemieux * @param stopwatchListener to be notified when stopwatch changes or laps are added 7449042b0b548db623f7f465767008a27d305299aa9James Lemieux */ 7459042b0b548db623f7f465767008a27d305299aa9James Lemieux public void addStopwatchListener(StopwatchListener stopwatchListener) { 7469042b0b548db623f7f465767008a27d305299aa9James Lemieux enforceMainLooper(); 7479042b0b548db623f7f465767008a27d305299aa9James Lemieux mStopwatchModel.addStopwatchListener(stopwatchListener); 7489042b0b548db623f7f465767008a27d305299aa9James Lemieux } 7499042b0b548db623f7f465767008a27d305299aa9James Lemieux 7509042b0b548db623f7f465767008a27d305299aa9James Lemieux /** 7519042b0b548db623f7f465767008a27d305299aa9James Lemieux * @param stopwatchListener to no longer be notified when stopwatch changes or laps are added 7529042b0b548db623f7f465767008a27d305299aa9James Lemieux */ 7539042b0b548db623f7f465767008a27d305299aa9James Lemieux public void removeStopwatchListener(StopwatchListener stopwatchListener) { 7549042b0b548db623f7f465767008a27d305299aa9James Lemieux enforceMainLooper(); 7559042b0b548db623f7f465767008a27d305299aa9James Lemieux mStopwatchModel.removeStopwatchListener(stopwatchListener); 7569042b0b548db623f7f465767008a27d305299aa9James Lemieux } 7579042b0b548db623f7f465767008a27d305299aa9James Lemieux 7589042b0b548db623f7f465767008a27d305299aa9James Lemieux /** 75924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the current state of the stopwatch 76024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 76124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public Stopwatch getStopwatch() { 76224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 76324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.getStopwatch(); 76424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 76524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 76624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 76724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the stopwatch after being started 76824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 76924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public Stopwatch startStopwatch() { 77024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 77124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.setStopwatch(getStopwatch().start()); 77224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 77324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 77424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 77524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the stopwatch after being paused 77624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 77724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public Stopwatch pauseStopwatch() { 77824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 77924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.setStopwatch(getStopwatch().pause()); 78024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 78124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 78224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 78324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the stopwatch after being reset 78424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 78524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public Stopwatch resetStopwatch() { 78624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 78724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.setStopwatch(getStopwatch().reset()); 78824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 78924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 79024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 79124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the laps recorded for this stopwatch 79224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 79324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public List<Lap> getLaps() { 79424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 79524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.getLaps(); 79624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 79724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 79824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 79924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return a newly recorded lap completed now; {@code null} if no more laps can be added 80024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 80124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public Lap addLap() { 80224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 80324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.addLap(); 80424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 80524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 80624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 80724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return {@code true} iff more laps can be recorded 80824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 80924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public boolean canAddMoreLaps() { 81024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 81124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.canAddMoreLaps(); 81224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 81324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 81424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 81524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the longest lap time of all recorded laps and the current lap 81624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 81724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public long getLongestLapTime() { 81824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 81924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.getLongestLapTime(); 82024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 82124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 82224a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux /** 82324a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @param time a point in time after the end of the last lap 82424a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux * @return the elapsed time between the given {@code time} and the end of the previous lap 82524a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux */ 82624a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux public long getCurrentLapTime(long time) { 82724a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux enforceMainLooper(); 82824a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux return mStopwatchModel.getCurrentLapTime(time); 82924a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux } 83024a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux 83124a54fc16fdf95ee3f76ab99978c3401473dc516James Lemieux // 832be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout // Time 8330b19985ecfa0f43acb8ededc173f643843098a95James Lemieux // (Time settings/values are accessible from any Thread so no Thread-enforcement exists.) 834be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout // 835be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout 836be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout /** 8370b19985ecfa0f43acb8ededc173f643843098a95James Lemieux * @return the current time in milliseconds 838be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout */ 839be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout public long currentTimeMillis() { 840be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout return mTimeModel.currentTimeMillis(); 841be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout } 842be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout 843be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout /** 8440b19985ecfa0f43acb8ededc173f643843098a95James Lemieux * @return milliseconds since boot, including time spent in sleep 845be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout */ 846be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout public long elapsedRealtime() { 847be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout return mTimeModel.elapsedRealtime(); 848be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout } 849be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout 8500b19985ecfa0f43acb8ededc173f643843098a95James Lemieux /** 8510b19985ecfa0f43acb8ededc173f643843098a95James Lemieux * @return {@code true} if 24 hour time format is selected; {@code false} otherwise 8520b19985ecfa0f43acb8ededc173f643843098a95James Lemieux */ 8530b19985ecfa0f43acb8ededc173f643843098a95James Lemieux public boolean is24HourFormat() { 8540b19985ecfa0f43acb8ededc173f643843098a95James Lemieux return mTimeModel.is24HourFormat(); 8550b19985ecfa0f43acb8ededc173f643843098a95James Lemieux } 8560b19985ecfa0f43acb8ededc173f643843098a95James Lemieux 8570b19985ecfa0f43acb8ededc173f643843098a95James Lemieux /** 8580b19985ecfa0f43acb8ededc173f643843098a95James Lemieux * @return a new calendar object initialized to the {@link #currentTimeMillis()} 8590b19985ecfa0f43acb8ededc173f643843098a95James Lemieux */ 8600b19985ecfa0f43acb8ededc173f643843098a95James Lemieux public Calendar getCalendar() { 8610b19985ecfa0f43acb8ededc173f643843098a95James Lemieux return mTimeModel.getCalendar(); 8620b19985ecfa0f43acb8ededc173f643843098a95James Lemieux } 8630b19985ecfa0f43acb8ededc173f643843098a95James Lemieux 864be74d5fefb57de5ec6bb986bb3ef6f2874da5a00Sean Stout // 86533781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux // Ringtones 86633781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux // 86733781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 86833781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux /** 869c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux * Ringtone titles are cached because loading them is expensive. This method 870c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux * <strong>must</strong> be called on a background thread and is responsible for priming the 871c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux * cache of ringtone titles to avoid later fetching titles on the main thread. 872c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux */ 873c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux public void loadRingtoneTitles() { 874c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux enforceNotMainLooper(); 875c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux mRingtoneModel.loadRingtoneTitles(); 876c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux } 877c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux 878c9446b52d9391e859e65d11e5342d84cfe3e781cJames Lemieux /** 87995eed3212011413e1cb717c281e2157859a5adf4Sean Stout * Recheck the permission to read each custom ringtone. 88095eed3212011413e1cb717c281e2157859a5adf4Sean Stout */ 88195eed3212011413e1cb717c281e2157859a5adf4Sean Stout public void loadRingtonePermissions() { 88295eed3212011413e1cb717c281e2157859a5adf4Sean Stout enforceNotMainLooper(); 88395eed3212011413e1cb717c281e2157859a5adf4Sean Stout mRingtoneModel.loadRingtonePermissions(); 88495eed3212011413e1cb717c281e2157859a5adf4Sean Stout } 88595eed3212011413e1cb717c281e2157859a5adf4Sean Stout 88695eed3212011413e1cb717c281e2157859a5adf4Sean Stout /** 88733781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @param uri the uri of a ringtone 88833781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @return the title of the ringtone with the {@code uri}; {@code null} if it cannot be fetched 88933781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux */ 89033781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux public String getRingtoneTitle(Uri uri) { 89133781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux enforceMainLooper(); 89233781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux return mRingtoneModel.getRingtoneTitle(uri); 89333781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux } 89433781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 89533781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux /** 89633781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @param uri the uri of an audio file to use as a ringtone 89733781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @param title the title of the audio content at the given {@code uri} 89833781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @return the ringtone instance created for the audio file 89933781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux */ 90033781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux public CustomRingtone addCustomRingtone(Uri uri, String title) { 90133781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux enforceMainLooper(); 90233781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux return mRingtoneModel.addCustomRingtone(uri, title); 90333781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux } 90433781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 90533781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux /** 90633781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @param uri identifies the ringtone to remove 90733781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux */ 90833781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux public void removeCustomRingtone(Uri uri) { 90933781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux enforceMainLooper(); 91033781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux mRingtoneModel.removeCustomRingtone(uri); 91133781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux } 91233781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 91333781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux /** 91433781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux * @return all available custom ringtones 91533781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux */ 91633781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux public List<CustomRingtone> getCustomRingtones() { 91733781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux enforceMainLooper(); 91833781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux return mRingtoneModel.getCustomRingtones(); 91933781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux } 92033781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux 92133781c882e4229f4ec1a8fafbabb9d4b8b8e2932James Lemieux // 922592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux // Widgets 923592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux // 924592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux 925592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux /** 926592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux * @param widgetClass indicates the type of widget being counted 927592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux * @param count the number of widgets of the given type 928592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux * @param eventCategoryId identifies the category of event to send 929592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux */ 930592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux public void updateWidgetCount(Class widgetClass, int count, @StringRes int eventCategoryId) { 931592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux enforceMainLooper(); 932592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux mWidgetModel.updateWidgetCount(widgetClass, count, eventCategoryId); 933592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux } 934592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux 935592c66b3eb497d24d1528fb2597059c6e4ec6620James Lemieux // 93634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // Settings 93734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux // 93834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 93934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 94025384711e3c2894a84642c49953594930dd078abJames Lemieux * @param silentSettingsListener to be notified when alarm-silencing settings change 94125384711e3c2894a84642c49953594930dd078abJames Lemieux */ 94225384711e3c2894a84642c49953594930dd078abJames Lemieux public void addSilentSettingsListener(OnSilentSettingsListener silentSettingsListener) { 94325384711e3c2894a84642c49953594930dd078abJames Lemieux enforceMainLooper(); 94425384711e3c2894a84642c49953594930dd078abJames Lemieux mSilentSettingsModel.addSilentSettingsListener(silentSettingsListener); 94525384711e3c2894a84642c49953594930dd078abJames Lemieux } 94625384711e3c2894a84642c49953594930dd078abJames Lemieux 94725384711e3c2894a84642c49953594930dd078abJames Lemieux /** 94825384711e3c2894a84642c49953594930dd078abJames Lemieux * @param silentSettingsListener to no longer be notified when alarm-silencing settings change 94925384711e3c2894a84642c49953594930dd078abJames Lemieux */ 95025384711e3c2894a84642c49953594930dd078abJames Lemieux public void removeSilentSettingsListener(OnSilentSettingsListener silentSettingsListener) { 95125384711e3c2894a84642c49953594930dd078abJames Lemieux enforceMainLooper(); 95225384711e3c2894a84642c49953594930dd078abJames Lemieux mSilentSettingsModel.removeSilentSettingsListener(silentSettingsListener); 95325384711e3c2894a84642c49953594930dd078abJames Lemieux } 95425384711e3c2894a84642c49953594930dd078abJames Lemieux 95525384711e3c2894a84642c49953594930dd078abJames Lemieux /** 9560777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return the id used to discriminate relevant AlarmManager callbacks from defunct ones 9570777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 9580777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public int getGlobalIntentId() { 9590777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mSettingsModel.getGlobalIntentId(); 9600777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 9610777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 9620777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 9630777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * Update the id used to discriminate relevant AlarmManager callbacks from defunct ones 9640777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 9650777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public void updateGlobalIntentId() { 9660777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux enforceMainLooper(); 9670777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux mSettingsModel.updateGlobalIntentId(); 9680777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 9690777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 9700777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 97134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return the style of clock to display in the clock application 97234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 97334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public ClockStyle getClockStyle() { 97434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 97534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mSettingsModel.getClockStyle(); 97634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 97734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 97834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 9797b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks * @return the style of clock to display in the clock application 9807b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks */ 9817b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks public boolean getDisplayClockSeconds() { 9827b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks enforceMainLooper(); 9837b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks return mSettingsModel.getDisplayClockSeconds(); 9847b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks } 9857b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks 9867b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks /** 9877b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks * @param displaySeconds whether or not to display seconds for main clock 9887b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks */ 9897b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks public void setDisplayClockSeconds(boolean displaySeconds) { 9907b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks enforceMainLooper(); 9917b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks mSettingsModel.setDisplayClockSeconds(displaySeconds); 9927b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks } 9937b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks 9947b852b43db6d9e50814dd07366b025b3f9f9b758Christine Franks /** 99534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return the style of clock to display in the clock screensaver 99634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 99734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public ClockStyle getScreensaverClockStyle() { 99834142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 99934142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mSettingsModel.getScreensaverClockStyle(); 100034142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 100134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux 100234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux /** 10033af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux * @return {@code true} if the screen saver should be dimmed for lower contrast at night 10043af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux */ 10053af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux public boolean getScreensaverNightModeOn() { 10063af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux enforceMainLooper(); 10073af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux return mSettingsModel.getScreensaverNightModeOn(); 10083af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux } 10093af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux 10103af168c834d73487f8f614f0aaafbf6f9a850f0fJames Lemieux /** 101134142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * @return {@code true} if the users wants to automatically show a clock for their home timezone 101234142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux * when they have travelled outside of that timezone 101334142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux */ 101434142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux public boolean getShowHomeClock() { 101534142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux enforceMainLooper(); 101634142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux return mSettingsModel.getShowHomeClock(); 101734142b1d0f2445bbd606bb490dfef6c078c630eaJames Lemieux } 1018d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1019d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan /** 1020ff17acface9b98eba868fff0e2d70ddc85c5e4dbJames Lemieux * @return the display order of the weekdays, which can start with {@link Calendar#SATURDAY}, 1021ff17acface9b98eba868fff0e2d70ddc85c5e4dbJames Lemieux * {@link Calendar#SUNDAY} or {@link Calendar#MONDAY} 1022458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieux */ 1023ff17acface9b98eba868fff0e2d70ddc85c5e4dbJames Lemieux public Weekdays.Order getWeekdayOrder() { 1024458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieux enforceMainLooper(); 1025ff17acface9b98eba868fff0e2d70ddc85c5e4dbJames Lemieux return mSettingsModel.getWeekdayOrder(); 1026458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieux } 1027458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieux 1028458aa8b4ebb8b7c6fdc0680a1b687ea21a61bf35James Lemieux /** 10290777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @return {@code true} if the restore process (of backup and restore) has completed 10300777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 10310777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public boolean isRestoreBackupFinished() { 10320777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux return mSettingsModel.isRestoreBackupFinished(); 10330777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 10340777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 10350777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 10360777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux * @param finished {@code true} means the restore process (of backup and restore) has completed 10370777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux */ 10380777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux public void setRestoreBackupFinished(boolean finished) { 10390777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux mSettingsModel.setRestoreBackupFinished(finished); 10400777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux } 10410777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux 10420777a082e248c33c2e5a32690bfcdbd5de7d3f9eJames Lemieux /** 104384b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux * @return a description of the time zones available for selection 104484b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux */ 104584b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux public TimeZones getTimeZones() { 104684b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux enforceMainLooper(); 104784b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux return mSettingsModel.getTimeZones(); 104884b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux } 104984b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux 105084b60fe3a95f07ee793d880ca754389159b4929eJames Lemieux /** 1051d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan * Used to execute a delegate runnable and track its completion. 1052d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan */ 1053d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private static class ExecutedRunnable implements Runnable { 1054d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1055d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private final Runnable mDelegate; 1056d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private boolean mExecuted; 1057d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1058d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private ExecutedRunnable(Runnable delegate) { 1059d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan this.mDelegate = delegate; 1060d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 1061d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1062d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan @Override 1063d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan public void run() { 1064d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan mDelegate.run(); 1065d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1066d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan synchronized (this) { 1067d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan mExecuted = true; 1068d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan notifyAll(); 1069d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 1070d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 1071d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan 1072d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan private boolean isExecuted() { 1073d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan return mExecuted; 1074d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 1075d6c134979a65c717aa5e667c39d9f9a788b32a45Dylan Phan } 1076ae9a055482865a70028fc9940c5d871775f9620cJustin Klaassen} 1077