/* * 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.content.SharedPreferences /** * This class encapsulates the transfer of data between [Stopwatch] and [Lap] domain * objects and their permanent storage in [SharedPreferences]. */ internal object StopwatchDAO { /** Key to a preference that stores the state of the stopwatch. */ private const val STATE = "sw_state" /** Key to a preference that stores the last start time of the stopwatch. */ private const val LAST_START_TIME = "sw_start_time" /** Key to a preference that stores the epoch time when the stopwatch last started. */ private const val LAST_WALL_CLOCK_TIME = "sw_wall_clock_time" /** Key to a preference that stores the accumulated elapsed time of the stopwatch. */ private const val ACCUMULATED_TIME = "sw_accum_time" /** Prefix for a key to a preference that stores the number of recorded laps. */ private const val LAP_COUNT = "sw_lap_num" /** Prefix for a key to a preference that stores accumulated time at the end of a lap. */ private const val LAP_ACCUMULATED_TIME = "sw_lap_time_" /** * @return the stopwatch from permanent storage or a reset stopwatch if none exists */ fun getStopwatch(prefs: SharedPreferences): Stopwatch { val stateIndex: Int = prefs.getInt(STATE, Stopwatch.State.RESET.ordinal) val state = Stopwatch.State.values()[stateIndex] val lastStartTime: Long = prefs.getLong(LAST_START_TIME, Stopwatch.UNUSED) val lastWallClockTime: Long = prefs.getLong(LAST_WALL_CLOCK_TIME, Stopwatch.UNUSED) val accumulatedTime: Long = prefs.getLong(ACCUMULATED_TIME, 0) var s = Stopwatch(state, lastStartTime, lastWallClockTime, accumulatedTime) // If the stopwatch reports an illegal (negative) amount of time, remove the bad data. if (s.totalTime < 0) { s = s.reset() setStopwatch(prefs, s) } return s } /** * @param stopwatch the last state of the stopwatch */ fun setStopwatch(prefs: SharedPreferences, stopwatch: Stopwatch) { val editor: SharedPreferences.Editor = prefs.edit() if (stopwatch.isReset) { editor.remove(STATE) .remove(LAST_START_TIME) .remove(LAST_WALL_CLOCK_TIME) .remove(ACCUMULATED_TIME) } else { editor.putInt(STATE, stopwatch.state.ordinal) .putLong(LAST_START_TIME, stopwatch.lastStartTime) .putLong(LAST_WALL_CLOCK_TIME, stopwatch.lastWallClockTime) .putLong(ACCUMULATED_TIME, stopwatch.accumulatedTime) } editor.apply() } /** * @return a list of recorded laps for the stopwatch */ fun getLaps(prefs: SharedPreferences): MutableList { // Prepare the container to be filled with laps. val lapCount: Int = prefs.getInt(LAP_COUNT, 0) val laps: MutableList = mutableListOf() var prevAccumulatedTime: Long = 0 // Lap numbers are 1-based and so the are corresponding shared preference keys. for (lapNumber in 1..lapCount) { // Look up the accumulated time for the lap. val lapAccumulatedTimeKey = LAP_ACCUMULATED_TIME + lapNumber val accumulatedTime: Long = prefs.getLong(lapAccumulatedTimeKey, 0) // Lap time is the delta between accumulated time of this lap and prior lap. val lapTime = accumulatedTime - prevAccumulatedTime // Create the lap instance from the data. laps.add(Lap(lapNumber, lapTime, accumulatedTime)) // Update the accumulated time of the previous lap. prevAccumulatedTime = accumulatedTime } // Laps are stored in the order they were recorded; display order is the reverse. laps.reverse() return laps } /** * @param newLapCount the number of laps including the new lap * @param accumulatedTime the amount of time accumulate by the stopwatch at the end of the lap */ fun addLap(prefs: SharedPreferences, newLapCount: Int, accumulatedTime: Long) { prefs.edit() .putInt(LAP_COUNT, newLapCount) .putLong(LAP_ACCUMULATED_TIME + newLapCount, accumulatedTime) .apply() } /** * Remove the recorded laps for the stopwatch */ fun clearLaps(prefs: SharedPreferences) { val editor: SharedPreferences.Editor = prefs.edit() val lapCount: Int = prefs.getInt(LAP_COUNT, 0) for (lapNumber in 1..lapCount) { editor.remove(LAP_ACCUMULATED_TIME + lapNumber) } editor.remove(LAP_COUNT) editor.apply() } }