@SuppressLint("NewApi")
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long i) {
          AlertActivity alertActivity = AlertActivity.this;
          Cursor cursor = alertActivity.getItemForView(view);

          long alarmId = cursor.getLong(INDEX_ROW_ID);
          long eventId = cursor.getLong(AlertActivity.INDEX_EVENT_ID);
          long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN);

          // Mark this alarm as DISMISSED
          dismissAlarm(alarmId, eventId, startMillis);

          // build an intent and task stack to start EventInfoActivity with AllInOneActivity
          // as the parent activity rooted to home.
          long endMillis = cursor.getLong(AlertActivity.INDEX_END);
          Intent eventIntent =
              AlertUtils.buildEventViewIntent(AlertActivity.this, eventId, startMillis, endMillis);

          if (Utils.isJellybeanOrLater()) {
            TaskStackBuilder.create(AlertActivity.this)
                .addParentStack(EventInfoActivity.class)
                .addNextIntent(eventIntent)
                .startActivities();
          } else {
            alertActivity.startActivity(eventIntent);
          }

          alertActivity.finish();
        }
  /**
   * Queries for all the reminders of the events in the instancesCursor, and schedules the alarm for
   * the next upcoming reminder.
   */
  private static void queryNextReminderAndSchedule(
      Cursor instancesCursor,
      Context context,
      ContentResolver contentResolver,
      AlarmManagerInterface alarmManager,
      int batchSize,
      long currentMillis) {
    if (AlertService.DEBUG) {
      int eventCount = instancesCursor.getCount();
      if (eventCount == 0) {
        Log.d(TAG, "No events found starting within 1 week.");
      } else {
        Log.d(TAG, "Query result count for events starting within 1 week: " + eventCount);
      }
    }

    // Put query results of all events starting within some interval into map of event ID to
    // local start time.
    Map<Integer, List<Long>> eventMap = new HashMap<Integer, List<Long>>();
    Time timeObj = new Time();
    long nextAlarmTime = Long.MAX_VALUE;
    int nextAlarmEventId = 0;
    instancesCursor.moveToPosition(-1);
    while (!instancesCursor.isAfterLast()) {
      int index = 0;
      eventMap.clear();
      StringBuilder eventIdsForQuery = new StringBuilder();
      eventIdsForQuery.append('(');
      while (index++ < batchSize && instancesCursor.moveToNext()) {
        int eventId = instancesCursor.getInt(INSTANCES_INDEX_EVENTID);
        long begin = instancesCursor.getLong(INSTANCES_INDEX_BEGIN);
        boolean allday = instancesCursor.getInt(INSTANCES_INDEX_ALL_DAY) != 0;
        long localStartTime;
        if (allday) {
          // Adjust allday to local time.
          localStartTime = Utils.convertAlldayUtcToLocal(timeObj, begin, Time.getCurrentTimezone());
        } else {
          localStartTime = begin;
        }
        List<Long> startTimes = eventMap.get(eventId);
        if (startTimes == null) {
          startTimes = new ArrayList<Long>();
          eventMap.put(eventId, startTimes);
          eventIdsForQuery.append(eventId);
          eventIdsForQuery.append(",");
        }
        startTimes.add(localStartTime);

        // Log for debugging.
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          timeObj.set(localStartTime);
          StringBuilder msg = new StringBuilder();
          msg.append("Events cursor result -- eventId:").append(eventId);
          msg.append(", allDay:").append(allday);
          msg.append(", start:").append(localStartTime);
          msg.append(" (").append(timeObj.format("%a, %b %d, %Y %I:%M%P")).append(")");
          Log.d(TAG, msg.toString());
        }
      }
      if (eventIdsForQuery.charAt(eventIdsForQuery.length() - 1) == ',') {
        eventIdsForQuery.deleteCharAt(eventIdsForQuery.length() - 1);
      }
      eventIdsForQuery.append(')');

      // Query the reminders table for the events found.
      Cursor cursor = null;
      try {
        cursor =
            contentResolver.query(
                Reminders.CONTENT_URI,
                REMINDERS_PROJECTION,
                REMINDERS_WHERE + eventIdsForQuery,
                null,
                null);

        // Process the reminders query results to find the next reminder time.
        cursor.moveToPosition(-1);
        while (cursor.moveToNext()) {
          int eventId = cursor.getInt(REMINDERS_INDEX_EVENT_ID);
          int reminderMinutes = cursor.getInt(REMINDERS_INDEX_MINUTES);
          List<Long> startTimes = eventMap.get(eventId);
          if (startTimes != null) {
            for (Long startTime : startTimes) {
              long alarmTime = startTime - reminderMinutes * DateUtils.MINUTE_IN_MILLIS;
              if (alarmTime > currentMillis && alarmTime < nextAlarmTime) {
                nextAlarmTime = alarmTime;
                nextAlarmEventId = eventId;
              }

              if (Log.isLoggable(TAG, Log.DEBUG)) {
                timeObj.set(alarmTime);
                StringBuilder msg = new StringBuilder();
                msg.append("Reminders cursor result -- eventId:").append(eventId);
                msg.append(", startTime:").append(startTime);
                msg.append(", minutes:").append(reminderMinutes);
                msg.append(", alarmTime:").append(alarmTime);
                msg.append(" (").append(timeObj.format("%a, %b %d, %Y %I:%M%P")).append(")");
                Log.d(TAG, msg.toString());
              }
            }
          }
        }
      } finally {
        if (cursor != null) {
          cursor.close();
        }
      }
    }

    // Schedule the alarm for the next reminder time.
    if (nextAlarmTime < Long.MAX_VALUE) {
      scheduleAlarm(context, nextAlarmEventId, nextAlarmTime, currentMillis, alarmManager);
    }
  }