Merge "AOSP/DeskClock - Add Kotlin file for DataModel"
diff --git a/Android.bp b/Android.bp
index ddb4de6..fccb977 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,36 +46,7 @@
"src/**/deskclock/actionbarmenu/*.java",
"src/**/deskclock/alarms/dataadapter/*.java",
"src/**/deskclock/controller/*.java",
- "src/**/deskclock/data/AlarmModel.java",
- "src/**/deskclock/data/City.java",
- "src/**/deskclock/data/CityDAO.java",
- "src/**/deskclock/data/CityListener.java",
- "src/**/deskclock/data/CityModel.java",
- "src/**/deskclock/data/CustomRingtone.java",
- "src/**/deskclock/data/CustomRingtoneDAO.java",
- "src/**/deskclock/data/Lap.java",
- "src/**/deskclock/data/NotificationModel.java",
- "src/**/deskclock/data/OnSilentSettingsListener.java",
- "src/**/deskclock/data/RingtoneModel.java",
- "src/**/deskclock/data/SettingsDAO.java",
- "src/**/deskclock/data/SettingsModel.java",
- "src/**/deskclock/data/SilentSettingsModel.java",
- "src/**/deskclock/data/Stopwatch.java",
- "src/**/deskclock/data/StopwatchDAO.java",
- "src/**/deskclock/data/StopwatchListener.java",
- "src/**/deskclock/data/StopwatchModel.java",
- "src/**/deskclock/data/StopwatchNotificationBuilder.java",
- "src/**/deskclock/data/TimeModel.java",
- "src/**/deskclock/data/Timer.java",
- "src/**/deskclock/data/TimerDAO.java",
- "src/**/deskclock/data/TimerListener.java",
- "src/**/deskclock/data/TimerModel.java",
- "src/**/deskclock/data/TimerNotificationBuilder.java",
- "src/**/deskclock/data/TimerStringFormatter.java",
- "src/**/deskclock/data/TimeZones.java",
- "src/**/deskclock/data/Weekdays.java",
- "src/**/deskclock/data/WidgetDAO.java",
- "src/**/deskclock/data/WidgetModel.java",
+ "src/**/deskclock/data/*.java",
"src/**/deskclock/events/*.java",
"src/**/deskclock/provider/*.java",
"src/**/deskclock/settings/*.java",
diff --git a/src/com/android/alarmclock/AnalogAppWidgetProvider.kt b/src/com/android/alarmclock/AnalogAppWidgetProvider.kt
index e3753db..743e441 100644
--- a/src/com/android/alarmclock/AnalogAppWidgetProvider.kt
+++ b/src/com/android/alarmclock/AnalogAppWidgetProvider.kt
@@ -39,7 +39,7 @@
// Send events for newly created/deleted widgets.
val provider = ComponentName(context, javaClass)
val widgetCount: Int = wm.getAppWidgetIds(provider).size
- val dm = DataModel.getDataModel()
+ val dm = DataModel.dataModel
dm.updateWidgetCount(javaClass, widgetCount, R.string.category_analog_widget)
}
diff --git a/src/com/android/alarmclock/DigitalAppWidgetCityViewsFactory.kt b/src/com/android/alarmclock/DigitalAppWidgetCityViewsFactory.kt
index 4eb42d1..a4e55ad 100644
--- a/src/com/android/alarmclock/DigitalAppWidgetCityViewsFactory.kt
+++ b/src/com/android/alarmclock/DigitalAppWidgetCityViewsFactory.kt
@@ -148,7 +148,7 @@
override fun onDataSetChanged() {
// Fetch the data on the main Looper.
val refreshRunnable = RefreshRunnable()
- DataModel.getDataModel().run(refreshRunnable)
+ DataModel.dataModel.run(refreshRunnable)
// Store the data in local variables.
mHomeCity = refreshRunnable.mHomeCity
@@ -201,9 +201,9 @@
var mShowHomeClock = false
override fun run() {
- mHomeCity = DataModel.getDataModel().homeCity
- mCities = ArrayList(DataModel.getDataModel().selectedCities)
- mShowHomeClock = DataModel.getDataModel().showHomeClock
+ mHomeCity = DataModel.dataModel.homeCity
+ mCities = ArrayList(DataModel.dataModel.selectedCities)
+ mShowHomeClock = DataModel.dataModel.showHomeClock
}
}
diff --git a/src/com/android/alarmclock/DigitalAppWidgetProvider.kt b/src/com/android/alarmclock/DigitalAppWidgetProvider.kt
index a4427d1..8e7ec2d 100644
--- a/src/com/android/alarmclock/DigitalAppWidgetProvider.kt
+++ b/src/com/android/alarmclock/DigitalAppWidgetProvider.kt
@@ -125,7 +125,7 @@
}
}
- val dm = DataModel.getDataModel()
+ val dm = DataModel.dataModel
dm.updateWidgetCount(javaClass, widgetIds.size, R.string.category_digital_widget)
if (widgetIds.size > 0) {
@@ -164,7 +164,7 @@
* Add the day-change callback if it is needed (selected cities exist).
*/
private fun updateDayChangeCallback(context: Context) {
- val dm = DataModel.getDataModel()
+ val dm = DataModel.dataModel
val selectedCities = dm.selectedCities
val showHomeClock = dm.showHomeClock
if (selectedCities.isEmpty() && !showHomeClock) {
diff --git a/src/com/android/deskclock/ClockFragment.java b/src/com/android/deskclock/ClockFragment.java
index 1536b55..db6cbcf 100644
--- a/src/com/android/deskclock/ClockFragment.java
+++ b/src/com/android/deskclock/ClockFragment.java
@@ -416,7 +416,7 @@
}
private List<City> getCities() {
- return DataModel.getDataModel().getSelectedCities();
+ return (List<City>) DataModel.getDataModel().getSelectedCities();
}
private void refreshAlarm() {
diff --git a/src/com/android/deskclock/alarms/AlarmActivity.kt b/src/com/android/deskclock/alarms/AlarmActivity.kt
index a1bd876..c68d2eb 100644
--- a/src/com/android/deskclock/alarms/AlarmActivity.kt
+++ b/src/com/android/deskclock/alarms/AlarmActivity.kt
@@ -146,7 +146,7 @@
LOGGER.i("Displaying alarm for instance: %s", mAlarmInstance)
// Get the volume/camera button behavior setting
- mVolumeBehavior = DataModel.getDataModel().alarmVolumeButtonBehavior
+ mVolumeBehavior = DataModel.dataModel.alarmVolumeButtonBehavior
// TODO(b/157255731) Replace deprecated LayoutParams flags on Android versions above O
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
@@ -467,7 +467,7 @@
val colorAccent = ThemeUtils.resolveColor(this, R.attr.colorAccent)
setAnimatedFractions(1.0f /* snoozeFraction */, 0.0f /* dismissFraction */)
- val snoozeMinutes = DataModel.getDataModel().snoozeLength
+ val snoozeMinutes = DataModel.dataModel.snoozeLength
val infoText: String = getResources().getQuantityString(
R.plurals.alarm_alert_snooze_duration, snoozeMinutes, snoozeMinutes)
val accessibilityText: String = getResources().getQuantityString(
diff --git a/src/com/android/deskclock/alarms/AlarmKlaxon.kt b/src/com/android/deskclock/alarms/AlarmKlaxon.kt
index cc3b6f9..bc37af7 100644
--- a/src/com/android/deskclock/alarms/AlarmKlaxon.kt
+++ b/src/com/android/deskclock/alarms/AlarmKlaxon.kt
@@ -56,7 +56,7 @@
LogUtils.v("AlarmKlaxon.start()")
if (!AlarmSettingColumns.NO_RINGTONE_URI.equals(instance.mRingtone)) {
- val crescendoDuration = DataModel.getDataModel().alarmCrescendoDuration
+ val crescendoDuration = DataModel.dataModel.alarmCrescendoDuration
getAsyncRingtonePlayer(context)!!.play(instance.mRingtone, crescendoDuration)
}
diff --git a/src/com/android/deskclock/alarms/AlarmStateManager.kt b/src/com/android/deskclock/alarms/AlarmStateManager.kt
index d50157b..d4cc370 100644
--- a/src/com/android/deskclock/alarms/AlarmStateManager.kt
+++ b/src/com/android/deskclock/alarms/AlarmStateManager.kt
@@ -190,7 +190,7 @@
private val currentTime: Calendar
get() = (if (sCurrentTimeFactory == null) {
- DataModel.getDataModel().calendar
+ DataModel.dataModel.calendar
} else {
sCurrentTimeFactory!!.currentTime
})
@@ -363,7 +363,7 @@
AlarmInstance.createIntent(context, AlarmService::class.java, instance.mId)
intent.setAction(CHANGE_STATE_ACTION)
intent.addCategory(tag)
- intent.putExtra(ALARM_GLOBAL_ID_EXTRA, DataModel.getDataModel().globalIntentId)
+ intent.putExtra(ALARM_GLOBAL_ID_EXTRA, DataModel.dataModel.globalIntentId)
if (state != null) {
intent.putExtra(ALARM_STATE_EXTRA, state.toInt())
}
@@ -536,7 +536,7 @@
AlarmService.stopAlarm(context, instance)
// Calculate the new snooze alarm time
- val snoozeMinutes = DataModel.getDataModel().snoozeLength
+ val snoozeMinutes = DataModel.dataModel.snoozeLength
val newAlarmTime = Calendar.getInstance()
newAlarmTime.add(Calendar.MINUTE, snoozeMinutes)
@@ -945,7 +945,7 @@
return
}
- val globalId = DataModel.getDataModel().globalIntentId
+ val globalId = DataModel.dataModel.globalIntentId
val intentId: Int = intent.getIntExtra(ALARM_GLOBAL_ID_EXTRA, -1)
val alarmState: Int = intent.getIntExtra(ALARM_STATE_EXTRA, -1)
if (intentId != globalId) {
diff --git a/src/com/android/deskclock/alarms/AlarmTimeClickHandler.kt b/src/com/android/deskclock/alarms/AlarmTimeClickHandler.kt
index 975a895..f9350ba 100644
--- a/src/com/android/deskclock/alarms/AlarmTimeClickHandler.kt
+++ b/src/com/android/deskclock/alarms/AlarmTimeClickHandler.kt
@@ -129,7 +129,7 @@
val now = Calendar.getInstance()
val oldNextAlarmTime = alarm.getNextAlarmTime(now)
- val weekday = DataModel.getDataModel().weekdayOrder.calendarDays[index]
+ val weekday = DataModel.dataModel.weekdayOrder.calendarDays[index]
alarm.daysOfWeek = alarm.daysOfWeek.setBit(weekday, checked)
// if the change altered the next scheduled alarm time, tell the user
diff --git a/src/com/android/deskclock/alarms/dataadapter/CollapsedAlarmViewHolder.kt b/src/com/android/deskclock/alarms/dataadapter/CollapsedAlarmViewHolder.kt
index 33217b6..5b7b1ce 100644
--- a/src/com/android/deskclock/alarms/dataadapter/CollapsedAlarmViewHolder.kt
+++ b/src/com/android/deskclock/alarms/dataadapter/CollapsedAlarmViewHolder.kt
@@ -95,7 +95,7 @@
private fun bindRepeatText(context: Context, alarm: Alarm) {
if (alarm.daysOfWeek.isRepeating) {
- val weekdayOrder = DataModel.getDataModel().weekdayOrder
+ val weekdayOrder = DataModel.dataModel.weekdayOrder
val daysOfWeekText = alarm.daysOfWeek.toString(context, weekdayOrder)
daysOfWeek.text = daysOfWeekText
diff --git a/src/com/android/deskclock/alarms/dataadapter/ExpandedAlarmViewHolder.kt b/src/com/android/deskclock/alarms/dataadapter/ExpandedAlarmViewHolder.kt
index 8fa4ca4..e071c99 100644
--- a/src/com/android/deskclock/alarms/dataadapter/ExpandedAlarmViewHolder.kt
+++ b/src/com/android/deskclock/alarms/dataadapter/ExpandedAlarmViewHolder.kt
@@ -73,7 +73,7 @@
// Build button for each day.
val inflater: LayoutInflater = LayoutInflater.from(context)
- val weekdays = DataModel.getDataModel().weekdayOrder.calendarDays
+ val weekdays = DataModel.dataModel.weekdayOrder.calendarDays
for (i in 0..6) {
val dayButtonFrame: View = inflater.inflate(R.layout.day_button, repeatDays,
false /* attachToRoot */)
@@ -153,7 +153,7 @@
}
private fun bindRingtone(context: Context, alarm: Alarm) {
- val title = DataModel.getDataModel().getRingtoneTitle(alarm.alert)
+ val title = DataModel.dataModel.getRingtoneTitle(alarm.alert!!)
ringtone.text = title
val description: String = context.getString(R.string.ringtone_description)
@@ -166,7 +166,7 @@
}
private fun bindDaysOfWeekButtons(alarm: Alarm, context: Context) {
- val weekdays = DataModel.getDataModel().weekdayOrder.calendarDays
+ val weekdays = DataModel.dataModel.weekdayOrder.calendarDays
for (i in weekdays.indices) {
val dayButton: CompoundButton? = dayButtons[i]
dayButton?.let {
diff --git a/src/com/android/deskclock/controller/ShortcutController.kt b/src/com/android/deskclock/controller/ShortcutController.kt
index 6b1e762..ee13111 100644
--- a/src/com/android/deskclock/controller/ShortcutController.kt
+++ b/src/com/android/deskclock/controller/ShortcutController.kt
@@ -51,7 +51,7 @@
init {
Controller.getController().addEventTracker(ShortcutEventTracker(context))
- DataModel.getDataModel().addStopwatchListener(StopwatchWatcher())
+ DataModel.dataModel.addStopwatchListener(StopwatchWatcher())
}
fun updateShortcuts() {
@@ -105,7 +105,7 @@
}
private fun createStopwatchShortcut(): ShortcutInfo {
- @StringRes val action: Int = if (DataModel.getDataModel().stopwatch.isRunning) {
+ @StringRes val action: Int = if (DataModel.dataModel.stopwatch.isRunning) {
R.string.action_pause
} else {
R.string.action_start
@@ -117,7 +117,7 @@
.setActivity(mComponentName)
.setRank(2)
val intent: Intent
- if (DataModel.getDataModel().stopwatch.isRunning) {
+ if (DataModel.dataModel.stopwatch.isRunning) {
intent = Intent(StopwatchService.ACTION_PAUSE_STOPWATCH)
.putExtra(Events.EXTRA_EVENT_LABEL, R.string.label_shortcut)
shortcut.setShortLabel(context.getString(R.string.shortcut_pause_stopwatch_short))
diff --git a/src/com/android/deskclock/data/DataModel.kt b/src/com/android/deskclock/data/DataModel.kt
new file mode 100644
index 0000000..27b3fac
--- /dev/null
+++ b/src/com/android/deskclock/data/DataModel.kt
@@ -0,0 +1,1073 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.deskclock.data
+
+import android.app.Service
+import android.content.Context
+import android.content.Context.AUDIO_SERVICE
+import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.content.SharedPreferences
+import android.media.AudioManager
+import android.media.AudioManager.FLAG_SHOW_UI
+import android.media.AudioManager.STREAM_ALARM
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
+import android.provider.Settings.ACTION_SOUND_SETTINGS
+import android.view.View
+import androidx.annotation.StringRes
+
+import com.android.deskclock.Predicate
+import com.android.deskclock.R
+import com.android.deskclock.Utils
+import com.android.deskclock.timer.TimerService
+
+import java.util.Calendar
+
+import kotlin.Comparator
+import kotlin.math.roundToInt
+
+/**
+ * All application-wide data is accessible through this singleton.
+ */
+// TODO(b/157255731) DataModel can be converted to an object after no Java code depends on it
+class DataModel private constructor() {
+
+ /** Indicates the display style of clocks. */
+ enum class ClockStyle {
+ ANALOG, DIGITAL
+ }
+
+ /** Indicates the preferred sort order of cities. */
+ enum class CitySort {
+ NAME, UTC_OFFSET
+ }
+
+ /** Indicates the preferred behavior of hardware volume buttons when firing alarms. */
+ enum class AlarmVolumeButtonBehavior {
+ NOTHING, SNOOZE, DISMISS
+ }
+
+ /** Indicates the reason alarms may not fire or may fire silently. */
+ enum class SilentSetting(
+ @field:StringRes @get:StringRes val labelResId: Int,
+ @field:StringRes @get:StringRes val actionResId: Int,
+ private val mActionEnabled: Predicate<Context>,
+ private val mActionListener: View.OnClickListener?
+ ) {
+
+ DO_NOT_DISTURB(R.string.alarms_blocked_by_dnd,
+ 0,
+ Predicate.FALSE as Predicate<Context>,
+ mActionListener = null),
+ MUTED_VOLUME(R.string.alarm_volume_muted,
+ R.string.unmute_alarm_volume,
+ Predicate.TRUE as Predicate<Context>,
+ UnmuteAlarmVolumeListener()),
+ SILENT_RINGTONE(R.string.silent_default_alarm_ringtone,
+ R.string.change_setting_action,
+ ChangeSoundActionPredicate(),
+ ChangeSoundSettingsListener()),
+ BLOCKED_NOTIFICATIONS(R.string.app_notifications_blocked,
+ R.string.change_setting_action,
+ Predicate.TRUE as Predicate<Context>,
+ ChangeAppNotificationSettingsListener());
+
+ val actionListener: View.OnClickListener?
+ get() = mActionListener
+
+ fun isActionEnabled(context: Context?): Boolean {
+ return labelResId != 0 && mActionEnabled.apply(context)
+ }
+
+ private class UnmuteAlarmVolumeListener : View.OnClickListener {
+ override fun onClick(v: View) {
+ // Set the alarm volume to 11/16th of max and show the slider UI.
+ // 11/16th of max is the initial volume of the alarm stream on a fresh install.
+ val context: Context = v.context
+ val am: AudioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
+ val index = (am.getStreamMaxVolume(STREAM_ALARM) * 11f / 16f).roundToInt()
+ am.setStreamVolume(STREAM_ALARM, index, FLAG_SHOW_UI)
+ }
+ }
+
+ private class ChangeSoundSettingsListener : View.OnClickListener {
+ override fun onClick(v: View) {
+ val context: Context = v.context
+ context.startActivity(Intent(ACTION_SOUND_SETTINGS)
+ .addFlags(FLAG_ACTIVITY_NEW_TASK))
+ }
+ }
+
+ private class ChangeSoundActionPredicate : Predicate<Context> {
+ override fun apply(context: Context): Boolean {
+ val intent = Intent(ACTION_SOUND_SETTINGS)
+ return intent.resolveActivity(context.packageManager) != null
+ }
+ }
+
+ private class ChangeAppNotificationSettingsListener : View.OnClickListener {
+ override fun onClick(v: View) {
+ val context: Context = v.context
+ if (Utils.isLOrLater()) {
+ try {
+ // Attempt to open the notification settings for this app.
+ context.startActivity(
+ Intent("android.settings.APP_NOTIFICATION_SETTINGS")
+ .putExtra("app_package", context.packageName)
+ .putExtra("app_uid", context.applicationInfo.uid)
+ .addFlags(FLAG_ACTIVITY_NEW_TASK))
+ return
+ } catch (ignored: Exception) {
+ // best attempt only; recovery code below
+ }
+ }
+
+ // Fall back to opening the app settings page.
+ context.startActivity(Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
+ .setData(Uri.fromParts("package", context.packageName, null))
+ .addFlags(FLAG_ACTIVITY_NEW_TASK))
+ }
+ }
+ }
+
+ private var mHandler: Handler? = null
+ private var mContext: Context? = null
+
+ /** The model from which settings are fetched. */
+ private var mSettingsModel: SettingsModel? = null
+
+ /** The model from which city data are fetched. */
+ private var mCityModel: CityModel? = null
+
+ /** The model from which timer data are fetched. */
+ private var mTimerModel: TimerModel? = null
+
+ /** The model from which alarm data are fetched. */
+ private var mAlarmModel: AlarmModel? = null
+
+ /** The model from which widget data are fetched. */
+ private var mWidgetModel: WidgetModel? = null
+
+ /** The model from which data about settings that silence alarms are fetched. */
+ private var mSilentSettingsModel: SilentSettingsModel? = null
+
+ /** The model from which stopwatch data are fetched. */
+ private var mStopwatchModel: StopwatchModel? = null
+
+ /** The model from which notification data are fetched. */
+ private var mNotificationModel: NotificationModel? = null
+
+ /** The model from which time data are fetched. */
+ private var mTimeModel: TimeModel? = null
+
+ /** The model from which ringtone data are fetched. */
+ private var mRingtoneModel: RingtoneModel? = null
+
+ /**
+ * Initializes the data model with the context and shared preferences to be used.
+ */
+ fun init(context: Context, prefs: SharedPreferences) {
+ if (mContext !== context) {
+ mContext = context.applicationContext
+ mTimeModel = TimeModel(mContext!!)
+ mWidgetModel = WidgetModel(prefs)
+ mNotificationModel = NotificationModel()
+ mRingtoneModel = RingtoneModel(mContext!!, prefs)
+ mSettingsModel = SettingsModel(mContext!!, prefs, mTimeModel!!)
+ mCityModel = CityModel(mContext!!, prefs, mSettingsModel!!)
+ mAlarmModel = AlarmModel(mContext!!, mSettingsModel!!)
+ mSilentSettingsModel = SilentSettingsModel(mContext!!, mNotificationModel!!)
+ mStopwatchModel = StopwatchModel(mContext!!, prefs, mNotificationModel!!)
+ mTimerModel = TimerModel(mContext!!, prefs, mSettingsModel!!, mRingtoneModel!!,
+ mNotificationModel!!)
+ }
+ }
+
+ /**
+ * Convenience for `run(runnable, 0)`, i.e. waits indefinitely.
+ */
+ fun run(runnable: Runnable) {
+ try {
+ run(runnable, 0 /* waitMillis */)
+ } catch (ignored: InterruptedException) {
+ }
+ }
+
+ /**
+ * Updates all timers and the stopwatch after the device has shutdown and restarted.
+ */
+ fun updateAfterReboot() {
+ Utils.enforceMainLooper()
+ mTimerModel!!.updateTimersAfterReboot()
+ mStopwatchModel!!.setStopwatch(stopwatch.updateAfterReboot())
+ }
+
+ /**
+ * Updates all timers and the stopwatch after the device's time has changed.
+ */
+ fun updateAfterTimeSet() {
+ Utils.enforceMainLooper()
+ mTimerModel!!.updateTimersAfterTimeSet()
+ mStopwatchModel!!.setStopwatch(stopwatch.updateAfterTimeSet())
+ }
+
+ /**
+ * Posts a runnable to the main thread and blocks until the runnable executes. Used to access
+ * the data model from the main thread.
+ */
+ @Throws(InterruptedException::class)
+ fun run(runnable: Runnable, waitMillis: Long) {
+ if (Looper.myLooper() === Looper.getMainLooper()) {
+ runnable.run()
+ return
+ }
+
+ val er = ExecutedRunnable(runnable)
+ handler.post(er)
+
+ // Wait for the data to arrive, if it has not.
+ synchronized(er) {
+ if (!er.isExecuted) {
+ er.wait(waitMillis)
+ }
+ }
+ }
+
+ /**
+ * @return a handler associated with the main thread
+ */
+ @get:Synchronized
+ private val handler: Handler
+ get() {
+ if (mHandler == null) {
+ mHandler = Handler(Looper.getMainLooper())
+ }
+ return mHandler!!
+ }
+
+ //
+ // Application
+ //
+
+ var isApplicationInForeground: Boolean
+ /**
+ * @return `true` when the application is open in the foreground; `false` otherwise
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mNotificationModel!!.isApplicationInForeground
+ }
+ /**
+ * @param inForeground `true` to indicate the application is open in the foreground
+ */
+ set(inForeground) {
+ Utils.enforceMainLooper()
+ if (mNotificationModel!!.isApplicationInForeground != inForeground) {
+ mNotificationModel!!.isApplicationInForeground = inForeground
+
+ // Refresh all notifications in response to a change in app open state.
+ mTimerModel!!.updateNotification()
+ mTimerModel!!.updateMissedNotification()
+ mStopwatchModel!!.updateNotification()
+ mSilentSettingsModel!!.updateSilentState()
+ }
+ }
+
+ /**
+ * Called when the notifications may be stale or absent from the notification manager and must
+ * be rebuilt. e.g. after upgrading the application
+ */
+ fun updateAllNotifications() {
+ Utils.enforceMainLooper()
+ mTimerModel!!.updateNotification()
+ mTimerModel!!.updateMissedNotification()
+ mStopwatchModel!!.updateNotification()
+ }
+
+ //
+ // Cities
+ //
+
+ /**
+ * @return a list of all cities in their display order
+ */
+ val allCities: List<City>
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.allCities
+ }
+
+ /**
+ * @return a city representing the user's home timezone
+ */
+ val homeCity: City
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.homeCity
+ }
+
+ /**
+ * @return a list of cities not selected for display
+ */
+ val unselectedCities: List<City>
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.unselectedCities
+ }
+
+ var selectedCities: Collection<City>
+ /**
+ * @return a list of cities selected for display
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.selectedCities
+ }
+ /**
+ * @param cities the new collection of cities selected for display by the user
+ */
+ set(cities) {
+ Utils.enforceMainLooper()
+ mCityModel?.setSelectedCities(cities)
+ }
+
+ /**
+ * @return a comparator used to locate index positions
+ */
+ val cityIndexComparator: Comparator<City>
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.cityIndexComparator
+ }
+
+ /**
+ * @return the order in which cities are sorted
+ */
+ val citySort: CitySort
+ get() {
+ Utils.enforceMainLooper()
+ return mCityModel!!.citySort
+ }
+
+ /**
+ * Adjust the order in which cities are sorted.
+ */
+ fun toggleCitySort() {
+ Utils.enforceMainLooper()
+ mCityModel?.toggleCitySort()
+ }
+
+ /**
+ * @param cityListener listener to be notified when the world city list changes
+ */
+ fun addCityListener(cityListener: CityListener) {
+ Utils.enforceMainLooper()
+ mCityModel?.addCityListener(cityListener)
+ }
+
+ /**
+ * @param cityListener listener that no longer needs to be notified of world city list changes
+ */
+ fun removeCityListener(cityListener: CityListener) {
+ Utils.enforceMainLooper()
+ mCityModel?.removeCityListener(cityListener)
+ }
+
+ //
+ // Timers
+ //
+
+ /**
+ * @param timerListener to be notified when timers are added, updated and removed
+ */
+ fun addTimerListener(timerListener: TimerListener) {
+ Utils.enforceMainLooper()
+ mTimerModel?.addTimerListener(timerListener)
+ }
+
+ /**
+ * @param timerListener to no longer be notified when timers are added, updated and removed
+ */
+ fun removeTimerListener(timerListener: TimerListener) {
+ Utils.enforceMainLooper()
+ mTimerModel?.removeTimerListener(timerListener)
+ }
+
+ /**
+ * @return a list of timers for display
+ */
+ val timers: List<Timer>
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.timers
+ }
+
+ /**
+ * @return a list of expired timers for display
+ */
+ val expiredTimers: List<Timer>
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.expiredTimers
+ }
+
+ /**
+ * @param timerId identifies the timer to return
+ * @return the timer with the given `timerId`
+ */
+ fun getTimer(timerId: Int): Timer? {
+ Utils.enforceMainLooper()
+ return mTimerModel?.getTimer(timerId)
+ }
+
+ /**
+ * @return the timer that last expired and is still expired now; `null` if no timers are
+ * expired
+ */
+ val mostRecentExpiredTimer: Timer?
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel?.mostRecentExpiredTimer
+ }
+
+ /**
+ * @param length the length of the timer in milliseconds
+ * @param label describes the purpose of the timer
+ * @param deleteAfterUse `true` indicates the timer should be deleted when it is reset
+ * @return the newly added timer
+ */
+ fun addTimer(length: Long, label: String?, deleteAfterUse: Boolean): Timer {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.addTimer(length, label, deleteAfterUse)
+ }
+
+ /**
+ * @param timer the timer to be removed
+ */
+ fun removeTimer(timer: Timer) {
+ Utils.enforceMainLooper()
+ mTimerModel?.removeTimer(timer)
+ }
+
+ /**
+ * @param timer the timer to be started
+ */
+ fun startTimer(timer: Timer) {
+ startTimer(null, timer)
+ }
+
+ /**
+ * @param service used to start foreground notifications for expired timers
+ * @param timer the timer to be started
+ */
+ fun startTimer(service: Service?, timer: Timer) {
+ Utils.enforceMainLooper()
+ val started = timer.start()
+ mTimerModel?.updateTimer(started)
+ if (timer.remainingTime <= 0) {
+ if (service != null) {
+ expireTimer(service, started)
+ } else {
+ mContext!!.startService(TimerService.createTimerExpiredIntent(mContext, started))
+ }
+ }
+ }
+
+ /**
+ * @param timer the timer to be paused
+ */
+ fun pauseTimer(timer: Timer) {
+ Utils.enforceMainLooper()
+ mTimerModel?.updateTimer(timer.pause())
+ }
+
+ /**
+ * @param service used to start foreground notifications for expired timers
+ * @param timer the timer to be expired
+ */
+ fun expireTimer(service: Service, timer: Timer) {
+ Utils.enforceMainLooper()
+ mTimerModel?.expireTimer(service, timer)
+ }
+
+ /**
+ * @param timer the timer to be reset
+ * @return the reset `timer`
+ */
+ fun resetTimer(timer: Timer): Timer? {
+ Utils.enforceMainLooper()
+ return mTimerModel?.resetTimer(timer, false /* allowDelete */, 0 /* eventLabelId */)
+ }
+
+ /**
+ * If the given `timer` is expired and marked for deletion after use then this method
+ * removes the timer. The timer is otherwise transitioned to the reset state and continues
+ * to exist.
+ *
+ * @param timer the timer to be reset
+ * @param eventLabelId the label of the timer event to send; 0 if no event should be sent
+ * @return the reset `timer` or `null` if the timer was deleted
+ */
+ fun resetOrDeleteTimer(timer: Timer, @StringRes eventLabelId: Int): Timer? {
+ Utils.enforceMainLooper()
+ return mTimerModel?.resetTimer(timer, true /* allowDelete */, eventLabelId)
+ }
+
+ /**
+ * Resets all expired timers.
+ *
+ * @param eventLabelId the label of the timer event to send; 0 if no event should be sent
+ */
+ fun resetOrDeleteExpiredTimers(@StringRes eventLabelId: Int) {
+ Utils.enforceMainLooper()
+ mTimerModel?.resetOrDeleteExpiredTimers(eventLabelId)
+ }
+
+ /**
+ * Resets all unexpired timers.
+ *
+ * @param eventLabelId the label of the timer event to send; 0 if no event should be sent
+ */
+ fun resetUnexpiredTimers(@StringRes eventLabelId: Int) {
+ Utils.enforceMainLooper()
+ mTimerModel?.resetUnexpiredTimers(eventLabelId)
+ }
+
+ /**
+ * Resets all missed timers.
+ *
+ * @param eventLabelId the label of the timer event to send; 0 if no event should be sent
+ */
+ fun resetMissedTimers(@StringRes eventLabelId: Int) {
+ Utils.enforceMainLooper()
+ mTimerModel?.resetMissedTimers(eventLabelId)
+ }
+
+ /**
+ * @param timer the timer to which a minute should be added to the remaining time
+ */
+ fun addTimerMinute(timer: Timer) {
+ Utils.enforceMainLooper()
+ mTimerModel?.updateTimer(timer.addMinute())
+ }
+
+ /**
+ * @param timer the timer to which the new `label` belongs
+ * @param label the new label to store for the `timer`
+ */
+ fun setTimerLabel(timer: Timer, label: String?) {
+ Utils.enforceMainLooper()
+ mTimerModel?.updateTimer(timer.setLabel(label))
+ }
+
+ /**
+ * @param timer the timer whose `length` to change
+ * @param length the new length of the timer in milliseconds
+ */
+ fun setTimerLength(timer: Timer, length: Long) {
+ Utils.enforceMainLooper()
+ mTimerModel?.updateTimer(timer.setLength(length))
+ }
+
+ /**
+ * @param timer the timer whose `remainingTime` to change
+ * @param remainingTime the new remaining time of the timer in milliseconds
+ */
+ fun setRemainingTime(timer: Timer, remainingTime: Long) {
+ Utils.enforceMainLooper()
+
+ val updated = timer.setRemainingTime(remainingTime)
+ mTimerModel?.updateTimer(updated)
+ if (timer.isRunning && timer.remainingTime <= 0) {
+ mContext?.startService(TimerService.createTimerExpiredIntent(mContext, updated))
+ }
+ }
+
+ /**
+ * Updates the timer notifications to be current.
+ */
+ fun updateTimerNotification() {
+ Utils.enforceMainLooper()
+ mTimerModel?.updateNotification()
+ }
+
+ /**
+ * @return the uri of the default ringtone to play for all timers when no user selection exists
+ */
+ val defaultTimerRingtoneUri: Uri
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.defaultTimerRingtoneUri
+ }
+
+ /**
+ * @return `true` iff the ringtone to play for all timers is the silent ringtone
+ */
+ val isTimerRingtoneSilent: Boolean
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.isTimerRingtoneSilent
+ }
+
+ var timerRingtoneUri: Uri
+ /**
+ * @return the uri of the ringtone to play for all timers
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.timerRingtoneUri
+ }
+ /**
+ * @param uri the uri of the ringtone to play for all timers
+ */
+ set(uri) {
+ Utils.enforceMainLooper()
+ mTimerModel!!.timerRingtoneUri = uri
+ }
+
+ /**
+ * @return the title of the ringtone that is played for all timers
+ */
+ val timerRingtoneTitle: String
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.timerRingtoneTitle
+ }
+
+ /**
+ * @return the duration, in milliseconds, of the crescendo to apply to timer ringtone playback;
+ * `0` implies no crescendo should be applied
+ */
+ val timerCrescendoDuration: Long
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.timerCrescendoDuration
+ }
+
+ var timerVibrate: Boolean
+ /**
+ * @return whether vibrate is enabled for all timers.
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mTimerModel!!.timerVibrate
+ }
+ /**
+ * @param enabled whether vibrate is enabled for all timers.
+ */
+ set(enabled) {
+ Utils.enforceMainLooper()
+ mTimerModel!!.timerVibrate = enabled
+ }
+
+ //
+ // Alarms
+ //
+
+ var defaultAlarmRingtoneUri: Uri
+ /**
+ * @return the uri of the ringtone to which all new alarms default
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mAlarmModel!!.defaultAlarmRingtoneUri
+ }
+ /**
+ * @param uri the uri of the ringtone to which future new alarms will default
+ */
+ set(uri) {
+ Utils.enforceMainLooper()
+ mAlarmModel!!.defaultAlarmRingtoneUri = uri
+ }
+
+ /**
+ * @return the duration, in milliseconds, of the crescendo to apply to alarm ringtone playback;
+ * `0` implies no crescendo should be applied
+ */
+ val alarmCrescendoDuration: Long
+ get() {
+ Utils.enforceMainLooper()
+ return mAlarmModel!!.alarmCrescendoDuration
+ }
+
+ /**
+ * @return the behavior to execute when volume buttons are pressed while firing an alarm
+ */
+ val alarmVolumeButtonBehavior: AlarmVolumeButtonBehavior
+ get() {
+ Utils.enforceMainLooper()
+ return mAlarmModel!!.alarmVolumeButtonBehavior
+ }
+
+ /**
+ * @return the number of minutes an alarm may ring before it has timed out and becomes missed
+ */
+ val alarmTimeout: Int
+ get() = mAlarmModel!!.alarmTimeout
+
+ /**
+ * @return the number of minutes an alarm will remain snoozed before it rings again
+ */
+ val snoozeLength: Int
+ get() = mAlarmModel!!.snoozeLength
+
+ //
+ // Stopwatch
+ //
+
+ /**
+ * @param stopwatchListener to be notified when stopwatch changes or laps are added
+ */
+ fun addStopwatchListener(stopwatchListener: StopwatchListener) {
+ Utils.enforceMainLooper()
+ mStopwatchModel?.addStopwatchListener(stopwatchListener)
+ }
+
+ /**
+ * @param stopwatchListener to no longer be notified when stopwatch changes or laps are added
+ */
+ fun removeStopwatchListener(stopwatchListener: StopwatchListener) {
+ Utils.enforceMainLooper()
+ mStopwatchModel?.removeStopwatchListener(stopwatchListener)
+ }
+
+ /**
+ * @return the current state of the stopwatch
+ */
+ val stopwatch: Stopwatch
+ get() {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.stopwatch
+ }
+
+ /**
+ * @return the stopwatch after being started
+ */
+ fun startStopwatch(): Stopwatch {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.setStopwatch(stopwatch.start())
+ }
+
+ /**
+ * @return the stopwatch after being paused
+ */
+ fun pauseStopwatch(): Stopwatch {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.setStopwatch(stopwatch.pause())
+ }
+
+ /**
+ * @return the stopwatch after being reset
+ */
+ fun resetStopwatch(): Stopwatch {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.setStopwatch(stopwatch.reset())
+ }
+
+ /**
+ * @return the laps recorded for this stopwatch
+ */
+ val laps: List<Lap>
+ get() {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.laps
+ }
+
+ /**
+ * @return a newly recorded lap completed now; `null` if no more laps can be added
+ */
+ fun addLap(): Lap? {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.addLap()
+ }
+
+ /**
+ * @return `true` iff more laps can be recorded
+ */
+ fun canAddMoreLaps(): Boolean {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.canAddMoreLaps()
+ }
+
+ /**
+ * @return the longest lap time of all recorded laps and the current lap
+ */
+ val longestLapTime: Long
+ get() {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.longestLapTime
+ }
+
+ /**
+ * @param time a point in time after the end of the last lap
+ * @return the elapsed time between the given `time` and the end of the previous lap
+ */
+ fun getCurrentLapTime(time: Long): Long {
+ Utils.enforceMainLooper()
+ return mStopwatchModel!!.getCurrentLapTime(time)
+ }
+
+ //
+ // Time
+ // (Time settings/values are accessible from any Thread so no Thread-enforcement exists.)
+ //
+
+ /**
+ * @return the current time in milliseconds
+ */
+ fun currentTimeMillis(): Long {
+ return mTimeModel!!.currentTimeMillis()
+ }
+
+ /**
+ * @return milliseconds since boot, including time spent in sleep
+ */
+ fun elapsedRealtime(): Long {
+ return mTimeModel!!.elapsedRealtime()
+ }
+
+ /**
+ * @return `true` if 24 hour time format is selected; `false` otherwise
+ */
+ fun is24HourFormat(): Boolean {
+ return mTimeModel!!.is24HourFormat()
+ }
+
+ /**
+ * @return a new calendar object initialized to the [.currentTimeMillis]
+ */
+ val calendar: Calendar
+ get() = mTimeModel!!.calendar
+
+ //
+ // Ringtones
+ //
+
+ /**
+ * Ringtone titles are cached because loading them is expensive. This method
+ * **must** be called on a background thread and is responsible for priming the
+ * cache of ringtone titles to avoid later fetching titles on the main thread.
+ */
+ fun loadRingtoneTitles() {
+ Utils.enforceNotMainLooper()
+ mRingtoneModel?.loadRingtoneTitles()
+ }
+
+ /**
+ * Recheck the permission to read each custom ringtone.
+ */
+ fun loadRingtonePermissions() {
+ Utils.enforceNotMainLooper()
+ mRingtoneModel?.loadRingtonePermissions()
+ }
+
+ /**
+ * @param uri the uri of a ringtone
+ * @return the title of the ringtone with the `uri`; `null` if it cannot be fetched
+ */
+ fun getRingtoneTitle(uri: Uri): String? {
+ Utils.enforceMainLooper()
+ return mRingtoneModel?.getRingtoneTitle(uri)
+ }
+
+ /**
+ * @param uri the uri of an audio file to use as a ringtone
+ * @param title the title of the audio content at the given `uri`
+ * @return the ringtone instance created for the audio file
+ */
+ fun addCustomRingtone(uri: Uri, title: String?): CustomRingtone? {
+ Utils.enforceMainLooper()
+ return mRingtoneModel?.addCustomRingtone(uri, title)
+ }
+
+ /**
+ * @param uri identifies the ringtone to remove
+ */
+ fun removeCustomRingtone(uri: Uri) {
+ Utils.enforceMainLooper()
+ mRingtoneModel?.removeCustomRingtone(uri)
+ }
+
+ /**
+ * @return all available custom ringtones
+ */
+ val customRingtones: List<CustomRingtone>
+ get() {
+ Utils.enforceMainLooper()
+ return mRingtoneModel!!.customRingtones
+ }
+
+ //
+ // Widgets
+ //
+
+ /**
+ * @param widgetClass indicates the type of widget being counted
+ * @param count the number of widgets of the given type
+ * @param eventCategoryId identifies the category of event to send
+ */
+ fun updateWidgetCount(widgetClass: Class<*>?, count: Int, @StringRes eventCategoryId: Int) {
+ Utils.enforceMainLooper()
+ mWidgetModel!!.updateWidgetCount(widgetClass!!, count, eventCategoryId)
+ }
+
+ //
+ // Settings
+ //
+
+ /**
+ * @param silentSettingsListener to be notified when alarm-silencing settings change
+ */
+ fun addSilentSettingsListener(silentSettingsListener: OnSilentSettingsListener) {
+ Utils.enforceMainLooper()
+ mSilentSettingsModel?.addSilentSettingsListener(silentSettingsListener)
+ }
+
+ /**
+ * @param silentSettingsListener to no longer be notified when alarm-silencing settings change
+ */
+ fun removeSilentSettingsListener(silentSettingsListener: OnSilentSettingsListener) {
+ Utils.enforceMainLooper()
+ mSilentSettingsModel?.removeSilentSettingsListener(silentSettingsListener)
+ }
+
+ /**
+ * @return the id used to discriminate relevant AlarmManager callbacks from defunct ones
+ */
+ val globalIntentId: Int
+ get() = mSettingsModel!!.globalIntentId
+
+ /**
+ * Update the id used to discriminate relevant AlarmManager callbacks from defunct ones
+ */
+ fun updateGlobalIntentId() {
+ Utils.enforceMainLooper()
+ mSettingsModel!!.updateGlobalIntentId()
+ }
+
+ /**
+ * @return the style of clock to display in the clock application
+ */
+ val clockStyle: ClockStyle
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.clockStyle
+ }
+
+ var displayClockSeconds: Boolean
+ /**
+ * @return the style of clock to display in the clock application
+ */
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.displayClockSeconds
+ }
+ /**
+ * @param displaySeconds whether or not to display seconds for main clock
+ */
+ set(displaySeconds) {
+ Utils.enforceMainLooper()
+ mSettingsModel!!.displayClockSeconds = displaySeconds
+ }
+
+ /**
+ * @return the style of clock to display in the clock screensaver
+ */
+ val screensaverClockStyle: ClockStyle
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.screensaverClockStyle
+ }
+
+ /**
+ * @return `true` if the screen saver should be dimmed for lower contrast at night
+ */
+ val screensaverNightModeOn: Boolean
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.screensaverNightModeOn
+ }
+
+ /**
+ * @return `true` if the users wants to automatically show a clock for their home timezone
+ * when they have travelled outside of that timezone
+ */
+ val showHomeClock: Boolean
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.showHomeClock
+ }
+
+ /**
+ * @return the display order of the weekdays, which can start with [Calendar.SATURDAY],
+ * [Calendar.SUNDAY] or [Calendar.MONDAY]
+ */
+ val weekdayOrder: Weekdays.Order
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.weekdayOrder
+ }
+
+ var isRestoreBackupFinished: Boolean
+ /**
+ * @return `true` if the restore process (of backup and restore) has completed
+ */
+ get() = mSettingsModel!!.isRestoreBackupFinished
+ /**
+ * @param finished `true` means the restore process (of backup and restore) has completed
+ */
+ set(finished) {
+ mSettingsModel!!.isRestoreBackupFinished = finished
+ }
+
+ /**
+ * @return a description of the time zones available for selection
+ */
+ val timeZones: TimeZones
+ get() {
+ Utils.enforceMainLooper()
+ return mSettingsModel!!.timeZones
+ }
+
+ /**
+ * Used to execute a delegate runnable and track its completion.
+ */
+ private class ExecutedRunnable(private val mDelegate: Runnable) : Runnable, java.lang.Object() {
+ var isExecuted = false
+ override fun run() {
+ mDelegate.run()
+ synchronized(this) {
+ isExecuted = true
+ notifyAll()
+ }
+ }
+ }
+
+ companion object {
+ const val ACTION_WORLD_CITIES_CHANGED = "com.android.deskclock.WORLD_CITIES_CHANGED"
+
+ /** The single instance of this data model that exists for the life of the application. */
+ val sDataModel = DataModel()
+
+ @get:JvmStatic
+ val dataModel
+ get() = sDataModel
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/deskclock/data/SettingsModel.kt b/src/com/android/deskclock/data/SettingsModel.kt
index bfbb8d7..040c791 100644
--- a/src/com/android/deskclock/data/SettingsModel.kt
+++ b/src/com/android/deskclock/data/SettingsModel.kt
@@ -60,7 +60,7 @@
val homeTimeZone: TimeZone
get() = SettingsDAO.getHomeTimeZone(mContext, mPrefs, TimeZone.getDefault())
- val clockStyle: DataModel.ClockStyle?
+ val clockStyle: DataModel.ClockStyle
get() = SettingsDAO.getClockStyle(mContext, mPrefs)
var displayClockSeconds: Boolean
@@ -69,7 +69,7 @@
SettingsDAO.setDisplayClockSeconds(mPrefs, shouldDisplaySeconds)
}
- val screensaverClockStyle: DataModel.ClockStyle?
+ val screensaverClockStyle: DataModel.ClockStyle
get() = SettingsDAO.getScreensaverClockStyle(mContext, mPrefs)
val screensaverNightModeOn: Boolean
diff --git a/src/com/android/deskclock/data/StopwatchNotificationBuilder.kt b/src/com/android/deskclock/data/StopwatchNotificationBuilder.kt
index 7671b05..a4bd9b8 100644
--- a/src/com/android/deskclock/data/StopwatchNotificationBuilder.kt
+++ b/src/com/android/deskclock/data/StopwatchNotificationBuilder.kt
@@ -87,7 +87,7 @@
actions.add(Action.Builder(icon1, title1, intent1).build())
// Right button: Add Lap
- if (DataModel.getDataModel().canAddMoreLaps()) {
+ if (DataModel.dataModel.canAddMoreLaps()) {
val lap: Intent = Intent(context, StopwatchService::class.java)
.setAction(StopwatchService.ACTION_LAP_STOPWATCH)
.putExtra(Events.EXTRA_EVENT_LABEL, eventLabel)
@@ -99,7 +99,7 @@
}
// Show the current lap number if any laps have been recorded.
- val lapCount = DataModel.getDataModel().laps.size
+ val lapCount = DataModel.dataModel.laps.size
if (lapCount > 0) {
val lapNumber = lapCount + 1
val lap: String = res.getString(R.string.sw_notification_lap_number, lapNumber)
diff --git a/src/com/android/deskclock/data/TimerModel.kt b/src/com/android/deskclock/data/TimerModel.kt
index 1ca630d..55ac14d 100644
--- a/src/com/android/deskclock/data/TimerModel.kt
+++ b/src/com/android/deskclock/data/TimerModel.kt
@@ -385,7 +385,7 @@
/**
* @return the title of the ringtone that is played for all timers
*/
- val timerRingtoneTitle: String?
+ val timerRingtoneTitle: String
get() {
if (mTimerRingtoneTitle == null) {
mTimerRingtoneTitle = if (isTimerRingtoneSilent) {
@@ -403,7 +403,7 @@
}
}
- return mTimerRingtoneTitle
+ return mTimerRingtoneTitle!!
}
/**
diff --git a/src/com/android/deskclock/provider/Alarm.kt b/src/com/android/deskclock/provider/Alarm.kt
index 2e7c4ec..729d059 100644
--- a/src/com/android/deskclock/provider/Alarm.kt
+++ b/src/com/android/deskclock/provider/Alarm.kt
@@ -84,7 +84,7 @@
vibrate = true
daysOfWeek = Weekdays.NONE
label = ""
- alert = DataModel.getDataModel().defaultAlarmRingtoneUri
+ alert = DataModel.dataModel.defaultAlarmRingtoneUri
deleteAfterUse = false
}
@@ -381,7 +381,7 @@
override fun loadInBackground(): Cursor {
// Prime the ringtone title cache for later access. Most alarms will refer to
// system ringtones.
- DataModel.getDataModel().loadRingtoneTitles()
+ DataModel.dataModel.loadRingtoneTitles()
return super.loadInBackground()
}
}
diff --git a/src/com/android/deskclock/provider/AlarmInstance.kt b/src/com/android/deskclock/provider/AlarmInstance.kt
index 810930c..d69ae5b 100644
--- a/src/com/android/deskclock/provider/AlarmInstance.kt
+++ b/src/com/android/deskclock/provider/AlarmInstance.kt
@@ -201,7 +201,7 @@
*/
val timeout: Calendar?
get() {
- val timeoutMinutes = DataModel.getDataModel().alarmTimeout
+ val timeoutMinutes = DataModel.dataModel.alarmTimeout
// Alarm silence has been set to "None"
if (timeoutMinutes < 0) {
diff --git a/src/com/android/deskclock/settings/AlarmVolumePreference.kt b/src/com/android/deskclock/settings/AlarmVolumePreference.kt
index 51f4ec6..790469f 100644
--- a/src/com/android/deskclock/settings/AlarmVolumePreference.kt
+++ b/src/com/android/deskclock/settings/AlarmVolumePreference.kt
@@ -90,7 +90,7 @@
if (!mPreviewPlaying && seekBar.getProgress() != 0) {
// If we are not currently playing and progress is set to non-zero, start.
RingtonePreviewKlaxon
- .start(context, DataModel.getDataModel().defaultAlarmRingtoneUri)
+ .start(context, DataModel.dataModel.defaultAlarmRingtoneUri)
mPreviewPlaying = true
seekBar.postDelayed(Runnable {
RingtonePreviewKlaxon.stop(context)
diff --git a/src/com/android/deskclock/settings/SettingsActivity.kt b/src/com/android/deskclock/settings/SettingsActivity.kt
index dc854a1..8c7cbfc 100644
--- a/src/com/android/deskclock/settings/SettingsActivity.kt
+++ b/src/com/android/deskclock/settings/SettingsActivity.kt
@@ -139,7 +139,7 @@
pref.setSummary(simpleMenuPreference.getEntries().get(i))
}
KEY_CLOCK_DISPLAY_SECONDS -> {
- DataModel.getDataModel().displayClockSeconds = newValue as Boolean
+ DataModel.dataModel.displayClockSeconds = newValue as Boolean
}
KEY_AUTO_SILENCE -> {
val delay = newValue as String
@@ -152,9 +152,9 @@
}
KEY_TIMER_VIBRATE -> {
val timerVibratePref: TwoStatePreference = pref as TwoStatePreference
- DataModel.getDataModel().timerVibrate = timerVibratePref.isChecked()
+ DataModel.dataModel.timerVibrate = timerVibratePref.isChecked()
}
- KEY_TIMER_RINGTONE -> pref.setSummary(DataModel.getDataModel().timerRingtoneTitle)
+ KEY_TIMER_RINGTONE -> pref.setSummary(DataModel.dataModel.timerRingtoneTitle)
}
// Set result so DeskClock knows to refresh itself
@@ -209,7 +209,7 @@
* Reconstruct the timezone list.
*/
private fun loadTimeZoneList() {
- val timezones = DataModel.getDataModel().timeZones
+ val timezones = DataModel.dataModel.timeZones
val homeTimezonePref: ListPreference? = findPreference(KEY_HOME_TZ)
homeTimezonePref?.let {
it.setEntryValues(timezones.timeZoneIds)
@@ -260,7 +260,7 @@
val weekStartPref: SimpleMenuPreference? = findPreference(KEY_WEEK_START)
// Set the default value programmatically
- val weekdayOrder = DataModel.getDataModel().weekdayOrder
+ val weekdayOrder = DataModel.dataModel.weekdayOrder
val firstDay = weekdayOrder.calendarDays[0]
val value = firstDay.toString()
weekStartPref?.let {
@@ -273,7 +273,7 @@
val timerRingtonePref: Preference? = findPreference(KEY_TIMER_RINGTONE)
timerRingtonePref?.let {
it.setOnPreferenceClickListener(this)
- it.setSummary(DataModel.getDataModel().timerRingtoneTitle)
+ it.setSummary(DataModel.dataModel.timerRingtoneTitle)
}
}
diff --git a/src/com/android/deskclock/stopwatch/LapsAdapter.kt b/src/com/android/deskclock/stopwatch/LapsAdapter.kt
index 4357748..798f7a6 100644
--- a/src/com/android/deskclock/stopwatch/LapsAdapter.kt
+++ b/src/com/android/deskclock/stopwatch/LapsAdapter.kt
@@ -87,7 +87,7 @@
} else {
// For the current lap, compute times relative to the stopwatch.
totalTime = stopwatch.totalTime
- lapTime = DataModel.getDataModel().getCurrentLapTime(totalTime)
+ lapTime = DataModel.dataModel.getCurrentLapTime(totalTime)
lapNumber = laps.size + 1
}
@@ -119,7 +119,7 @@
val currentLapView: View? = rv.getChildAt(0)
if (currentLapView != null) {
// Compute the lap time using the total time.
- val lapTime = DataModel.getDataModel().getCurrentLapTime(totalTime)
+ val lapTime = DataModel.dataModel.getCurrentLapTime(totalTime)
val holder = rv.getChildViewHolder(currentLapView) as LapItemHolder
holder.lapTime.setText(formatLapTime(lapTime, false))
holder.accumulatedTime.setText(formatAccumulatedTime(totalTime, false))
@@ -132,7 +132,7 @@
* @return a newly cleared lap
*/
fun addLap(): Lap? {
- val lap = DataModel.getDataModel().addLap()
+ val lap = DataModel.dataModel.addLap()
if (itemCount == 10) {
// 10 total laps indicates all items switch from 1 to 2 digit lap numbers.
@@ -195,7 +195,7 @@
// Append the final lap
builder.append(laps.size + 1)
builder.append(separator)
- val lapTime = DataModel.getDataModel().getCurrentLapTime(totalTime)
+ val lapTime = DataModel.dataModel.getCurrentLapTime(totalTime)
builder.append(formatTime(lapTime, lapTime, " "))
builder.append("\n")
}
@@ -224,7 +224,7 @@
*/
private fun formatLapTime(lapTime: Long, isBinding: Boolean): String {
// The longest lap dictates the way the given lapTime must be formatted.
- val longestLapTime = max(DataModel.getDataModel().longestLapTime, lapTime)
+ val longestLapTime = max(DataModel.dataModel.longestLapTime, lapTime)
val formattedTime = formatTime(longestLapTime, lapTime, LRM_SPACE)
// If the newly formatted lap time has altered the format, refresh all laps.
@@ -259,10 +259,10 @@
}
private val stopwatch: Stopwatch
- get() = DataModel.getDataModel().stopwatch
+ get() = DataModel.dataModel.stopwatch
private val laps: List<Lap>
- get() = DataModel.getDataModel().laps
+ get() = DataModel.dataModel.laps
/**
* Cache the child views of each lap item view.
diff --git a/src/com/android/deskclock/stopwatch/StopwatchCircleView.kt b/src/com/android/deskclock/stopwatch/StopwatchCircleView.kt
index 305b7b1..a7d8699 100644
--- a/src/com/android/deskclock/stopwatch/StopwatchCircleView.kt
+++ b/src/com/android/deskclock/stopwatch/StopwatchCircleView.kt
@@ -109,7 +109,7 @@
val laps = laps
// If a reference lap does not exist or should not be drawn, draw a simple white circle.
- if (laps.isEmpty() || !DataModel.getDataModel().canAddMoreLaps()) {
+ if (laps.isEmpty() || !DataModel.dataModel.canAddMoreLaps()) {
// Draw a complete white circle; no red arc required.
canvas.drawCircle(xCenter.toFloat(), yCenter.toFloat(), radius, mPaint)
@@ -164,8 +164,8 @@
}
private val stopwatch: Stopwatch
- get() = DataModel.getDataModel().stopwatch
+ get() = DataModel.dataModel.stopwatch
private val laps: List<Lap>
- get() = DataModel.getDataModel().laps
+ get() = DataModel.dataModel.laps
}
\ No newline at end of file
diff --git a/src/com/android/deskclock/stopwatch/StopwatchFragment.kt b/src/com/android/deskclock/stopwatch/StopwatchFragment.kt
index 660ca44..d048817 100644
--- a/src/com/android/deskclock/stopwatch/StopwatchFragment.kt
+++ b/src/com/android/deskclock/stopwatch/StopwatchFragment.kt
@@ -144,7 +144,7 @@
mStopwatchTextController = StopwatchTextController(mMainTimeText, mHundredthsTimeText)
mStopwatchWrapper = v.findViewById(R.id.stopwatch_time_wrapper)
- DataModel.getDataModel().addStopwatchListener(mStopwatchWatcher)
+ DataModel.dataModel.addStopwatchListener(mStopwatchWatcher)
mStopwatchWrapper.setOnClickListener(TimeClickListener())
if (mTime != null) {
@@ -173,11 +173,11 @@
if (intent != null) {
val action: String? = intent.getAction()
if (StopwatchService.Companion.ACTION_START_STOPWATCH == action) {
- DataModel.getDataModel().startStopwatch()
+ DataModel.dataModel.startStopwatch()
// Consume the intent
activity.setIntent(null)
} else if (StopwatchService.Companion.ACTION_PAUSE_STOPWATCH == action) {
- DataModel.getDataModel().pauseStopwatch()
+ DataModel.dataModel.pauseStopwatch()
// Consume the intent
activity.setIntent(null)
}
@@ -209,7 +209,7 @@
override fun onDestroyView() {
super.onDestroyView()
- DataModel.getDataModel().removeStopwatchListener(mStopwatchWatcher)
+ DataModel.dataModel.removeStopwatchListener(mStopwatchWatcher)
}
override fun onFabClick(fab: ImageView) {
@@ -306,7 +306,7 @@
*/
private fun doStart() {
Events.sendStopwatchEvent(R.string.action_start, R.string.label_deskclock)
- DataModel.getDataModel().startStopwatch()
+ DataModel.dataModel.startStopwatch()
}
/**
@@ -314,7 +314,7 @@
*/
private fun doPause() {
Events.sendStopwatchEvent(R.string.action_pause, R.string.label_deskclock)
- DataModel.getDataModel().pauseStopwatch()
+ DataModel.dataModel.pauseStopwatch()
}
/**
@@ -323,7 +323,7 @@
private fun doReset() {
val priorState = stopwatch.state
Events.sendStopwatchEvent(R.string.action_reset, R.string.label_deskclock)
- DataModel.getDataModel().resetStopwatch()
+ DataModel.dataModel.resetStopwatch()
mMainTimeText.setAlpha(1f)
mHundredthsTimeText.setAlpha(1f)
if (priorState == Stopwatch.State.RUNNING) {
@@ -421,7 +421,7 @@
}
private fun adjustWakeLock() {
- val appInForeground = DataModel.getDataModel().isApplicationInForeground
+ val appInForeground = DataModel.dataModel.isApplicationInForeground
if (stopwatch.isRunning && isTabSelected && appInForeground) {
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
@@ -445,9 +445,9 @@
}
private val stopwatch: Stopwatch
- get() = DataModel.getDataModel().stopwatch
+ get() = DataModel.dataModel.stopwatch
- private fun canRecordMoreLaps(): Boolean = DataModel.getDataModel().canAddMoreLaps()
+ private fun canRecordMoreLaps(): Boolean = DataModel.dataModel.canAddMoreLaps()
/**
* Post the first runnable to update times within the UI. It will reschedule itself as needed.
@@ -561,12 +561,12 @@
if (after.isReset) {
// Ensure the drop shadow is hidden when the stopwatch is reset.
setTabScrolledToTop(true)
- if (DataModel.getDataModel().isApplicationInForeground) {
+ if (DataModel.dataModel.isApplicationInForeground) {
updateUI(FabContainer.BUTTONS_IMMEDIATE)
}
return
}
- if (DataModel.getDataModel().isApplicationInForeground) {
+ if (DataModel.dataModel.isApplicationInForeground) {
updateUI(FabContainer.FAB_MORPH or FabContainer.BUTTONS_IMMEDIATE)
}
}
@@ -582,9 +582,9 @@
override fun onClick(view: View?) {
if (stopwatch.isRunning) {
- DataModel.getDataModel().pauseStopwatch()
+ DataModel.dataModel.pauseStopwatch()
} else {
- DataModel.getDataModel().startStopwatch()
+ DataModel.dataModel.startStopwatch()
}
}
}
diff --git a/src/com/android/deskclock/stopwatch/StopwatchService.kt b/src/com/android/deskclock/stopwatch/StopwatchService.kt
index 0ce936d..aba659a 100644
--- a/src/com/android/deskclock/stopwatch/StopwatchService.kt
+++ b/src/com/android/deskclock/stopwatch/StopwatchService.kt
@@ -52,19 +52,19 @@
}
ACTION_START_STOPWATCH -> {
Events.sendStopwatchEvent(R.string.action_start, label)
- DataModel.getDataModel().startStopwatch()
+ DataModel.dataModel.startStopwatch()
}
ACTION_PAUSE_STOPWATCH -> {
Events.sendStopwatchEvent(R.string.action_pause, label)
- DataModel.getDataModel().pauseStopwatch()
+ DataModel.dataModel.pauseStopwatch()
}
ACTION_RESET_STOPWATCH -> {
Events.sendStopwatchEvent(R.string.action_reset, label)
- DataModel.getDataModel().resetStopwatch()
+ DataModel.dataModel.resetStopwatch()
}
ACTION_LAP_STOPWATCH -> {
Events.sendStopwatchEvent(R.string.action_lap, label)
- DataModel.getDataModel().addLap()
+ DataModel.dataModel.addLap()
}
}
diff --git a/src/com/android/deskclock/worldclock/CitySelectionActivity.java b/src/com/android/deskclock/worldclock/CitySelectionActivity.java
index d8954d0..13e85c4 100644
--- a/src/com/android/deskclock/worldclock/CitySelectionActivity.java
+++ b/src/com/android/deskclock/worldclock/CitySelectionActivity.java
@@ -497,7 +497,7 @@
mIs24HoursMode = DateFormat.is24HourFormat(mContext);
// Refresh the user selections.
- final List<City> selected = DataModel.getDataModel().getSelectedCities();
+ final List<City> selected = (List<City>) DataModel.getDataModel().getSelectedCities();
mUserSelectedCities.clear();
mUserSelectedCities.addAll(selected);
mOriginalUserSelectionCount = selected.size();