1 /* 2 * Copyright (C) 2015 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.Context; 20 import android.content.SharedPreferences; 21 import android.preference.PreferenceManager; 22 23 import com.android.deskclock.Utils; 24 import com.android.deskclock.data.Stopwatch.State; 25 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.List; 29 30 import static com.android.deskclock.data.Stopwatch.State.RESET; 31 32 /** 33 * This class encapsulates the transfer of data between {@link Stopwatch} and {@link Lap} domain 34 * objects and their permanent storage in {@link SharedPreferences}. 35 */ 36 final class StopwatchDAO { 37 38 // Key to a preference that stores the state of the stopwatch. 39 private static final String STATE = "sw_state"; 40 41 // Key to a preference that stores the last start time of the stopwatch. 42 private static final String LAST_START_TIME = "sw_start_time"; 43 44 // Key to a preference that stores the accumulated elapsed time of the stopwatch. 45 private static final String ACCUMULATED_TIME = "sw_accum_time"; 46 47 // Key to a preference that stores the number of recorded laps. 48 private static final String LAP_COUNT = "sw_lap_num"; 49 50 // Prefix for a key to a preference that stores accumulated time at the end of a particular lap. 51 private static final String LAP_ACCUMULATED_TIME = "sw_lap_time_"; 52 53 // Lazily instantiated and cached for the life of the application. 54 private static SharedPreferences sPrefs; 55 56 private StopwatchDAO() {} 57 58 /** 59 * @return the stopwatch from permanent storage or a reset stopwatch if none exists 60 */ 61 public static Stopwatch getStopwatch(Context context) { 62 final SharedPreferences prefs = getSharedPreferences(context); 63 final int stateIndex = prefs.getInt(STATE, RESET.ordinal()); 64 final State state = State.values()[stateIndex]; 65 final long lastStartTime = prefs.getLong(LAST_START_TIME, Long.MIN_VALUE); 66 final long accumulatedTime = prefs.getLong(ACCUMULATED_TIME, 0); 67 return new Stopwatch(state, lastStartTime, accumulatedTime); 68 } 69 70 /** 71 * @param stopwatch the last state of the stopwatch 72 */ 73 public static void setStopwatch(Context context, Stopwatch stopwatch) { 74 final SharedPreferences prefs = getSharedPreferences(context); 75 final SharedPreferences.Editor editor = prefs.edit(); 76 77 if (stopwatch.isReset()) { 78 editor.remove(STATE) 79 .remove(LAST_START_TIME) 80 .remove(ACCUMULATED_TIME); 81 } else { 82 editor.putInt(STATE, stopwatch.getState().ordinal()) 83 .putLong(LAST_START_TIME, stopwatch.getLastStartTime()) 84 .putLong(ACCUMULATED_TIME, stopwatch.getAccumulatedTime()); 85 } 86 87 editor.apply(); 88 } 89 90 /** 91 * @return a list of recorded laps for the stopwatch 92 */ 93 public static List<Lap> getLaps(Context context) { 94 final SharedPreferences prefs = getSharedPreferences(context); 95 96 // Prepare the container to be filled with laps. 97 final int lapCount = prefs.getInt(LAP_COUNT, 0); 98 final List<Lap> laps = new ArrayList<>(lapCount); 99 100 long prevAccumulatedTime = 0; 101 102 // Lap numbers are 1-based and so the are corresponding shared preference keys. 103 for (int lapNumber = 1; lapNumber <= lapCount; lapNumber++) { 104 // Look up the accumulated time for the lap. 105 final String lapAccumulatedTimeKey = LAP_ACCUMULATED_TIME + lapNumber; 106 final long accumulatedTime = prefs.getLong(lapAccumulatedTimeKey, 0); 107 108 // Lap time is the delta between accumulated time of this lap and prior lap. 109 final long lapTime = accumulatedTime - prevAccumulatedTime; 110 111 // Create the lap instance from the data. 112 laps.add(new Lap(lapNumber, lapTime, accumulatedTime)); 113 114 // Update the accumulated time of the previous lap. 115 prevAccumulatedTime = accumulatedTime; 116 } 117 118 // Laps are stored in the order they were recorded; display order is the reverse. 119 Collections.reverse(laps); 120 121 return laps; 122 } 123 124 /** 125 * @param newLapCount the number of laps including the new lap 126 * @param accumulatedTime the amount of time accumulate by the stopwatch at the end of the lap 127 */ 128 public static void addLap(Context context, int newLapCount, long accumulatedTime) { 129 getSharedPreferences(context).edit() 130 .putInt(LAP_COUNT, newLapCount) 131 .putLong(LAP_ACCUMULATED_TIME + newLapCount, accumulatedTime) 132 .apply(); 133 } 134 135 /** 136 * Remove the recorded laps for the stopwatch 137 */ 138 public static void clearLaps(Context context) { 139 final SharedPreferences prefs = getSharedPreferences(context); 140 final SharedPreferences.Editor editor = prefs.edit(); 141 142 final int lapCount = prefs.getInt(LAP_COUNT, 0); 143 for (int lapNumber = 1; lapNumber <= lapCount; lapNumber++) { 144 editor.remove(LAP_ACCUMULATED_TIME + lapNumber); 145 } 146 editor.remove(LAP_COUNT); 147 148 editor.apply(); 149 } 150 151 private static SharedPreferences getSharedPreferences(Context context) { 152 if (sPrefs == null) { 153 sPrefs = Utils.getDefaultSharedPreferences(context.getApplicationContext()); 154 } 155 156 return sPrefs; 157 } 158 } 159