| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.deskclock; |
| |
| import static android.text.format.DateUtils.SECOND_IN_MILLIS; |
| import static com.android.deskclock.AlarmSelectionActivity.ACTION_DISMISS; |
| import static com.android.deskclock.AlarmSelectionActivity.EXTRA_ACTION; |
| import static com.android.deskclock.AlarmSelectionActivity.EXTRA_ALARMS; |
| import static com.android.deskclock.provider.AlarmInstance.FIRED_STATE; |
| import static com.android.deskclock.provider.AlarmInstance.SNOOZE_STATE; |
| import static com.android.deskclock.uidata.UiDataModel.Tab.ALARMS; |
| import static com.android.deskclock.uidata.UiDataModel.Tab.TIMERS; |
| |
| import android.app.Activity; |
| import android.content.ContentResolver; |
| import android.content.ContentUris; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.Parcelable; |
| import android.provider.AlarmClock; |
| import android.text.TextUtils; |
| import android.text.format.DateFormat; |
| |
| import com.android.deskclock.alarms.AlarmStateManager; |
| import com.android.deskclock.controller.Controller; |
| import com.android.deskclock.data.DataModel; |
| import com.android.deskclock.data.Timer; |
| import com.android.deskclock.data.Weekdays; |
| import com.android.deskclock.events.Events; |
| import com.android.deskclock.provider.Alarm; |
| import com.android.deskclock.provider.AlarmInstance; |
| import com.android.deskclock.timer.TimerFragment; |
| import com.android.deskclock.timer.TimerService; |
| import com.android.deskclock.uidata.UiDataModel; |
| |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| |
| /** |
| * This activity is never visible. It processes all public intents defined by {@link AlarmClock} |
| * that apply to alarms and timers. Its definition in AndroidManifest.xml requires callers to hold |
| * the com.android.alarm.permission.SET_ALARM permission to complete the requested action. |
| */ |
| public class HandleApiCalls extends Activity { |
| |
| private static final LogUtils.Logger LOGGER = new LogUtils.Logger("HandleApiCalls"); |
| |
| private Context mAppContext; |
| |
| @Override |
| protected void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| |
| mAppContext = getApplicationContext(); |
| |
| try { |
| final Intent intent = getIntent(); |
| final String action = intent == null ? null : intent.getAction(); |
| if (action == null) { |
| return; |
| } |
| LOGGER.i("onCreate: " + intent); |
| |
| switch (action) { |
| |
| case AlarmClock.ACTION_SET_ALARM: |
| handleSetAlarm(intent); |
| break; |
| case AlarmClock.ACTION_SHOW_ALARMS: |
| handleShowAlarms(); |
| break; |
| case AlarmClock.ACTION_SET_TIMER: |
| handleSetTimer(intent); |
| break; |
| case AlarmClock.ACTION_SHOW_TIMERS: |
| handleShowTimers(); |
| break; |
| case AlarmClock.ACTION_DISMISS_ALARM: |
| handleDismissAlarm(intent); |
| break; |
| case AlarmClock.ACTION_SNOOZE_ALARM: |
| handleSnoozeAlarm(); |
| break; |
| case AlarmClock.ACTION_DISMISS_TIMER: |
| handleDismissTimer(intent); |
| break; |
| } |
| } catch (Exception e) { |
| LOGGER.wtf(e); |
| } finally { |
| finish(); |
| } |
| } |
| |
| |
| private void handleDismissAlarm(Intent intent) { |
| // Change to the alarms tab. |
| UiDataModel.getUiDataModel().setSelectedTab(ALARMS); |
| |
| // Open DeskClock which is now positioned on the alarms tab. |
| startActivity(new Intent(mAppContext, DeskClock.class)); |
| |
| new DismissAlarmAsync(mAppContext, intent, this).execute(); |
| } |
| |
| public static void dismissAlarm(Alarm alarm, Activity activity) { |
| final Context context = activity.getApplicationContext(); |
| final AlarmInstance instance = AlarmInstance.getNextUpcomingInstanceByAlarmId( |
| context.getContentResolver(), alarm.id); |
| if (instance == null) { |
| final String reason = context.getString(R.string.no_alarm_scheduled_for_this_time); |
| Controller.getController().notifyVoiceFailure(activity, reason); |
| LOGGER.i("No alarm instance to dismiss"); |
| return; |
| } |
| |
| dismissAlarmInstance(instance, activity); |
| } |
| |
| public static void dismissAlarmInstance(AlarmInstance instance, Activity activity) { |
| Utils.enforceNotMainLooper(); |
| |
| final Context context = activity.getApplicationContext(); |
| final Date alarmTime = instance.getAlarmTime().getTime(); |
| final String time = DateFormat.getTimeFormat(context).format(alarmTime); |
| |
| if (instance.mAlarmState == FIRED_STATE || instance.mAlarmState == SNOOZE_STATE) { |
| // Always dismiss alarms that are fired or snoozed. |
| AlarmStateManager.deleteInstanceAndUpdateParent(context, instance); |
| } else if (Utils.isAlarmWithin24Hours(instance)) { |
| // Upcoming alarms are always predismissed. |
| AlarmStateManager.setPreDismissState(context, instance); |
| } else { |
| // Otherwise the alarm cannot be dismissed at this time. |
| final String reason = context.getString( |
| R.string.alarm_cant_be_dismissed_still_more_than_24_hours_away, time); |
| Controller.getController().notifyVoiceFailure(activity, reason); |
| LOGGER.i("Can't dismiss alarm more than 24 hours in advance"); |
| } |
| |
| // Log the successful dismissal. |
| final String reason = context.getString(R.string.alarm_is_dismissed, time); |
| Controller.getController().notifyVoiceSuccess(activity, reason); |
| LOGGER.i("Alarm dismissed: " + instance); |
| Events.sendAlarmEvent(R.string.action_dismiss, R.string.label_intent); |
| } |
| |
| private static class DismissAlarmAsync { |
| |
| private final Context mContext; |
| private final Intent mIntent; |
| private final Activity mActivity; |
| |
| public DismissAlarmAsync(Context context, Intent intent, Activity activity) { |
| mContext = context; |
| mIntent = intent; |
| mActivity = activity; |
| } |
| |
| protected void execute() { |
| ExecutorService executor = Executors.newSingleThreadExecutor(); |
| executor.execute(() -> { |
| final ContentResolver cr = mContext.getContentResolver(); |
| final List<Alarm> alarms = getEnabledAlarms(mContext); |
| if (alarms.isEmpty()) { |
| final String reason = mContext.getString(R.string.no_scheduled_alarms); |
| Controller.getController().notifyVoiceFailure(mActivity, reason); |
| LOGGER.i("No scheduled alarms"); |
| return; |
| } |
| |
| // remove Alarms in MISSED, DISMISSED, and PREDISMISSED states |
| for (Iterator<Alarm> i = alarms.iterator(); i.hasNext();) { |
| final AlarmInstance instance = AlarmInstance.getNextUpcomingInstanceByAlarmId( |
| cr, i.next().id); |
| if (instance == null || instance.mAlarmState > FIRED_STATE) { |
| i.remove(); |
| } |
| } |
| |
| final String searchMode = mIntent.getStringExtra( |
| AlarmClock.EXTRA_ALARM_SEARCH_MODE); |
| if (searchMode == null && alarms.size() > 1) { |
| // shows the UI where user picks which alarm they want to DISMISS |
| final Intent pickSelectionIntent = new Intent(mContext, |
| AlarmSelectionActivity.class) |
| .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
| .putExtra(EXTRA_ACTION, ACTION_DISMISS) |
| .putExtra(EXTRA_ALARMS, alarms.toArray(new Parcelable[0])); |
| mContext.startActivity(pickSelectionIntent); |
| final String voiceMessage = mContext.getString(R.string.pick_alarm_to_dismiss); |
| Controller.getController().notifyVoiceSuccess(mActivity, voiceMessage); |
| return; |
| } |
| |
| // fetch the alarms that are specified by the intent |
| final FetchMatchingAlarmsAction fmaa = |
| new FetchMatchingAlarmsAction(mContext, alarms, mIntent, mActivity); |
| fmaa.run(); |
| final List<Alarm> matchingAlarms = fmaa.getMatchingAlarms(); |
| |
| // If there are multiple matching alarms and it wasn't expected |
| // disambiguate what the user meant |
| if (!AlarmClock.ALARM_SEARCH_MODE_ALL.equals(searchMode) && |
| matchingAlarms.size() > 1) { |
| final Intent pickSelectionIntent = new Intent(mContext, |
| AlarmSelectionActivity.class) |
| .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
| .putExtra(EXTRA_ACTION, ACTION_DISMISS) |
| .putExtra(EXTRA_ALARMS, matchingAlarms.toArray(new Parcelable[0])); |
| mContext.startActivity(pickSelectionIntent); |
| final String voiceMessage = mContext.getString(R.string.pick_alarm_to_dismiss); |
| Controller.getController().notifyVoiceSuccess(mActivity, voiceMessage); |
| return; |
| } |
| |
| // Apply the action to the matching alarms |
| for (Alarm alarm : matchingAlarms) { |
| dismissAlarm(alarm, mActivity); |
| LOGGER.i("Alarm dismissed: " + alarm); |
| } |
| }); |
| } |
| |
| private static List<Alarm> getEnabledAlarms(Context context) { |
| final String selection = String.format("%s=?", Alarm.ENABLED); |
| final String[] args = { "1" }; |
| return Alarm.getAlarms(context.getContentResolver(), selection, args); |
| } |
| } |
| |
| private void handleSnoozeAlarm() { |
| ExecutorService executor = Executors.newSingleThreadExecutor(); |
| executor.execute(() -> { |
| final Context context = getApplicationContext(); |
| final ContentResolver cr = context.getContentResolver(); |
| final List<AlarmInstance> alarmInstances = AlarmInstance.getInstancesByState( |
| cr, FIRED_STATE); |
| if (alarmInstances.isEmpty()) { |
| final String reason = context.getString(R.string.no_firing_alarms); |
| Controller.getController().notifyVoiceFailure(this, reason); |
| LOGGER.i("No firing alarms"); |
| return; |
| } |
| |
| for (AlarmInstance firingAlarmInstance : alarmInstances) { |
| snoozeAlarm(firingAlarmInstance, context, this); |
| } |
| }); |
| } |
| |
| static void snoozeAlarm(AlarmInstance alarmInstance, Context context, Activity activity) { |
| Utils.enforceNotMainLooper(); |
| |
| final String time = DateFormat.getTimeFormat(context).format( |
| alarmInstance.getAlarmTime().getTime()); |
| final String reason = context.getString(R.string.alarm_is_snoozed, time); |
| AlarmStateManager.setSnoozeState(context, alarmInstance, true); |
| |
| Controller.getController().notifyVoiceSuccess(activity, reason); |
| LOGGER.i("Alarm snoozed: " + alarmInstance); |
| Events.sendAlarmEvent(R.string.action_snooze, R.string.label_intent); |
| } |
| |
| /*** |
| * Processes the SET_ALARM intent |
| * @param intent Intent passed to the app |
| */ |
| private void handleSetAlarm(Intent intent) { |
| // Validate the hour, if one was given. |
| int hour = -1; |
| if (intent.hasExtra(AlarmClock.EXTRA_HOUR)) { |
| hour = intent.getIntExtra(AlarmClock.EXTRA_HOUR, hour); |
| if (hour < 0 || hour > 23) { |
| final int mins = intent.getIntExtra(AlarmClock.EXTRA_MINUTES, 0); |
| final String voiceMessage = getString(R.string.invalid_time, hour, mins, " "); |
| Controller.getController().notifyVoiceFailure(this, voiceMessage); |
| LOGGER.i("Illegal hour: " + hour); |
| return; |
| } |
| } |
| |
| // Validate the minute, if one was given. |
| final int minutes = intent.getIntExtra(AlarmClock.EXTRA_MINUTES, 0); |
| if (minutes < 0 || minutes > 59) { |
| final String voiceMessage = getString(R.string.invalid_time, hour, minutes, " "); |
| Controller.getController().notifyVoiceFailure(this, voiceMessage); |
| LOGGER.i("Illegal minute: " + minutes); |
| return; |
| } |
| |
| final boolean skipUi = intent.getBooleanExtra(AlarmClock.EXTRA_SKIP_UI, false); |
| final ContentResolver cr = getContentResolver(); |
| |
| // If time information was not provided an existing alarm cannot be located and a new one |
| // cannot be created so show the UI for creating the alarm from scratch per spec. |
| if (hour == -1) { |
| // Change to the alarms tab. |
| UiDataModel.getUiDataModel().setSelectedTab(ALARMS); |
| |
| // Intent has no time or an invalid time, open the alarm creation UI. |
| final Intent createAlarm = Alarm.createIntent(this, DeskClock.class, Alarm.INVALID_ID) |
| .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
| .putExtra(AlarmClockFragment.ALARM_CREATE_NEW_INTENT_EXTRA, true); |
| |
| // Open DeskClock which is now positioned on the alarms tab. |
| startActivity(createAlarm); |
| final String voiceMessage = getString(R.string.invalid_time, hour, minutes, " "); |
| Controller.getController().notifyVoiceFailure(this, voiceMessage); |
| LOGGER.i("Missing alarm time; opening UI"); |
| return; |
| } |
| |
| final StringBuilder selection = new StringBuilder(); |
| final List<String> argsList = new ArrayList<>(); |
| setSelectionFromIntent(intent, hour, minutes, selection, argsList); |
| |
| // Try to locate an existing alarm using the intent data. |
| final String[] args = argsList.toArray(new String[0]); |
| final List<Alarm> alarms = Alarm.getAlarms(cr, selection.toString(), args); |
| |
| final Alarm alarm; |
| if (!alarms.isEmpty()) { |
| // Enable the first matching alarm. |
| alarm = alarms.get(0); |
| alarm.enabled = true; |
| Alarm.updateAlarm(cr, alarm); |
| |
| // Delete all old instances. |
| AlarmStateManager.deleteAllInstances(this, alarm.id); |
| |
| Events.sendAlarmEvent(R.string.action_update, R.string.label_intent); |
| LOGGER.i("Updated alarm: " + alarm); |
| } else { |
| // No existing alarm could be located; create one using the intent data. |
| alarm = new Alarm(); |
| updateAlarmFromIntent(alarm, intent); |
| alarm.deleteAfterUse = !alarm.daysOfWeek.isRepeating() && skipUi; |
| |
| // Save the new alarm. |
| Alarm.addAlarm(cr, alarm); |
| |
| Events.sendAlarmEvent(R.string.action_create, R.string.label_intent); |
| LOGGER.i("Created new alarm: " + alarm); |
| } |
| |
| // Schedule the next instance. |
| final Calendar now = DataModel.getDataModel().getCalendar(); |
| final AlarmInstance alarmInstance = alarm.createInstanceAfter(now); |
| setupInstance(alarmInstance, skipUi); |
| |
| final String time = DateFormat.getTimeFormat(this) |
| .format(alarmInstance.getAlarmTime().getTime()); |
| Controller.getController().notifyVoiceSuccess(this, getString(R.string.alarm_is_set, time)); |
| } |
| |
| private void handleDismissTimer(Intent intent) { |
| final Uri dataUri = intent.getData(); |
| if (dataUri != null) { |
| final Timer selectedTimer = getSelectedTimer(dataUri); |
| if (selectedTimer != null) { |
| DataModel.getDataModel().resetOrDeleteTimer(selectedTimer, R.string.label_intent); |
| Controller.getController().notifyVoiceSuccess(this, |
| getResources().getQuantityString(R.plurals.expired_timers_dismissed, 1)); |
| LOGGER.i("Timer dismissed: " + selectedTimer); |
| } else { |
| Controller.getController().notifyVoiceFailure(this, |
| getString(R.string.invalid_timer)); |
| LOGGER.e("Could not dismiss timer: invalid URI"); |
| } |
| } else { |
| final List<Timer> expiredTimers = DataModel.getDataModel().getExpiredTimers(); |
| if (!expiredTimers.isEmpty()) { |
| for (Timer timer : expiredTimers) { |
| DataModel.getDataModel().resetOrDeleteTimer(timer, R.string.label_intent); |
| } |
| final int numberOfTimers = expiredTimers.size(); |
| final String timersDismissedMessage = getResources().getQuantityString( |
| R.plurals.expired_timers_dismissed, numberOfTimers, numberOfTimers); |
| Controller.getController().notifyVoiceSuccess(this, timersDismissedMessage); |
| LOGGER.i(timersDismissedMessage); |
| } else { |
| Controller.getController().notifyVoiceFailure(this, |
| getString(R.string.no_expired_timers)); |
| LOGGER.e("Could not dismiss timer: no expired timers"); |
| } |
| } |
| } |
| |
| private Timer getSelectedTimer(Uri dataUri) { |
| try { |
| final int timerId = (int) ContentUris.parseId(dataUri); |
| return DataModel.getDataModel().getTimer(timerId); |
| } catch (NumberFormatException e) { |
| return null; |
| } |
| } |
| |
| private void handleShowAlarms() { |
| Events.sendAlarmEvent(R.string.action_show, R.string.label_intent); |
| |
| // Open DeskClock positioned on the alarms tab. |
| UiDataModel.getUiDataModel().setSelectedTab(ALARMS); |
| startActivity(new Intent(this, DeskClock.class)); |
| } |
| |
| private void handleShowTimers() { |
| Events.sendTimerEvent(R.string.action_show, R.string.label_intent); |
| |
| final Intent showTimersIntent = new Intent(this, DeskClock.class); |
| |
| final List<Timer> timers = DataModel.getDataModel().getTimers(); |
| if (!timers.isEmpty()) { |
| final Timer newestTimer = timers.get(timers.size() - 1); |
| showTimersIntent.putExtra(TimerService.EXTRA_TIMER_ID, newestTimer.getId()); |
| } |
| |
| // Open DeskClock positioned on the timers tab. |
| UiDataModel.getUiDataModel().setSelectedTab(TIMERS); |
| startActivity(showTimersIntent); |
| } |
| |
| private void handleSetTimer(Intent intent) { |
| // If no length is supplied, show the timer setup view. |
| if (!intent.hasExtra(AlarmClock.EXTRA_LENGTH)) { |
| // Change to the timers tab. |
| UiDataModel.getUiDataModel().setSelectedTab(TIMERS); |
| |
| // Open DeskClock which is now positioned on the timers tab and show the timer setup. |
| startActivity(TimerFragment.createTimerSetupIntent(this)); |
| LOGGER.i("Showing timer setup"); |
| return; |
| } |
| |
| // Verify that the timer length is between one second and one day. |
| final long lengthMillis = SECOND_IN_MILLIS * intent.getIntExtra(AlarmClock.EXTRA_LENGTH, 0); |
| if (lengthMillis < Timer.MIN_LENGTH) { |
| final String voiceMessage = getString(R.string.invalid_timer_length); |
| Controller.getController().notifyVoiceFailure(this, voiceMessage); |
| LOGGER.i("Invalid timer length requested: " + lengthMillis); |
| return; |
| } |
| |
| final String label = getLabelFromIntent(intent, ""); |
| final boolean skipUi = intent.getBooleanExtra(AlarmClock.EXTRA_SKIP_UI, false); |
| |
| // Attempt to reuse an existing timer that is Reset with the same length and label. |
| Timer timer = null; |
| for (Timer t : DataModel.getDataModel().getTimers()) { |
| if (!t.isReset()) { continue; } |
| if (t.getLength() != lengthMillis) { continue; } |
| if (!TextUtils.equals(label, t.getLabel())) { continue; } |
| |
| timer = t; |
| break; |
| } |
| |
| // Create a new timer if one could not be reused. |
| if (timer == null) { |
| timer = DataModel.getDataModel().addTimer(lengthMillis, label, skipUi); |
| Events.sendTimerEvent(R.string.action_create, R.string.label_intent); |
| } |
| |
| // Start the selected timer. |
| DataModel.getDataModel().startTimer(timer); |
| Events.sendTimerEvent(R.string.action_start, R.string.label_intent); |
| Controller.getController().notifyVoiceSuccess(this, getString(R.string.timer_created)); |
| |
| // If not instructed to skip the UI, display the running timer. |
| if (!skipUi) { |
| // Change to the timers tab. |
| UiDataModel.getUiDataModel().setSelectedTab(TIMERS); |
| |
| // Open DeskClock which is now positioned on the timers tab. |
| startActivity(new Intent(this, DeskClock.class) |
| .putExtra(TimerService.EXTRA_TIMER_ID, timer.getId())); |
| } |
| } |
| |
| private void setupInstance(AlarmInstance instance, boolean skipUi) { |
| instance = AlarmInstance.addInstance(this.getContentResolver(), instance); |
| AlarmStateManager.registerInstance(this, instance, true); |
| AlarmUtils.popAlarmSetToast(this, instance.getAlarmTime().getTimeInMillis()); |
| if (!skipUi) { |
| // Change to the alarms tab. |
| UiDataModel.getUiDataModel().setSelectedTab(ALARMS); |
| |
| // Open DeskClock which is now positioned on the alarms tab. |
| final Intent showAlarm = Alarm.createIntent(this, DeskClock.class, instance.mAlarmId) |
| .putExtra(AlarmClockFragment.SCROLL_TO_ALARM_INTENT_EXTRA, instance.mAlarmId) |
| .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| startActivity(showAlarm); |
| } |
| } |
| |
| /** |
| * @param alarm the alarm to be updated |
| * @param intent the intent containing new alarm field values to merge into the {@code alarm} |
| */ |
| private static void updateAlarmFromIntent(Alarm alarm, Intent intent) { |
| alarm.enabled = true; |
| alarm.hour = intent.getIntExtra(AlarmClock.EXTRA_HOUR, alarm.hour); |
| alarm.minutes = intent.getIntExtra(AlarmClock.EXTRA_MINUTES, alarm.minutes); |
| alarm.vibrate = intent.getBooleanExtra(AlarmClock.EXTRA_VIBRATE, alarm.vibrate); |
| alarm.alert = getAlertFromIntent(intent, alarm.alert); |
| alarm.label = getLabelFromIntent(intent, alarm.label); |
| alarm.daysOfWeek = getDaysFromIntent(intent, alarm.daysOfWeek); |
| } |
| |
| private static String getLabelFromIntent(Intent intent, String defaultLabel) { |
| final String message = intent.getExtras().getString(AlarmClock.EXTRA_MESSAGE, defaultLabel); |
| return message == null ? "" : message; |
| } |
| |
| private static Weekdays getDaysFromIntent(Intent intent, Weekdays defaultWeekdays) { |
| if (!intent.hasExtra(AlarmClock.EXTRA_DAYS)) { |
| return defaultWeekdays; |
| } |
| |
| final List<Integer> days = intent.getIntegerArrayListExtra(AlarmClock.EXTRA_DAYS); |
| if (days != null) { |
| final int[] daysArray = new int[days.size()]; |
| for (int i = 0; i < days.size(); i++) { |
| daysArray[i] = days.get(i); |
| } |
| return Weekdays.fromCalendarDays(daysArray); |
| } else { |
| // API says to use an ArrayList<Integer> but we allow the user to use a int[] too. |
| final int[] daysArray = intent.getIntArrayExtra(AlarmClock.EXTRA_DAYS); |
| if (daysArray != null) { |
| return Weekdays.fromCalendarDays(daysArray); |
| } |
| } |
| return defaultWeekdays; |
| } |
| |
| private static Uri getAlertFromIntent(Intent intent, Uri defaultUri) { |
| final String alert = intent.getStringExtra(AlarmClock.EXTRA_RINGTONE); |
| if (alert == null) { |
| return defaultUri; |
| } else if (AlarmClock.VALUE_RINGTONE_SILENT.equals(alert) || alert.isEmpty()) { |
| return Alarm.NO_RINGTONE_URI; |
| } |
| |
| return Uri.parse(alert); |
| } |
| |
| /** |
| * Assemble a database where clause to search for an alarm matching the given {@code hour} and |
| * {@code minutes} as well as all of the optional information within the {@code intent} |
| * including: |
| * |
| * <ul> |
| * <li>alarm message</li> |
| * <li>repeat days</li> |
| * <li>vibration setting</li> |
| * <li>ringtone uri</li> |
| * </ul> |
| * |
| * @param intent contains details of the alarm to be located |
| * @param hour the hour of the day of the alarm |
| * @param minutes the minute of the hour of the alarm |
| * @param selection an out parameter containing a SQL where clause |
| * @param args an out parameter containing the values to substitute into the {@code selection} |
| */ |
| private void setSelectionFromIntent( |
| Intent intent, |
| int hour, |
| int minutes, |
| StringBuilder selection, |
| List<String> args) { |
| selection.append(Alarm.HOUR).append("=?"); |
| args.add(String.valueOf(hour)); |
| selection.append(" AND ").append(Alarm.MINUTES).append("=?"); |
| args.add(String.valueOf(minutes)); |
| |
| if (intent.hasExtra(AlarmClock.EXTRA_MESSAGE)) { |
| selection.append(" AND ").append(Alarm.LABEL).append("=?"); |
| args.add(getLabelFromIntent(intent, "")); |
| } |
| |
| // Days is treated differently than other fields because if days is not specified, it |
| // explicitly means "not recurring". |
| selection.append(" AND ").append(Alarm.DAYS_OF_WEEK).append("=?"); |
| args.add(String.valueOf(getDaysFromIntent(intent, Weekdays.NONE).getBits())); |
| |
| if (intent.hasExtra(AlarmClock.EXTRA_VIBRATE)) { |
| selection.append(" AND ").append(Alarm.VIBRATE).append("=?"); |
| args.add(intent.getBooleanExtra(AlarmClock.EXTRA_VIBRATE, false) ? "1" : "0"); |
| } |
| |
| if (intent.hasExtra(AlarmClock.EXTRA_RINGTONE)) { |
| selection.append(" AND ").append(Alarm.RINGTONE).append("=?"); |
| |
| // If the intent explicitly specified a NULL ringtone, treat it as the default ringtone. |
| final Uri defaultRingtone = DataModel.getDataModel().getDefaultAlarmRingtoneUri(); |
| final Uri ringtone = getAlertFromIntent(intent, defaultRingtone); |
| args.add(ringtone.toString()); |
| } |
| } |
| } |