1/* 2 * Copyright (C) 2012 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 17package com.android.deskclock.timer; 18 19import android.content.Context; 20import android.content.SharedPreferences; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.preference.PreferenceManager; 24import android.util.Log; 25 26import com.android.deskclock.R; 27import com.android.deskclock.Utils; 28 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.Comparator; 32import java.util.HashSet; 33import java.util.Iterator; 34import java.util.Set; 35 36public class TimerObj implements Parcelable { 37 38 public static final String KEY_NEXT_TIMER_ID = "next_timer_id"; 39 40 private static final String TAG = "TimerObj"; 41 // Max timer length is 9 hours + 99 minutes + 9 seconds 42 public static final long MAX_TIMER_LENGTH = (9 * 3600 + 99 * 60 + 99) * 1000; 43 public static final long MINUTE_IN_MILLIS = 60 * 1000; 44 45 public int mTimerId; // Unique id 46 public long mStartTime; // With mTimeLeft , used to calculate the correct time 47 public long mTimeLeft; // in the timer. 48 public long mOriginalLength; // length set at start of timer and by +1 min after times up 49 public long mSetupLength; // length set at start of timer 50 public TimerListItem mView; 51 public int mState; 52 public String mLabel; 53 public boolean mDeleteAfterUse; 54 55 public static final int STATE_RUNNING = 1; 56 public static final int STATE_STOPPED = 2; 57 public static final int STATE_TIMESUP = 3; 58 public static final int STATE_DONE = 4; 59 public static final int STATE_RESTART = 5; 60 public static final int STATE_DELETED = 6; 61 62 private static final String PREF_TIMER_ID = "timer_id_"; 63 private static final String PREF_START_TIME = "timer_start_time_"; 64 private static final String PREF_TIME_LEFT = "timer_time_left_"; 65 private static final String PREF_ORIGINAL_TIME = "timer_original_timet_"; 66 private static final String PREF_SETUP_TIME = "timer_setup_timet_"; 67 private static final String PREF_STATE = "timer_state_"; 68 private static final String PREF_LABEL = "timer_label_"; 69 private static final String PREF_DELETE_AFTER_USE = "delete_after_use_"; 70 71 private static final String PREF_TIMERS_LIST = "timers_list"; 72 73 public static final Parcelable.Creator<TimerObj> CREATOR = new Parcelable.Creator<TimerObj>() { 74 @Override 75 public TimerObj createFromParcel(Parcel p) { 76 return new TimerObj(p); 77 } 78 79 @Override 80 public TimerObj[] newArray(int size) { 81 return new TimerObj[size]; 82 } 83 }; 84 85 public void writeToSharedPref(SharedPreferences prefs) { 86 final SharedPreferences.Editor editor = prefs.edit(); 87 final String id = Integer.toString(mTimerId); 88 editor.putInt(PREF_TIMER_ID + id, mTimerId); 89 editor.putLong(PREF_START_TIME + id, mStartTime); 90 editor.putLong (PREF_TIME_LEFT + id, mTimeLeft); 91 editor.putLong (PREF_ORIGINAL_TIME + id, mOriginalLength); 92 editor.putLong (PREF_SETUP_TIME + id, mSetupLength); 93 editor.putInt(PREF_STATE + id, mState); 94 final Set <String> timersList = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()); 95 timersList.add(id); 96 editor.putStringSet(PREF_TIMERS_LIST, timersList); 97 editor.putString(PREF_LABEL + id, mLabel); 98 editor.putBoolean(PREF_DELETE_AFTER_USE + id, mDeleteAfterUse); 99 editor.apply(); 100 } 101 102 public void readFromSharedPref(SharedPreferences prefs) { 103 String id = Integer.toString(mTimerId); 104 String key = PREF_START_TIME + id; 105 mStartTime = prefs.getLong(key, 0); 106 key = PREF_TIME_LEFT + id; 107 mTimeLeft = prefs.getLong(key, 0); 108 key = PREF_ORIGINAL_TIME + id; 109 mOriginalLength = prefs.getLong(key, 0); 110 key = PREF_SETUP_TIME + id; 111 mSetupLength = prefs.getLong(key, 0); 112 key = PREF_STATE + id; 113 mState = prefs.getInt(key, 0); 114 key = PREF_LABEL + id; 115 mLabel = prefs.getString(key, ""); 116 key = PREF_DELETE_AFTER_USE + id; 117 mDeleteAfterUse = prefs.getBoolean(key, false); 118 } 119 120 public void deleteFromSharedPref(SharedPreferences prefs) { 121 SharedPreferences.Editor editor = prefs.edit(); 122 String key = PREF_TIMER_ID + Integer.toString(mTimerId); 123 String id = Integer.toString(mTimerId); 124 editor.remove (key); 125 key = PREF_START_TIME + id; 126 editor.remove (key); 127 key = PREF_TIME_LEFT + id; 128 editor.remove (key); 129 key = PREF_ORIGINAL_TIME + id; 130 editor.remove (key); 131 key = PREF_SETUP_TIME + id; 132 editor.remove (key); 133 key = PREF_STATE + id; 134 editor.remove (key); 135 Set <String> timersList = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()); 136 timersList.remove(id); 137 editor.putStringSet(PREF_TIMERS_LIST, timersList); 138 key = PREF_LABEL + id; 139 editor.remove(key); 140 key = PREF_DELETE_AFTER_USE + id; 141 editor.remove(key); 142 if (timersList.isEmpty()) { 143 editor.remove(KEY_NEXT_TIMER_ID); 144 } 145 editor.commit(); 146 //dumpTimersFromSharedPrefs(prefs); 147 } 148 149 @Override 150 public int describeContents() { 151 return 0; 152 } 153 154 @Override 155 public void writeToParcel(Parcel dest, int flags) { 156 dest.writeInt(mTimerId); 157 dest.writeLong(mStartTime); 158 dest.writeLong(mTimeLeft); 159 dest.writeLong(mOriginalLength); 160 dest.writeLong(mSetupLength); 161 dest.writeInt(mState); 162 dest.writeString(mLabel); 163 } 164 165 public TimerObj(Parcel p) { 166 mTimerId = p.readInt(); 167 mStartTime = p.readLong(); 168 mTimeLeft = p.readLong(); 169 mOriginalLength = p.readLong(); 170 mSetupLength = p.readLong(); 171 mState = p.readInt(); 172 mLabel = p.readString(); 173 } 174 175 private TimerObj() { 176 this(0 /* timerLength */, 0 /* timerId */); 177 } 178 179 public TimerObj(long timerLength, int timerId) { 180 init(timerLength, timerId); 181 } 182 183 public TimerObj(long timerLength, Context context) { 184 init(timerLength, getNextTimerId(context)); 185 } 186 187 public TimerObj(long length, String label, Context context) { 188 this(length, context); 189 mLabel = label != null ? label : ""; 190 } 191 192 private void init (long length, int timerId) { 193 /* TODO: mTimerId must avoid StopwatchService.NOTIFICATION_ID, 194 * TimerReceiver.IN_USE_NOTIFICATION_ID, and alarm ID's (which seem to be 1, 2, ..) 195 */ 196 mTimerId = timerId; 197 mStartTime = Utils.getTimeNow(); 198 mTimeLeft = mOriginalLength = mSetupLength = length; 199 mLabel = ""; 200 } 201 202 private int getNextTimerId(Context context) { 203 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 204 final int nextTimerId; 205 synchronized (TimerObj.class) { 206 nextTimerId = prefs.getInt(KEY_NEXT_TIMER_ID, 0); 207 prefs.edit().putInt(KEY_NEXT_TIMER_ID, nextTimerId + 1).apply(); 208 } 209 return nextTimerId; 210 } 211 212 public long updateTimeLeft(boolean forceUpdate) { 213 if (isTicking() || forceUpdate) { 214 long millis = Utils.getTimeNow(); 215 mTimeLeft = mOriginalLength - (millis - mStartTime); 216 } 217 return mTimeLeft; 218 } 219 220 public String getLabelOrDefault(Context context) { 221 return (mLabel == null || mLabel.length() == 0) ? context.getString( 222 R.string.timer_notification_label) 223 : mLabel; 224 } 225 226 public boolean isTicking() { 227 return mState == STATE_RUNNING || mState == STATE_TIMESUP; 228 } 229 230 public boolean isInUse() { 231 return mState == STATE_RUNNING || mState == STATE_STOPPED; 232 } 233 234 public void addTime(long time) { 235 mTimeLeft = mOriginalLength - (Utils.getTimeNow() - mStartTime); 236 if (mTimeLeft < MAX_TIMER_LENGTH - time) { 237 mOriginalLength += time; 238 } 239 } 240 241 public boolean getDeleteAfterUse() { 242 return mDeleteAfterUse; 243 } 244 245 public long getTimesupTime() { 246 return mStartTime + mOriginalLength; 247 } 248 249 250 public static void getTimersFromSharedPrefs( 251 SharedPreferences prefs, ArrayList<TimerObj> timers) { 252 Object[] timerStrings = 253 prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()).toArray(); 254 if (timerStrings.length > 0) { 255 for (int i = 0; i < timerStrings.length; i++) { 256 TimerObj t = new TimerObj(); 257 t.mTimerId = Integer.parseInt((String)timerStrings[i]); 258 t.readFromSharedPref(prefs); 259 timers.add(t); 260 } 261 Collections.sort(timers, new Comparator<TimerObj>() { 262 @Override 263 public int compare(TimerObj timerObj1, TimerObj timerObj2) { 264 return timerObj1.mTimerId - timerObj2.mTimerId; 265 } 266 }); 267 } 268 } 269 270 public static void getTimersFromSharedPrefs( 271 SharedPreferences prefs, ArrayList<TimerObj> timers, int match) { 272 Object[] timerStrings = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()) 273 .toArray(); 274 if (timerStrings.length > 0) { 275 for (int i = 0; i < timerStrings.length; i++) { 276 TimerObj t = new TimerObj(); 277 t.mTimerId = Integer.parseInt((String) timerStrings[i]); 278 t.readFromSharedPref(prefs); 279 if (t.mState == match) { 280 timers.add(t); 281 } 282 } 283 } 284 } 285 286 public static void putTimersInSharedPrefs( 287 SharedPreferences prefs, ArrayList<TimerObj> timers) { 288 if (timers.size() > 0) { 289 for (int i = 0; i < timers.size(); i++) { 290 timers.get(i).writeToSharedPref(prefs); 291 } 292 } 293 } 294 295 public static void dumpTimersFromSharedPrefs( 296 SharedPreferences prefs) { 297 Object[] timerStrings = 298 prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()).toArray(); 299 Log.v(TAG,"--------------------- timers list in shared prefs"); 300 if (timerStrings.length > 0) { 301 for (int i = 0; i < timerStrings.length; i++) { 302 int id = Integer.parseInt((String)timerStrings[i]); 303 Log.v(TAG,"---------------------timer " + (i + 1) + ": id - " + id); 304 } 305 } 306 } 307 308 public static void resetTimersInSharedPrefs(SharedPreferences prefs) { 309 ArrayList<TimerObj> timers = new ArrayList<TimerObj>(); 310 getTimersFromSharedPrefs(prefs, timers); 311 Iterator<TimerObj> i = timers.iterator(); 312 while(i.hasNext()) { 313 TimerObj t = i.next(); 314 t.mState = TimerObj.STATE_RESTART; 315 t.mTimeLeft = t. mOriginalLength = t.mSetupLength; 316 t.writeToSharedPref(prefs); 317 } 318 } 319 320} 321