1 /* 2 * Copyright (C) 2013 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.cellbroadcastreceiver; 18 19 import android.app.AlarmManager; 20 import android.app.PendingIntent; 21 import android.app.Service; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.SharedPreferences; 25 import android.media.Ringtone; 26 import android.media.RingtoneManager; 27 import android.net.Uri; 28 import android.os.IBinder; 29 import android.os.SystemClock; 30 import android.preference.PreferenceManager; 31 import android.telephony.CellBroadcastMessage; 32 import android.telephony.SubscriptionManager; 33 import android.util.Log; 34 import android.media.AudioManager; 35 import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG; 36 import com.android.internal.telephony.PhoneConstants; 37 38 /** 39 * Manages alert reminder notification. 40 */ 41 public class CellBroadcastAlertReminder extends Service { 42 private static final String TAG = "CellBroadcastAlertReminder"; 43 44 /** Action to wake up and play alert reminder sound. */ 45 static final String ACTION_PLAY_ALERT_REMINDER = "ACTION_PLAY_ALERT_REMINDER"; 46 47 /** 48 * Pending intent for alert reminder. This is static so that we don't have to start the 49 * service in order to cancel any pending reminders when user dismisses the alert dialog. 50 */ 51 private static PendingIntent sPlayReminderIntent; 52 53 /** 54 * Alert reminder for current ringtone being played. 55 */ 56 private static Ringtone sPlayReminderRingtone; 57 58 @Override 59 public IBinder onBind(Intent intent) { 60 return null; 61 } 62 63 @Override 64 public int onStartCommand(Intent intent, int flags, int startId) { 65 // No intent or unrecognized action; tell the system not to restart us. 66 if (intent == null || !ACTION_PLAY_ALERT_REMINDER.equals(intent.getAction())) { 67 stopSelf(); 68 return START_NOT_STICKY; 69 } 70 71 int subId = intent.getExtras().getInt(PhoneConstants.SUBSCRIPTION_KEY); 72 if(DBG) Log.d(TAG, "subscription id = " + subId); 73 74 log("playing alert reminder"); 75 playAlertReminderSound(); 76 77 if (queueAlertReminder(this, false, subId)) { 78 return START_STICKY; 79 } else { 80 log("no reminders queued"); 81 stopSelf(); 82 return START_NOT_STICKY; 83 } 84 } 85 86 /** 87 * Use the RingtoneManager to play the alert reminder sound. 88 */ 89 private void playAlertReminderSound() { 90 Uri notificationUri = RingtoneManager.getDefaultUri( 91 RingtoneManager.TYPE_NOTIFICATION); 92 if (notificationUri == null) { 93 loge("Can't get URI for alert reminder sound"); 94 return; 95 } 96 Ringtone r = RingtoneManager.getRingtone(this, notificationUri); 97 r.setStreamType(AudioManager.STREAM_NOTIFICATION); 98 99 if (r != null) { 100 log("playing alert reminder sound"); 101 r.play(); 102 } else { 103 loge("can't get Ringtone for alert reminder sound"); 104 } 105 } 106 107 /** 108 * Helper method to start the alert reminder service to queue the alert reminder. 109 * @return true if a pending reminder was set; false if there are no more reminders 110 */ 111 static boolean queueAlertReminder(Context context, boolean firstTime, int subId) { 112 // Stop any alert reminder sound and cancel any previously queued reminders. 113 cancelAlertReminder(); 114 115 int interval = SubscriptionManager.getIntegerSubscriptionProperty(subId, 116 SubscriptionManager.CB_ALERT_REMINDER_INTERVAL, Integer.parseInt( 117 CellBroadcastSettings.ALERT_REMINDER_INTERVAL), context); 118 119 if (interval == 0 || (interval == 1 && !firstTime)) { 120 return false; 121 } 122 if (interval == 1) { 123 interval = 2; // "1" = one reminder after 2 minutes 124 } 125 126 if (DBG) log("queueAlertReminder() in " + interval + " minutes"); 127 128 Intent playIntent = new Intent(context, CellBroadcastAlertReminder.class); 129 playIntent.setAction(ACTION_PLAY_ALERT_REMINDER); 130 playIntent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); 131 sPlayReminderIntent = PendingIntent.getService(context, 0, playIntent, 132 PendingIntent.FLAG_UPDATE_CURRENT); 133 134 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 135 if (alarmManager == null) { 136 loge("can't get Alarm Service"); 137 return false; 138 } 139 140 // remind user after 2 minutes or 15 minutes 141 long triggerTime = SystemClock.elapsedRealtime() + (interval * 60000); 142 alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, sPlayReminderIntent); 143 return true; 144 } 145 146 /** 147 * Stops alert reminder and cancels any queued reminders. 148 */ 149 static void cancelAlertReminder() { 150 if (DBG) log("cancelAlertReminder()"); 151 if (sPlayReminderRingtone != null) { 152 if (DBG) log("stopping play reminder ringtone"); 153 sPlayReminderRingtone.stop(); 154 sPlayReminderRingtone = null; 155 } 156 if (sPlayReminderIntent != null) { 157 if (DBG) log("canceling pending play reminder intent"); 158 sPlayReminderIntent.cancel(); 159 sPlayReminderIntent = null; 160 } 161 } 162 163 private static void log(String msg) { 164 Log.d(TAG, msg); 165 } 166 167 private static void loge(String msg) { 168 Log.e(TAG, msg); 169 } 170 } 171