• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.deskclock.data
18 
19 import android.content.SharedPreferences
20 
21 /**
22  * This class encapsulates the transfer of data between [Stopwatch] and [Lap] domain
23  * objects and their permanent storage in [SharedPreferences].
24  */
25 internal object StopwatchDAO {
26     /** Key to a preference that stores the state of the stopwatch.  */
27     private const val STATE = "sw_state"
28 
29     /** Key to a preference that stores the last start time of the stopwatch.  */
30     private const val LAST_START_TIME = "sw_start_time"
31 
32     /** Key to a preference that stores the epoch time when the stopwatch last started.  */
33     private const val LAST_WALL_CLOCK_TIME = "sw_wall_clock_time"
34 
35     /** Key to a preference that stores the accumulated elapsed time of the stopwatch.  */
36     private const val ACCUMULATED_TIME = "sw_accum_time"
37 
38     /** Prefix for a key to a preference that stores the number of recorded laps.  */
39     private const val LAP_COUNT = "sw_lap_num"
40 
41     /** Prefix for a key to a preference that stores accumulated time at the end of a lap.  */
42     private const val LAP_ACCUMULATED_TIME = "sw_lap_time_"
43 
44     /**
45      * @return the stopwatch from permanent storage or a reset stopwatch if none exists
46      */
getStopwatchnull47     fun getStopwatch(prefs: SharedPreferences): Stopwatch {
48         val stateIndex: Int = prefs.getInt(STATE, Stopwatch.State.RESET.ordinal)
49         val state = Stopwatch.State.values()[stateIndex]
50         val lastStartTime: Long = prefs.getLong(LAST_START_TIME, Stopwatch.UNUSED)
51         val lastWallClockTime: Long = prefs.getLong(LAST_WALL_CLOCK_TIME, Stopwatch.UNUSED)
52         val accumulatedTime: Long = prefs.getLong(ACCUMULATED_TIME, 0)
53         var s = Stopwatch(state, lastStartTime, lastWallClockTime, accumulatedTime)
54 
55         // If the stopwatch reports an illegal (negative) amount of time, remove the bad data.
56         if (s.totalTime < 0) {
57             s = s.reset()
58             setStopwatch(prefs, s)
59         }
60         return s
61     }
62 
63     /**
64      * @param stopwatch the last state of the stopwatch
65      */
setStopwatchnull66     fun setStopwatch(prefs: SharedPreferences, stopwatch: Stopwatch) {
67         val editor: SharedPreferences.Editor = prefs.edit()
68 
69         if (stopwatch.isReset) {
70             editor.remove(STATE)
71                     .remove(LAST_START_TIME)
72                     .remove(LAST_WALL_CLOCK_TIME)
73                     .remove(ACCUMULATED_TIME)
74         } else {
75             editor.putInt(STATE, stopwatch.state.ordinal)
76                     .putLong(LAST_START_TIME, stopwatch.lastStartTime)
77                     .putLong(LAST_WALL_CLOCK_TIME, stopwatch.lastWallClockTime)
78                     .putLong(ACCUMULATED_TIME, stopwatch.accumulatedTime)
79         }
80 
81         editor.apply()
82     }
83 
84     /**
85      * @return a list of recorded laps for the stopwatch
86      */
getLapsnull87     fun getLaps(prefs: SharedPreferences): MutableList<Lap> {
88         // Prepare the container to be filled with laps.
89         val lapCount: Int = prefs.getInt(LAP_COUNT, 0)
90         val laps: MutableList<Lap> = mutableListOf()
91 
92         var prevAccumulatedTime: Long = 0
93 
94         // Lap numbers are 1-based and so the are corresponding shared preference keys.
95         for (lapNumber in 1..lapCount) {
96             // Look up the accumulated time for the lap.
97             val lapAccumulatedTimeKey = LAP_ACCUMULATED_TIME + lapNumber
98             val accumulatedTime: Long = prefs.getLong(lapAccumulatedTimeKey, 0)
99 
100             // Lap time is the delta between accumulated time of this lap and prior lap.
101             val lapTime = accumulatedTime - prevAccumulatedTime
102 
103             // Create the lap instance from the data.
104             laps.add(Lap(lapNumber, lapTime, accumulatedTime))
105 
106             // Update the accumulated time of the previous lap.
107             prevAccumulatedTime = accumulatedTime
108         }
109 
110         // Laps are stored in the order they were recorded; display order is the reverse.
111         laps.reverse()
112 
113         return laps
114     }
115 
116     /**
117      * @param newLapCount the number of laps including the new lap
118      * @param accumulatedTime the amount of time accumulate by the stopwatch at the end of the lap
119      */
addLapnull120     fun addLap(prefs: SharedPreferences, newLapCount: Int, accumulatedTime: Long) {
121         prefs.edit()
122                 .putInt(LAP_COUNT, newLapCount)
123                 .putLong(LAP_ACCUMULATED_TIME + newLapCount, accumulatedTime)
124                 .apply()
125     }
126 
127     /**
128      * Remove the recorded laps for the stopwatch
129      */
clearLapsnull130     fun clearLaps(prefs: SharedPreferences) {
131         val editor: SharedPreferences.Editor = prefs.edit()
132 
133         val lapCount: Int = prefs.getInt(LAP_COUNT, 0)
134         for (lapNumber in 1..lapCount) {
135             editor.remove(LAP_ACCUMULATED_TIME + lapNumber)
136         }
137         editor.remove(LAP_COUNT)
138 
139         editor.apply()
140     }
141 }