1 /* 2 * Copyright 2016 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.example.android.directboot.alarms; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.support.v4.os.BuildCompat; 22 import android.util.Log; 23 24 import java.security.SecureRandom; 25 import java.util.HashSet; 26 import java.util.Map; 27 import java.util.Set; 28 29 /** 30 * Class responsible for saving/retrieving alarms. This class uses SharedPreferences as storage. 31 */ 32 public class AlarmStorage { 33 34 private static final String TAG = AlarmStorage.class.getSimpleName(); 35 private static final String ALARM_PREFERENCES_NAME = "alarm_preferences"; 36 private static final SecureRandom SECURE_RANDOM = new SecureRandom(); 37 38 private SharedPreferences mSharedPreferences; 39 AlarmStorage(Context context)40 public AlarmStorage(Context context) { 41 Context storageContext; 42 if (BuildCompat.isAtLeastN()) { 43 // All N devices have split storage areas, but we may need to 44 // move the existing preferences to the new device protected 45 // storage area, which is where the data lives from now on. 46 final Context deviceContext = context.createDeviceProtectedStorageContext(); 47 if (!deviceContext.moveSharedPreferencesFrom(context, 48 ALARM_PREFERENCES_NAME)) { 49 Log.w(TAG, "Failed to migrate shared preferences."); 50 } 51 storageContext = deviceContext; 52 } else { 53 storageContext = context; 54 } 55 mSharedPreferences = storageContext 56 .getSharedPreferences(ALARM_PREFERENCES_NAME, Context.MODE_PRIVATE); 57 } 58 59 /** 60 * Stores an alarm in the SharedPreferences. 61 * 62 * @param month the integer represents a month 63 * @param date the integer represents a date 64 * @param hour the integer as 24-hour format the alarm goes off 65 * @param minute the integer of the minute the alarm goes off 66 * @return the saved {@link Alarm} instance 67 */ saveAlarm(int month, int date, int hour, int minute)68 public Alarm saveAlarm(int month, int date, int hour, int minute) { 69 Alarm alarm = new Alarm(); 70 // Ignore the Id duplication if that happens 71 alarm.id = SECURE_RANDOM.nextInt(); 72 alarm.month = month; 73 alarm.date = date; 74 alarm.hour = hour; 75 alarm.minute = minute; 76 SharedPreferences.Editor editor = mSharedPreferences.edit(); 77 editor.putString(String.valueOf(alarm.id), alarm.toJson()); 78 editor.apply(); 79 return alarm; 80 } 81 82 /** 83 * Retrieves the alarms stored in the SharedPreferences. 84 * This method takes linear time as the alarms count. 85 * 86 * @return a {@link Set} of alarms. 87 */ getAlarms()88 public Set<Alarm> getAlarms() { 89 Set<Alarm> alarms = new HashSet<>(); 90 for (Map.Entry<String, ?> entry : mSharedPreferences.getAll().entrySet()) { 91 alarms.add(Alarm.fromJson(entry.getValue().toString())); 92 } 93 return alarms; 94 } 95 96 /** 97 * Delete the alarm instance passed as an argument from the SharedPreferences. 98 * This method iterates through the alarms stored in the SharedPreferences, takes linear time 99 * as the alarms count. 100 * 101 * @param toBeDeleted the alarm instance to be deleted 102 */ deleteAlarm(Alarm toBeDeleted)103 public void deleteAlarm(Alarm toBeDeleted) { 104 for (Map.Entry<String, ?> entry : mSharedPreferences.getAll().entrySet()) { 105 Alarm alarm = Alarm.fromJson(entry.getValue().toString()); 106 if (alarm.id == toBeDeleted.id) { 107 SharedPreferences.Editor editor = mSharedPreferences.edit(); 108 editor.remove(String.valueOf(alarm.id)); 109 editor.apply(); 110 return; 111 } 112 } 113 } 114 } 115