Move DISMISS_ALARM & rename HandleVoiceApiCalls

Renamed HandleVoiceApiCalls to HandleDeskClockApiCalls.
Removed the VOICE_ prefix from all the intents in that class.
Moved DISMISS_ALARM to HandleApiCalls instead of
HandleDeskClockApiCalls.

Change-Id: I17a1271e68a4b275ba8f4d471a61a7b02e6ceac0
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1c7dbe0..b59fabf 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -125,6 +125,10 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <intent-filter>
+                <action android:name="android.intent.action.DISMISS_ALARM" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
                 <action android:name="android.intent.action.SHOW_ALARMS" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
@@ -139,81 +143,63 @@
             android:exported="true">
         </activity-alias>
 
-        <activity android:name=".voice.HandleVoiceApiCalls"
+        <activity android:name=".HandleDeskClockApiCalls"
             android:excludeFromRecents="true"
             android:launchMode="singleTask"
             android:taskAffinity=""
             android:theme="@android:style/Theme.NoDisplay"
             android:permission="com.android.alarm.permission.SET_ALARM">
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_SHOW_CLOCK" />
+                <action android:name="com.android.deskclock.action.SHOW_CLOCK" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_ADD_CLOCK" />
+                <action android:name="com.android.deskclock.action.ADD_CLOCK" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_DELETE_CLOCK" />
+                <action android:name="com.android.deskclock.action.DELETE_CLOCK" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.DISMISS_ALARM" />
+                <action android:name="com.android.deskclock.action.START_TIMER" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_START_TIMER" />
+                <action android:name="com.android.deskclock.action.RESET_TIMER" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_RESET_TIMER" />
+                <action android:name="com.android.deskclock.action.STOP_TIMER" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_STOP_TIMER" />
+                <action android:name="com.android.deskclock.action.SHOW_TIMERS" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_SHOW_TIMERS" />
+                <action android:name="com.android.deskclock.action.DELETE_TIMER" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_DELETE_TIMER" />
+                <action android:name="com.android.deskclock.action.SHOW_STOPWATCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_SHOW_STOPWATCH" />
+                <action android:name="com.android.deskclock.action.START_STOPWATCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_START_STOPWATCH" />
+                <action android:name="com.android.deskclock.action.STOP_STOPWATCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_STOP_STOPWATCH" />
+                <action android:name="com.android.deskclock.action.LAP_STOPWATCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
             <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_LAP_STOPWATCH" />
+                <action android:name="com.android.deskclock.action.RESET_STOPWATCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="com.android.deskclock.action.VOICE_RESET_STOPWATCH" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
             </intent-filter>
         </activity>
 
diff --git a/src/com/android/deskclock/voice/FetchMatchingAlarmsAction.java b/src/com/android/deskclock/FetchMatchingAlarmsAction.java
similarity index 97%
rename from src/com/android/deskclock/voice/FetchMatchingAlarmsAction.java
rename to src/com/android/deskclock/FetchMatchingAlarmsAction.java
index 721c1b5..3ae93f6 100644
--- a/src/com/android/deskclock/voice/FetchMatchingAlarmsAction.java
+++ b/src/com/android/deskclock/FetchMatchingAlarmsAction.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.deskclock.voice;
+package com.android.deskclock;
 
 import android.content.ContentResolver;
 import android.content.Context;
@@ -22,7 +22,6 @@
 import android.os.Looper;
 import android.provider.AlarmClock;
 
-import com.android.deskclock.LogUtils;
 import com.android.deskclock.alarms.AlarmStateManager;
 import com.android.deskclock.provider.Alarm;
 import com.android.deskclock.provider.AlarmInstance;
@@ -33,7 +32,7 @@
 
 /**
  * Returns a list of alarms that are specified by the intent
- * processed by HandleVoiceApiCalls
+ * processed by HandleDeskClockApiCalls
  * if there are more than 1 matching alarms and the SEARCH_MODE is not ALL
  * we show a picker UI dialog
  */
diff --git a/src/com/android/deskclock/HandleApiCalls.java b/src/com/android/deskclock/HandleApiCalls.java
index fe62519..20731d9 100644
--- a/src/com/android/deskclock/HandleApiCalls.java
+++ b/src/com/android/deskclock/HandleApiCalls.java
@@ -18,11 +18,14 @@
 
 import android.app.Activity;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.media.RingtoneManager;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Looper;
 import android.preference.PreferenceManager;
 import android.provider.AlarmClock;
 import android.text.TextUtils;
@@ -45,24 +48,140 @@
     public static final long TIMER_MIN_LENGTH = 1000;
     public static final long TIMER_MAX_LENGTH = 24 * 60 * 60 * 1000;
 
+    private Context mAppContext;
+
     @Override
     protected void onCreate(Bundle icicle) {
         try {
             super.onCreate(icicle);
+            mAppContext = getApplicationContext();
             final Intent intent = getIntent();
             final String action = intent == null ? null : intent.getAction();
-            if (AlarmClock.ACTION_SET_ALARM.equals(action)) {
-                handleSetAlarm(intent);
-            } else if (AlarmClock.ACTION_SHOW_ALARMS.equals(action)) {
-                handleShowAlarms();
-            } else if (AlarmClock.ACTION_SET_TIMER.equals(action)) {
-                handleSetTimer(intent);
+            if (action == null) {
+                return;
+            }
+            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_DISMISS_ALARM:
+                    handleDismissAlarm(intent.getAction());
+                    break;
             }
         } finally {
             finish();
         }
     }
 
+    private void handleDismissAlarm(final String action) {
+        // Opens the UI for Alarms
+        final Intent alarmIntent =
+                Alarm.createIntent(mAppContext, DeskClock.class, Alarm.INVALID_ID)
+                        .setAction(action)
+                        .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX);
+        startActivity(alarmIntent);
+
+        final Intent intent = getIntent();
+
+        new DismissAlarmAsync(mAppContext, intent).execute();
+    }
+
+    static void dismissAlarm(Alarm alarm, Context context) {
+        // only allow on background thread
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            throw new IllegalStateException("dismissAlarm must be called on a " +
+                    "background thread");
+        }
+
+        final AlarmInstance alarmInstance = AlarmInstance.getNextUpcomingInstanceByAlarmId(
+                context.getContentResolver(), alarm.id);
+        if (alarmInstance == null) {
+            LogUtils.i("There are no alarm instances for this alarm id");
+            return;
+        }
+
+        if (Utils.isAlarmWithinTwoHours(alarmInstance)) {
+            AlarmStateManager.setPreDismissState(context, alarmInstance);
+            LogUtils.i("Dismiss %d:%d",alarm.hour, alarm.minutes);
+            Events.sendAlarmEvent(R.string.action_dismiss,
+                    R.string.label_voice);
+        } else {
+            LogUtils.i("%s wasn't dismissed, still more than two hours away.", alarm);
+        }
+    }
+
+    private static class DismissAlarmAsync extends AsyncTask<Void, Void, Void> {
+
+        private final Context mContext;
+        private final Intent mIntent;
+
+        public DismissAlarmAsync(Context context, Intent intent) {
+            mContext = context;
+            mIntent = intent;
+        }
+
+        @Override
+        protected Void doInBackground(Void... parameters) {
+            final List<Alarm> alarms = getEnabledAlarms();
+            if (alarms.isEmpty()) {
+                LogUtils.i("No alarms are scheduled.");
+                return null;
+            }
+
+            final String searchMode = mIntent.getStringExtra(AlarmClock.EXTRA_ALARM_SEARCH_MODE);
+            if (searchMode == null && alarms.size() > 1) {
+                // TODO: add picker UI
+                // shows the UI where user picks which alarm they want to DISMISS
+//                final Intent pickSelectionIntent = new Intent(mContext, PickSelectionActivity.class)
+//                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+//                        .setAction(mIntent.getAction())
+//                        .putExtra(PickSelectionActivity.EXTRA_ALARMS,
+//                                alarms.toArray(new Parcelable[alarms.size()]));
+//                mContext.startActivity(pickSelectionIntent);
+                return null;
+            }
+
+            // fetch the alarms that are specified by the intent
+            final FetchMatchingAlarmsAction fmaa =
+                    new FetchMatchingAlarmsAction(mContext, alarms, mIntent);
+            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) {
+                // TODO: add picker UI
+//              final Intent pickSelectionIntent = new Intent(mContext, PickSelectionActivity.class)
+//                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+//                        .setAction(mIntent.getAction())
+//                        .putExtra(PickSelectionActivity.EXTRA_ALARMS,
+//                                matchingAlarms.toArray(new Parcelable[matchingAlarms.size()]));
+//                mContext.startActivity(pickSelectionIntent);
+                return null;
+            }
+
+            // Apply the action to the matching alarms
+            for (Alarm alarm : matchingAlarms) {
+                dismissAlarm(alarm, mContext);
+                LogUtils.i("Alarm %s is dismissed", alarm);
+            }
+            return null;
+        }
+
+        private List<Alarm> getEnabledAlarms() {
+            // since we want to dismiss we should only add enabled alarms
+            final String selection = String.format("%s=?", Alarm.ENABLED);
+            final String[] args = { "1" };
+            return Alarm.getAlarms(mContext.getContentResolver(), selection, args);
+        }
+    }
+
     /***
      * Processes the SET_ALARM intent
      * @param intent Intent passed to the app
diff --git a/src/com/android/deskclock/voice/HandleVoiceApiCalls.java b/src/com/android/deskclock/HandleDeskClockApiCalls.java
similarity index 60%
rename from src/com/android/deskclock/voice/HandleVoiceApiCalls.java
rename to src/com/android/deskclock/HandleDeskClockApiCalls.java
index a3dd2e0..fa0944c 100644
--- a/src/com/android/deskclock/voice/HandleVoiceApiCalls.java
+++ b/src/com/android/deskclock/HandleDeskClockApiCalls.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.deskclock.voice;
+package com.android.deskclock;
 
 import android.app.Activity;
 import android.content.Context;
@@ -22,19 +22,9 @@
 import android.content.SharedPreferences;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Looper;
 import android.preference.PreferenceManager;
-import android.provider.AlarmClock;
-import android.text.format.DateUtils;
 
-import com.android.deskclock.DeskClock;
-import com.android.deskclock.LogUtils;
-import com.android.deskclock.R;
-import com.android.deskclock.Utils;
-import com.android.deskclock.alarms.AlarmStateManager;
 import com.android.deskclock.events.Events;
-import com.android.deskclock.provider.Alarm;
-import com.android.deskclock.provider.AlarmInstance;
 import com.android.deskclock.stopwatch.StopwatchService;
 import com.android.deskclock.stopwatch.Stopwatches;
 import com.android.deskclock.timer.TimerFullScreenFragment;
@@ -45,49 +35,46 @@
 import com.android.deskclock.worldclock.CityObj;
 
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class HandleVoiceApiCalls extends Activity {
+public class HandleDeskClockApiCalls extends Activity {
     private Context mAppContext;
 
     private static final String ACTION_PREFIX = "com.android.deskclock.action.";
 
     // shows the tab with world clocks
-    public static final String VOICE_ACTION_SHOW_CLOCK = ACTION_PREFIX + "VOICE_SHOW_CLOCK";
+    public static final String ACTION_SHOW_CLOCK = ACTION_PREFIX + "SHOW_CLOCK";
     // add a clock of a selected city, if no city is specified opens the city selection screen
-    public static final String VOICE_ACTION_ADD_CLOCK = ACTION_PREFIX + "VOICE_ADD_CLOCK";
+    public static final String ACTION_ADD_CLOCK = ACTION_PREFIX + "ADD_CLOCK";
     // delete a clock of a selected city, if no city is specified shows CitiesActivity for the user
     // to choose a city
-    public static final String VOICE_ACTION_DELETE_CLOCK = ACTION_PREFIX + "VOICE_DELETE_CLOCK";
-    // extra for VOICE_ACTION_ADD_CLOCK and VOICE_ACTION_DELETE_CLOCK
+    public static final String ACTION_DELETE_CLOCK = ACTION_PREFIX + "DELETE_CLOCK";
+    // extra for ACTION_ADD_CLOCK and ACTION_DELETE_CLOCK
     public static final String EXTRA_CITY = "com.android.deskclock.extra.clock.CITY";
 
     // shows the tab with the stopwatch
-    public static final String VOICE_ACTION_SHOW_STOPWATCH = ACTION_PREFIX + "VOICE_SHOW_STOPWATCH";
+    public static final String ACTION_SHOW_STOPWATCH = ACTION_PREFIX + "SHOW_STOPWATCH";
     // starts the current stopwatch
-    public static final String VOICE_ACTION_START_STOPWATCH = ACTION_PREFIX
-            + "VOICE_START_STOPWATCH";
+    public static final String ACTION_START_STOPWATCH = ACTION_PREFIX + "START_STOPWATCH";
     // stops the current stopwatch
-    public static final String VOICE_ACTION_STOP_STOPWATCH = ACTION_PREFIX + "VOICE_STOP_STOPWATCH";
+    public static final String ACTION_STOP_STOPWATCH = ACTION_PREFIX + "STOP_STOPWATCH";
     // laps the stopwatch that's currently running
-    public static final String VOICE_ACTION_LAP_STOPWATCH = ACTION_PREFIX + "VOICE_LAP_STOPWATCH";
+    public static final String ACTION_LAP_STOPWATCH = ACTION_PREFIX + "LAP_STOPWATCH";
     // resets the stopwatch if it's stopped
-    public static final String VOICE_ACTION_RESET_STOPWATCH = ACTION_PREFIX
-            + "VOICE_RESET_STOPWATCH";
+    public static final String ACTION_RESET_STOPWATCH = ACTION_PREFIX + "RESET_STOPWATCH";
 
     // shows the tab with timers
-    public static final String VOICE_ACTION_SHOW_TIMERS = ACTION_PREFIX + "VOICE_SHOW_TIMERS";
+    public static final String ACTION_SHOW_TIMERS = ACTION_PREFIX + "SHOW_TIMERS";
     // deletes the topmost timer
-    public static final String VOICE_ACTION_DELETE_TIMER = ACTION_PREFIX + "VOICE_DELETE_TIMER";
+    public static final String ACTION_DELETE_TIMER = ACTION_PREFIX + "DELETE_TIMER";
     // stops the running timer
-    public static final String VOICE_ACTION_STOP_TIMER = ACTION_PREFIX + "VOICE_STOP_TIMER";
+    public static final String ACTION_STOP_TIMER = ACTION_PREFIX + "STOP_TIMER";
     // starts the topmost timer
-    public static final String VOICE_ACTION_START_TIMER = ACTION_PREFIX + "VOICE_START_TIMER";
+    public static final String ACTION_START_TIMER = ACTION_PREFIX + "START_TIMER";
     // resets the timer, works for both running and stopped
-    public static final String VOICE_ACTION_RESET_TIMER = ACTION_PREFIX + "VOICE_RESET_TIMER";
+    public static final String ACTION_RESET_TIMER = ACTION_PREFIX + "RESET_TIMER";
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -102,26 +89,23 @@
 
             final String action = intent.getAction();
             switch (action) {
-                case VOICE_ACTION_START_STOPWATCH:
-                case VOICE_ACTION_STOP_STOPWATCH:
-                case VOICE_ACTION_LAP_STOPWATCH:
-                case VOICE_ACTION_SHOW_STOPWATCH:
-                case VOICE_ACTION_RESET_STOPWATCH:
+                case ACTION_START_STOPWATCH:
+                case ACTION_STOP_STOPWATCH:
+                case ACTION_LAP_STOPWATCH:
+                case ACTION_SHOW_STOPWATCH:
+                case ACTION_RESET_STOPWATCH:
                     handleStopwatchIntent(action);
                     break;
-                case AlarmClock.ACTION_DISMISS_ALARM:
-                    handleAlarmIntent(action);
-                    break;
-                case VOICE_ACTION_SHOW_TIMERS:
-                case VOICE_ACTION_DELETE_TIMER:
-                case VOICE_ACTION_RESET_TIMER:
-                case VOICE_ACTION_STOP_TIMER:
-                case VOICE_ACTION_START_TIMER:
+                case ACTION_SHOW_TIMERS:
+                case ACTION_DELETE_TIMER:
+                case ACTION_RESET_TIMER:
+                case ACTION_STOP_TIMER:
+                case ACTION_START_TIMER:
                     handleTimerIntent(action);
                     break;
-                case VOICE_ACTION_SHOW_CLOCK:
-                case VOICE_ACTION_ADD_CLOCK:
-                case VOICE_ACTION_DELETE_CLOCK:
+                case ACTION_SHOW_CLOCK:
+                case ACTION_ADD_CLOCK:
+                case ACTION_DELETE_CLOCK:
                     handleClockIntent(action);
                     break;
             }
@@ -130,26 +114,13 @@
         }
     }
 
-    private void handleAlarmIntent(final String action) {
-        // Opens the UI for Alarms
-        final Intent alarmIntent =
-                Alarm.createIntent(mAppContext, DeskClock.class, Alarm.INVALID_ID)
-                        .setAction(action)
-                        .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX);
-        startActivity(alarmIntent);
-
-        final Intent intent = getIntent();
-
-        new DismissAlarmAsync(mAppContext, intent).execute();
-    }
-
     private void handleStopwatchIntent(String action) {
         // Opens the UI for stopwatch
         final Intent stopwatchIntent = new Intent(mAppContext, DeskClock.class)
                 .setAction(action)
                 .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.STOPWATCH_TAB_INDEX);
         startActivity(stopwatchIntent);
-        LogUtils.i("HandleVoiceApiCalls " + action);
+        LogUtils.i("HandleDeskClockApiCalls " + action);
 
         // checking if the stopwatch is already running
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mAppContext);
@@ -158,15 +129,15 @@
 
         if (stopwatchAlreadyRunning) {
             // don't fire START_STOPWATCH or RESET_STOPWATCH if a stopwatch is already running
-            if (VOICE_ACTION_START_STOPWATCH.equals(action) ||
-                    VOICE_ACTION_RESET_STOPWATCH.equals(action)) {
+            if (ACTION_START_STOPWATCH.equals(action) ||
+                    ACTION_RESET_STOPWATCH.equals(action)) {
                 LogUtils.i("Stopwatch is already running");
                 return;
             }
         } else {
             // if a stopwatch isn't running, don't try to stop or lap it
-            if (VOICE_ACTION_STOP_STOPWATCH.equals(action) ||
-                    VOICE_ACTION_LAP_STOPWATCH.equals(action)) {
+            if (ACTION_STOP_STOPWATCH.equals(action) ||
+                    ACTION_LAP_STOPWATCH.equals(action)) {
                 LogUtils.i("Stopwatch isn't running");
                 return;
             }
@@ -174,23 +145,23 @@
 
         // Events setup
         switch (action) {
-            case VOICE_ACTION_START_STOPWATCH:
+            case ACTION_START_STOPWATCH:
                 Events.sendStopwatchEvent(R.string.action_start, R.string.label_voice);
                 LogUtils.i("Stopwatch was started.");
                 break;
-            case VOICE_ACTION_STOP_STOPWATCH:
+            case ACTION_STOP_STOPWATCH:
                 Events.sendStopwatchEvent(R.string.action_stop, R.string.label_voice);
                 LogUtils.i("Stopwatch was stopped.");
                 break;
-            case VOICE_ACTION_LAP_STOPWATCH:
+            case ACTION_LAP_STOPWATCH:
                 Events.sendStopwatchEvent(R.string.action_lap, R.string.label_voice);
                 LogUtils.i("Stopwatch was lapped.");
                 break;
-            case VOICE_ACTION_SHOW_STOPWATCH:
+            case ACTION_SHOW_STOPWATCH:
                 Events.sendStopwatchEvent(R.string.action_show, R.string.label_voice);
                 LogUtils.i("Stopwatch tab was shown.");
                 break;
-            case VOICE_ACTION_RESET_STOPWATCH:
+            case ACTION_RESET_STOPWATCH:
                 Events.sendStopwatchEvent(R.string.action_reset, R.string.label_voice);
                 LogUtils.i("Stopwatch was reset.");
                 break;
@@ -207,28 +178,28 @@
                 .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX)
                 .putExtra(TimerFullScreenFragment.GOTO_SETUP_VIEW, false);
         switch (action) {
-            case VOICE_ACTION_DELETE_TIMER:
+            case ACTION_DELETE_TIMER:
                 timerIntent.setAction(Timers.DELETE_TIMER);
                 break;
-            case VOICE_ACTION_START_TIMER:
+            case ACTION_START_TIMER:
                 timerIntent.setAction(Timers.START_TIMER);
                 break;
-            case VOICE_ACTION_RESET_TIMER:
+            case ACTION_RESET_TIMER:
                 timerIntent.setAction(Timers.RESET_TIMER);
                 break;
-            case VOICE_ACTION_STOP_TIMER:
+            case ACTION_STOP_TIMER:
                 timerIntent.setAction(Timers.STOP_TIMER);
                 break;
-            case VOICE_ACTION_SHOW_TIMERS:
+            case ACTION_SHOW_TIMERS:
                 // no action necessary
                 break;
             default:
                 return;
         }
         startActivity(timerIntent);
-        LogUtils.i("HandleVoiceApiCalls " + action);
+        LogUtils.i("HandleDeskClockApiCalls " + action);
 
-        if (VOICE_ACTION_SHOW_TIMERS.equals(action)) {
+        if (ACTION_SHOW_TIMERS.equals(action)) {
             Events.sendTimerEvent(R.string.action_show, R.string.label_voice);
             return;
         }
@@ -246,104 +217,6 @@
         new HandleClockAsync(mAppContext, getIntent()).execute();
     }
 
-    static void dismissAlarm(Alarm alarm, Context context) {
-        // only allow on background thread
-        if (Looper.myLooper() == Looper.getMainLooper()) {
-            throw new IllegalStateException("dismissAlarm must be called on a " +
-                    "background thread");
-        }
-
-        final AlarmInstance alarmInstance = AlarmInstance.getNextUpcomingInstanceByAlarmId(
-                context.getContentResolver(), alarm.id);
-        if (alarmInstance == null) {
-            LogUtils.i("There are no alarm instances for this alarm id");
-            return;
-        }
-
-        final Calendar nextAlarmTime = alarmInstance.getAlarmTime();
-        final long nextAlarmTimeMillis = nextAlarmTime.getTimeInMillis();
-        final long twoHours = -AlarmInstance.LOW_NOTIFICATION_HOUR_OFFSET *
-                DateUtils.HOUR_IN_MILLIS;
-        final boolean isWithinTwoHours = nextAlarmTimeMillis - System.currentTimeMillis()
-                <= twoHours;
-
-        if (isWithinTwoHours) {
-            AlarmStateManager.setPreDismissState(context, alarmInstance);
-            LogUtils.i("Dismiss %d:%d",alarm.hour, alarm.minutes);
-            Events.sendAlarmEvent(R.string.action_dismiss,
-                    R.string.label_voice);
-        } else {
-            LogUtils.i("%s wasn't dismissed, still more than two hours away.", alarm);
-        }
-    }
-
-    private static class DismissAlarmAsync extends AsyncTask<Void, Void, Void> {
-
-        private final Context mContext;
-        private final Intent mIntent;
-
-        public DismissAlarmAsync(Context context, Intent intent) {
-            mContext = context;
-            mIntent = intent;
-        }
-
-        @Override
-        protected Void doInBackground(Void... parameters) {
-            final List<Alarm> alarms = getRelevantAlarms();
-            if (alarms.isEmpty()) {
-                LogUtils.i("No alarms are scheduled.");
-                return null;
-            }
-
-            final String searchMode = mIntent.getStringExtra(AlarmClock.EXTRA_ALARM_SEARCH_MODE);
-            if (searchMode == null && alarms.size() > 1) {
-                // TODO: add picker UI
-                // shows the UI where user picks which alarm they want to DISMISS
-//                final Intent pickSelectionIntent = new Intent(mContext, PickSelectionActivity.class)
-//                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-//                        .setAction(mIntent.getAction())
-//                        .putExtra(PickSelectionActivity.EXTRA_ALARMS,
-//                                alarms.toArray(new Parcelable[alarms.size()]));
-//                mContext.startActivity(pickSelectionIntent);
-                return null;
-            }
-
-            // fetch the alarms that are specified by the intent
-            final FetchMatchingAlarmsAction fmaa =
-                    new FetchMatchingAlarmsAction(mContext, alarms, mIntent);
-            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) {
-                // TODO: add picker UI
-//              final Intent pickSelectionIntent = new Intent(mContext, PickSelectionActivity.class)
-//                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-//                        .setAction(mIntent.getAction())
-//                        .putExtra(PickSelectionActivity.EXTRA_ALARMS,
-//                                matchingAlarms.toArray(new Parcelable[matchingAlarms.size()]));
-//                mContext.startActivity(pickSelectionIntent);
-                return null;
-            }
-
-            // Apply the action to the matching alarms
-            for (Alarm alarm : matchingAlarms) {
-                dismissAlarm(alarm, mContext);
-                LogUtils.i("Alarm %s is dismissed", alarm);
-            }
-            return null;
-        }
-
-        private List<Alarm> getRelevantAlarms() {
-            // since we want to dismiss we should only add enabled alarms
-            final String selection = String.format("%s=?", Alarm.ENABLED);
-
-            final String[] args = {"1"};
-            return Alarm.getAlarms(mContext.getContentResolver(), selection, args);
-        }
-    }
-
     private static class HandleTimersAsync extends AsyncTask<Void, Void, Void> {
         private final Context mContext;
         private final String mAction;
@@ -367,14 +240,14 @@
             final TimerObj timer = timers.get(timers.size() - 1);
 
             switch (mAction) {
-                case VOICE_ACTION_DELETE_TIMER:
+                case ACTION_DELETE_TIMER:
                     timer.deleteFromSharedPref(prefs);
                     Events.sendTimerEvent(R.string.action_delete, R.string.label_voice);
                     LogUtils.i("Timer was successfully deleted");
                     break;
-                case VOICE_ACTION_START_TIMER:
+                case ACTION_START_TIMER:
                     // adjust mStartTime to reflect that starting time changed,
-                    // VOICE_ACTION_START_TIMER considers that a part of
+                    // ACTION_START_TIMER considers that a part of
                     // the timer's length might have elapsed
                     if (timer.mState == TimerObj.STATE_RUNNING) {
                         LogUtils.i("Timer is already running");
@@ -387,7 +260,7 @@
                     LogUtils.i("Timer was successfully started");
                     Events.sendTimerEvent(R.string.action_start, R.string.label_voice);
                     break;
-                case VOICE_ACTION_RESET_TIMER:
+                case ACTION_RESET_TIMER:
                     // timer can be reset only if it's stopped
                     if (timer.mState == TimerObj.STATE_STOPPED) {
                         timer.mTimeLeft = timer.mOriginalLength;
@@ -399,7 +272,7 @@
                         return null;
                     }
                     break;
-                case VOICE_ACTION_STOP_TIMER:
+                case ACTION_STOP_TIMER:
                     if (timer.mState == TimerObj.STATE_STOPPED) {
                         LogUtils.i("Timer is already stopped");
                         return null;
@@ -429,7 +302,7 @@
             final SharedPreferences prefs =
                     PreferenceManager.getDefaultSharedPreferences(mContext);
             switch (mIntent.getAction()) {
-                case VOICE_ACTION_ADD_CLOCK: {
+                case ACTION_ADD_CLOCK: {
                     // if a city isn't specified open CitiesActivity to choose a city
                     if (cityExtra == null) {
                         LogUtils.i("No city specified");
@@ -460,7 +333,7 @@
                     Events.sendClockEvent(R.string.action_start, R.string.label_voice);
                     break;
                 }
-                case VOICE_ACTION_DELETE_CLOCK: {
+                case ACTION_DELETE_CLOCK: {
                     if (cityExtra == null) {
                         // if a city isn't specified open CitiesActivity to choose a city
                         LogUtils.i("No city specified");
@@ -487,7 +360,7 @@
                     }
                     break;
                 }
-                case VOICE_ACTION_SHOW_CLOCK:
+                case ACTION_SHOW_CLOCK:
                     Events.sendClockEvent(R.string.action_show, R.string.label_voice);
                     break;
             }
diff --git a/src/com/android/deskclock/Utils.java b/src/com/android/deskclock/Utils.java
index 8178a99..2129474 100644
--- a/src/com/android/deskclock/Utils.java
+++ b/src/com/android/deskclock/Utils.java
@@ -54,6 +54,7 @@
 import android.widget.TextClock;
 import android.widget.TextView;
 
+import com.android.deskclock.provider.AlarmInstance;
 import com.android.deskclock.provider.DaysOfWeek;
 import com.android.deskclock.stopwatch.Stopwatches;
 import com.android.deskclock.timer.Timers;
@@ -490,6 +491,14 @@
         return timeString;
     }
 
+    public static boolean isAlarmWithinTwoHours(AlarmInstance alarmInstance) {
+        final Calendar nextAlarmTime = alarmInstance.getAlarmTime();
+        final long nextAlarmTimeMillis = nextAlarmTime.getTimeInMillis();
+        final long twoHours = -AlarmInstance.LOW_NOTIFICATION_HOUR_OFFSET *
+                DateUtils.HOUR_IN_MILLIS;
+        return nextAlarmTimeMillis - System.currentTimeMillis() <= twoHours;
+    }
+
     /** Clock views can call this to refresh their alarm to the next upcoming value. **/
     public static void refreshAlarm(Context context, View clock) {
         final String nextAlarm = getNextAlarm(context);
diff --git a/src/com/android/deskclock/stopwatch/StopwatchFragment.java b/src/com/android/deskclock/stopwatch/StopwatchFragment.java
index cf7b129..5ba6dfd 100644
--- a/src/com/android/deskclock/stopwatch/StopwatchFragment.java
+++ b/src/com/android/deskclock/stopwatch/StopwatchFragment.java
@@ -41,12 +41,12 @@
 import com.android.deskclock.CircleTimerView;
 import com.android.deskclock.DeskClock;
 import com.android.deskclock.DeskClockFragment;
+import com.android.deskclock.HandleDeskClockApiCalls;
 import com.android.deskclock.LogUtils;
 import com.android.deskclock.R;
 import com.android.deskclock.Utils;
 import com.android.deskclock.events.Events;
 import com.android.deskclock.timer.CountingTimerView;
-import com.android.deskclock.voice.HandleVoiceApiCalls;
 
 import java.util.ArrayList;
 
@@ -294,7 +294,7 @@
                 doStop();
                 Events.sendStopwatchEvent(R.string.action_stop, R.string.label_deskclock);
 
-                intent.setAction(HandleVoiceApiCalls.VOICE_ACTION_STOP_STOPWATCH);
+                intent.setAction(HandleDeskClockApiCalls.ACTION_STOP_STOPWATCH);
                 context.startService(intent);
                 releaseWakeLock();
                 break;
@@ -304,7 +304,7 @@
                 doStart(time);
                 Events.sendStopwatchEvent(R.string.action_start, R.string.label_deskclock);
 
-                intent.setAction(HandleVoiceApiCalls.VOICE_ACTION_START_STOPWATCH);
+                intent.setAction(HandleDeskClockApiCalls.ACTION_START_STOPWATCH);
                 context.startService(intent);
                 acquireWakeLock();
                 break;
@@ -851,7 +851,7 @@
                 doLap();
                 Events.sendStopwatchEvent(R.string.action_lap, R.string.label_deskclock);
 
-                intent.setAction(HandleVoiceApiCalls.VOICE_ACTION_LAP_STOPWATCH);
+                intent.setAction(HandleDeskClockApiCalls.ACTION_LAP_STOPWATCH);
                 context.startService(intent);
                 break;
             case Stopwatches.STOPWATCH_STOPPED:
@@ -859,7 +859,7 @@
                 doReset();
                 Events.sendStopwatchEvent(R.string.action_reset, R.string.label_deskclock);
 
-                intent.setAction(HandleVoiceApiCalls.VOICE_ACTION_RESET_STOPWATCH);
+                intent.setAction(HandleDeskClockApiCalls.ACTION_RESET_STOPWATCH);
                 context.startService(intent);
                 releaseWakeLock();
                 break;
diff --git a/src/com/android/deskclock/stopwatch/StopwatchService.java b/src/com/android/deskclock/stopwatch/StopwatchService.java
index 815dc29..6e10f0d 100644
--- a/src/com/android/deskclock/stopwatch/StopwatchService.java
+++ b/src/com/android/deskclock/stopwatch/StopwatchService.java
@@ -15,9 +15,9 @@
 
 import com.android.deskclock.CircleTimerView;
 import com.android.deskclock.DeskClock;
+import com.android.deskclock.HandleDeskClockApiCalls;
 import com.android.deskclock.R;
 import com.android.deskclock.Utils;
-import com.android.deskclock.voice.HandleVoiceApiCalls;
 
 /**
  * TODO: Insert description here. (generated by sblitz)
@@ -65,7 +65,7 @@
         boolean showNotif = intent.getBooleanExtra(Stopwatches.SHOW_NOTIF, true);
         boolean updateCircle = showNotif; // Don't save updates to the cirle if we're in the app.
         switch(actionType) {
-            case HandleVoiceApiCalls.VOICE_ACTION_START_STOPWATCH:
+            case HandleDeskClockApiCalls.ACTION_START_STOPWATCH:
                 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this) ;
                 prefs.edit().putBoolean(Stopwatches.NOTIF_CLOCK_RUNNING, true).apply();
 
@@ -77,7 +77,7 @@
                     saveNotification(mStartTime - mElapsedTime, true, mNumLaps);
                 }
                 break;
-            case HandleVoiceApiCalls.VOICE_ACTION_LAP_STOPWATCH:
+            case HandleDeskClockApiCalls.ACTION_LAP_STOPWATCH:
                 mNumLaps++;
                 long lapTimeElapsed = actionTime - mStartTime + mElapsedTime;
                 writeSharedPrefsLap(lapTimeElapsed, updateCircle);
@@ -87,7 +87,7 @@
                     saveNotification(mStartTime - mElapsedTime, true, mNumLaps);
                 }
                 break;
-            case HandleVoiceApiCalls.VOICE_ACTION_STOP_STOPWATCH:
+            case HandleDeskClockApiCalls.ACTION_STOP_STOPWATCH:
                 prefs = PreferenceManager.getDefaultSharedPreferences(this);
                 prefs.edit().putBoolean(Stopwatches.NOTIF_CLOCK_RUNNING, false).apply();
 
@@ -99,7 +99,7 @@
                     saveNotification(mElapsedTime, false, mNumLaps);
                 }
                 break;
-            case HandleVoiceApiCalls.VOICE_ACTION_RESET_STOPWATCH:
+            case HandleDeskClockApiCalls.ACTION_RESET_STOPWATCH:
                 mLoadApp = false;
                 writeSharedPrefsReset(updateCircle);
                 clearSavedNotification();
@@ -193,7 +193,7 @@
             remoteViewsExpanded.setTextViewText(
                     R.id.swn_left_button, getResources().getText(R.string.sw_lap_button));
             Intent leftButtonIntent = new Intent(context, StopwatchService.class);
-            leftButtonIntent.setAction(HandleVoiceApiCalls.VOICE_ACTION_LAP_STOPWATCH);
+            leftButtonIntent.setAction(HandleDeskClockApiCalls.ACTION_LAP_STOPWATCH);
             remoteViewsExpanded.setOnClickPendingIntent(R.id.swn_left_button,
                     PendingIntent.getService(context, 0, leftButtonIntent, 0));
             remoteViewsExpanded.
@@ -204,7 +204,7 @@
             remoteViewsExpanded.setTextViewText(
                     R.id.swn_right_button, getResources().getText(R.string.sw_stop_button));
             Intent rightButtonIntent = new Intent(context, StopwatchService.class);
-            rightButtonIntent.setAction(HandleVoiceApiCalls.VOICE_ACTION_STOP_STOPWATCH);
+            rightButtonIntent.setAction(HandleDeskClockApiCalls.ACTION_STOP_STOPWATCH);
             remoteViewsExpanded.setOnClickPendingIntent(R.id.swn_right_button,
                     PendingIntent.getService(context, 0, rightButtonIntent, 0));
             remoteViewsExpanded.
@@ -239,7 +239,7 @@
             remoteViewsExpanded.setTextViewText(
                     R.id.swn_right_button, getResources().getText(R.string.sw_start_button));
             Intent rightButtonIntent = new Intent(context, StopwatchService.class);
-            rightButtonIntent.setAction(HandleVoiceApiCalls.VOICE_ACTION_START_STOPWATCH);
+            rightButtonIntent.setAction(HandleDeskClockApiCalls.ACTION_START_STOPWATCH);
             remoteViewsExpanded.setOnClickPendingIntent(R.id.swn_right_button,
                     PendingIntent.getService(context, 0, rightButtonIntent, 0));
             remoteViewsExpanded.
@@ -256,7 +256,7 @@
         }
 
         Intent dismissIntent = new Intent(context, StopwatchService.class);
-        dismissIntent.setAction(HandleVoiceApiCalls.VOICE_ACTION_RESET_STOPWATCH);
+        dismissIntent.setAction(HandleDeskClockApiCalls.ACTION_RESET_STOPWATCH);
 
         Notification notification = new NotificationCompat.Builder(context)
                 .setAutoCancel(!clockRunning)