b/2293263 Replaced busybit functionality with eventday functionality.
Stripped out references to busybits and replaced with code to request only whether an event
exists for each day. In MetaData only minimal changes were made to prevent breaking the
build as I'm not certain all of the effects it has yet. Will do more complete removal of
busybits along with other references.
diff --git a/src/com/android/providers/calendar/CalendarProvider.java b/src/com/android/providers/calendar/CalendarProvider.java
index 39695a7..9cd6f86 100644
--- a/src/com/android/providers/calendar/CalendarProvider.java
+++ b/src/com/android/providers/calendar/CalendarProvider.java
@@ -62,7 +62,6 @@
import android.pim.RecurrenceSet;
import android.provider.Calendar;
import android.provider.Calendar.Attendees;
-import android.provider.Calendar.BusyBits;
import android.provider.Calendar.CalendarAlerts;
import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events;
@@ -134,24 +133,6 @@
*/
MetaData mMetaData;
- // The interval in minutes for calculating busy bits
- private static final int BUSYBIT_INTERVAL = 60;
-
- // A lookup table for getting a bit mask of length N, for N <= 32
- // For example, BIT_MASKS[4] gives 0xf (which has 4 bits set to 1).
- // We use this for computing the busy bits for events.
- private static final int[] BIT_MASKS = {
- 0,
- 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
- 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
- 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
- 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
- 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
- 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
- 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
- };
-
// To determine if a recurrence exception originally overlapped the
// window, we need to assume a maximum duration, since we only know
// the original start time.
@@ -265,12 +246,6 @@
private static final int INSTANCES_INDEX_END_MINUTE = 3;
private static final int INSTANCES_INDEX_ALL_DAY = 4;
- private static final String[] sBusyBitProjection = new String[] {
- BusyBits.DAY, BusyBits.BUSYBITS, BusyBits.ALL_DAY_COUNT };
-
- private static final int BUSYBIT_INDEX_DAY = 0;
- private static final int BUSYBIT_INDEX_BUSYBITS= 1;
- private static final int BUSYBIT_INDEX_ALL_DAY_COUNT = 2;
private CalendarClient mCalendarClient = null;
@@ -392,12 +367,6 @@
handleInstanceQuery(qb, begin, end, new String[] { Instances._ID },
null /* selection */, null /* sort */, false /* searchByDayInsteadOfMillis */);
- // Also pre-compute the BusyBits table for this month.
- int startDay = Time.getJulianDay(begin, time.gmtoff);
- int endDay = startDay + 31;
- qb = new SQLiteQueryBuilder();
- handleBusyBitsQuery(qb, startDay, endDay, sBusyBitProjection,
- null /* selection */, null /* sort */);
rescheduleMissedAlarms();
}
@@ -1137,7 +1106,7 @@
}
return handleInstanceQuery(qb, begin, end, projectionIn,
selection, sort, match == INSTANCES_BY_DAY);
- case BUSYBITS:
+ case EVENT_DAYS:
int startDay;
int endDay;
try {
@@ -1152,8 +1121,7 @@
throw new IllegalArgumentException("Cannot parse end day "
+ url.getPathSegments().get(3));
}
- return handleBusyBitsQuery(qb, startDay, endDay, projectionIn,
- selection, sort);
+ return handleEventDayQuery(qb, startDay, endDay, projectionIn, selection);
case ATTENDEES:
qb.setTables("Attendees, Events, Calendars");
qb.setProjectionMap(sAttendeesProjectionMap);
@@ -1269,18 +1237,19 @@
return qb.query(db, projectionIn, selection, null, null, null, sort);
}
- private Cursor handleBusyBitsQuery(SQLiteQueryBuilder qb, int startDay,
- int endDay, String[] projectionIn,
- String selection, String sort) {
+ private Cursor handleEventDayQuery(SQLiteQueryBuilder qb, int begin, int end,
+ String[] projection, String selection) {
final SQLiteDatabase db = getDatabase();
- acquireBusyBitRange(startDay, endDay);
- qb.setTables("BusyBits");
- qb.setProjectionMap(sBusyBitsProjectionMap);
- qb.appendWhere("day >= ");
- qb.appendWhere(String.valueOf(startDay));
- qb.appendWhere(" AND day <= ");
- qb.appendWhere(String.valueOf(endDay));
- return qb.query(db, projectionIn, selection, null, null, null, sort);
+ qb.setTables("Instances INNER JOIN Events ON (Instances.event_id=Events._id) " +
+ "INNER JOIN Calendars ON (Events.calendar_id = Calendars._id)");
+ qb.setProjectionMap(sInstancesProjectionMap);
+ acquireInstanceRange(begin, end, true);
+ qb.appendWhere("startDay <= ");
+ qb.appendWhere(String.valueOf(end));
+ qb.appendWhere(" AND endDay >= ");
+ qb.appendWhere(String.valueOf(begin));
+ return qb.query(db, projection, selection, null /* selectionArgs */,
+ Instances.START_DAY /* groupBy */, null /* having */, null);
}
/**
@@ -1304,20 +1273,6 @@
}
/**
- * Expands the Instances table (if needed) and the BusyBits table.
- * Acquires the database lock and calls {@link #acquireBusyBitRangeLocked}.
- */
- private void acquireBusyBitRange(final int startDay, final int endDay) {
- mDb.beginTransaction();
- try {
- acquireBusyBitRangeLocked(startDay, endDay);
- mDb.setTransactionSuccessful();
- } finally {
- mDb.endTransaction();
- }
- }
-
- /**
* Ensure that the date range given has all elements in the instance
* table. The database lock must be held when calling this method.
*
@@ -1355,9 +1310,8 @@
if (maxInstance == 0 || timezoneChanged) {
// Empty the Instances table and expand from scratch.
mDb.execSQL("DELETE FROM Instances;");
- mDb.execSQL("DELETE FROM BusyBits;");
if (Config.LOGV) {
- Log.v(TAG, "acquireInstanceRangeLocked() deleted Instances and Busybits,"
+ Log.v(TAG, "acquireInstanceRangeLocked() deleted Instances,"
+ " timezone changed: " + timezoneChanged);
}
expandInstanceRangeLocked(expandBegin, expandEnd, localTimezone);
@@ -1405,122 +1359,6 @@
fields.minBusyBit, fields.maxBusyBit);
}
- private void acquireBusyBitRangeLocked(int firstDay, int lastDay) {
- if (firstDay > lastDay) {
- throw new IllegalArgumentException("firstDay must not be greater than lastDay");
- }
- String localTimezone = TimeZone.getDefault().getID();
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- String dbTimezone = fields.timezone;
- int minBusyBit = fields.minBusyBit;
- int maxBusyBit = fields.maxBusyBit;
- boolean timezoneChanged = (dbTimezone == null) || !dbTimezone.equals(localTimezone);
- if (firstDay >= minBusyBit && lastDay <= maxBusyBit && !timezoneChanged) {
- if (Config.LOGV) {
- Log.v(TAG, "acquireBusyBitRangeLocked() no expansion needed");
- }
- return;
- }
-
- // Avoid gaps in the BusyBit table and avoid recomputing the busy bits
- // that are already in the table. If the busy bit range has been cleared,
- // don't bother checking.
- if (maxBusyBit != 0) {
- if (firstDay > maxBusyBit) {
- firstDay = maxBusyBit;
- } else if (lastDay < minBusyBit) {
- lastDay = minBusyBit;
- } else if (firstDay < minBusyBit && lastDay <= maxBusyBit) {
- lastDay = minBusyBit;
- } else if (lastDay > maxBusyBit && firstDay >= minBusyBit) {
- firstDay = maxBusyBit;
- }
- }
-
- // Allocate space for the busy bits, one 32-bit integer for each day.
- int numDays = lastDay - firstDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- // Convert the first and last Julian day range to a range that uses
- // UTC milliseconds.
- Time time = new Time();
- long begin = time.setJulianDay(firstDay);
-
- // We add one to lastDay because the time is set to 12am on the given
- // Julian day and we want to include all the events on the last day.
- long end = time.setJulianDay(lastDay + 1);
-
- // Make sure the Instances table includes events in the range
- // [begin, end].
- acquireInstanceRange(begin, end, true /* use minimum expansion window */);
-
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- qb.setTables("Instances INNER JOIN Events ON (Instances.event_id=Events._id) " +
- "INNER JOIN Calendars ON (Events.calendar_id = Calendars._id)");
- qb.setProjectionMap(sInstancesProjectionMap);
- qb.appendWhere("begin <= ");
- qb.appendWhere(String.valueOf(end));
- qb.appendWhere(" AND end >= ");
- qb.appendWhere(String.valueOf(begin));
- qb.appendWhere(" AND ");
- qb.appendWhere(Instances.SELECTED);
- qb.appendWhere("=1");
-
- final SQLiteDatabase db = getDatabase();
- // Get all the instances that overlap the range [begin,end]
- Cursor cursor = qb.query(db, sInstancesProjection, null, null, null, null, null);
- int count = 0;
- try {
- count = cursor.getCount();
- while (cursor.moveToNext()) {
- int startDay = cursor.getInt(INSTANCES_INDEX_START_DAY);
- int endDay = cursor.getInt(INSTANCES_INDEX_END_DAY);
- int startMinute = cursor.getInt(INSTANCES_INDEX_START_MINUTE);
- int endMinute = cursor.getInt(INSTANCES_INDEX_END_MINUTE);
- boolean allDay = cursor.getInt(INSTANCES_INDEX_ALL_DAY) != 0;
- fillBusyBits(firstDay, startDay, endDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- if (count == 0) {
- return;
- }
-
- // Read the busybit range again because that may have changed when we
- // called acquireInstanceRange().
- fields = mMetaData.getFieldsLocked();
- minBusyBit = fields.minBusyBit;
- maxBusyBit = fields.maxBusyBit;
-
- // If the busybit range was cleared, then delete all the entries.
- if (maxBusyBit == 0) {
- mDb.execSQL("DELETE FROM BusyBits;");
- }
-
- // Merge the busy bits with the database.
- mergeBusyBits(firstDay, lastDay, busybits, allDayCounts);
- if (maxBusyBit == 0) {
- minBusyBit = firstDay;
- maxBusyBit = lastDay;
- } else {
- if (firstDay < minBusyBit) {
- minBusyBit = firstDay;
- }
- if (lastDay > maxBusyBit) {
- maxBusyBit = lastDay;
- }
- }
- // Update the busy bit range
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- minBusyBit, maxBusyBit);
- }
-
private static final String[] EXPAND_COLUMNS = new String[] {
Events._ID,
Events._SYNC_ID,
@@ -1960,324 +1798,6 @@
values.put(Instances.END_MINUTE, endMinute);
}
- private void fillBusyBits(int minDay, int startDay, int endDay, int startMinute,
- int endMinute, boolean allDay, int[] busybits, int[] allDayCounts) {
-
- // The startDay can be less than the minDay if we have an event
- // that starts earlier than the time range we are interested in.
- // In that case, we ignore the time range that falls outside the
- // the range we are interested in.
- if (startDay < minDay) {
- startDay = minDay;
- startMinute = 0;
- }
-
- // Likewise, truncate the event's end day so that it doesn't go past
- // the expected range.
- int numDays = busybits.length;
- int stopDay = endDay;
- if (stopDay > minDay + numDays - 1) {
- stopDay = minDay + numDays - 1;
- }
- int dayIndex = startDay - minDay;
-
- if (allDay) {
- for (int day = startDay; day <= stopDay; day++, dayIndex++) {
- allDayCounts[dayIndex] += 1;
- }
- return;
- }
-
- for (int day = startDay; day <= stopDay; day++, dayIndex++) {
- int endTime = endMinute;
- // If the event ends on a future day, then show it extending to
- // the end of this day.
- if (endDay > day) {
- endTime = 24 * 60;
- }
-
- int startBit = startMinute / BUSYBIT_INTERVAL ;
- int endBit = (endTime + BUSYBIT_INTERVAL - 1) / BUSYBIT_INTERVAL;
- int len = endBit - startBit;
- if (len == 0) {
- len = 1;
- }
- if (len < 0 || len > 24) {
- Log.e("Cal", "fillBusyBits() error: len " + len
- + " startMinute,endTime " + startMinute + " , " + endTime
- + " startDay,endDay " + startDay + " , " + endDay);
- } else {
- int oneBits = BIT_MASKS[len];
- busybits[dayIndex] |= oneBits << startBit;
- }
-
- // Set the start minute to the beginning of the day, in
- // case this event spans multiple days.
- startMinute = 0;
- }
- }
-
- private void mergeBusyBits(int startDay, int endDay, int[] busybits, int[] allDayCounts) {
- mDb.beginTransaction();
- try {
- mergeBusyBitsLocked(startDay, endDay, busybits, allDayCounts);
- mDb.setTransactionSuccessful();
- } finally {
- mDb.endTransaction();
- }
- }
-
- private void mergeBusyBitsLocked(int startDay, int endDay, int[] busybits,
- int[] allDayCounts) {
- final SQLiteDatabase db = getDatabase();
- Cursor cursor = null;
- try {
- String selection = "day>=" + startDay + " AND day<=" + endDay;
- cursor = db.query("BusyBits", sBusyBitProjection, selection, null, null, null, null);
- if (cursor == null) {
- return;
- }
- while (cursor.moveToNext()) {
- int day = cursor.getInt(BUSYBIT_INDEX_DAY);
- int busy = cursor.getInt(BUSYBIT_INDEX_BUSYBITS);
- int allDayCount = cursor.getInt(BUSYBIT_INDEX_ALL_DAY_COUNT);
-
- int dayIndex = day - startDay;
- busybits[dayIndex] |= busy;
- allDayCounts[dayIndex] += allDayCount;
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- // Allocate a map that we can reuse
- ContentValues values = new ContentValues();
-
- // Write the busy bits to the database
- int len = busybits.length;
- for (int dayIndex = 0; dayIndex < len; dayIndex++) {
- int busy = busybits[dayIndex];
- int allDayCount = allDayCounts[dayIndex];
- if (busy == 0 && allDayCount == 0) {
- continue;
- }
- int day = startDay + dayIndex;
-
- values.clear();
- values.put(BusyBits.DAY, day);
- values.put(BusyBits.BUSYBITS, busy);
- values.put(BusyBits.ALL_DAY_COUNT, allDayCount);
- db.replace("BusyBits", null, values);
- }
- }
-
- /**
- * Updates the BusyBit table when a new event is inserted into the Events
- * table. This is called after the event has been entered into the Events
- * table. If the event time is not within the date range of the current
- * BusyBits table, then the busy bits are not updated. The BusyBits
- * table is not automatically expanded to include this event.
- *
- * @param eventId the id of the newly created event
- * @param values the ContentValues for the new event
- */
- private void insertBusyBitsLocked(long eventId, ContentValues values) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // If this is a recurrence event, then the expanded Instances range
- // should be 0 because this is called after updateInstancesLocked().
- // But for now check this condition and report an error if it occurs.
- // In the future, we could even support recurring events by
- // expanding them here and updating the busy bits for each instance.
- if (isRecurrenceEvent(values)) {
- Log.e(TAG, "insertBusyBitsLocked(): unexpected recurrence event\n");
- return;
- }
-
- long dtstartMillis = values.getAsLong(Events.DTSTART);
- Long dtendMillis = values.getAsLong(Events.DTEND);
- if (dtendMillis == null) {
- dtendMillis = dtstartMillis;
- }
-
- boolean allDay = false;
- Integer allDayInteger = values.getAsInteger(Events.ALL_DAY);
- if (allDayInteger != null) {
- allDay = allDayInteger != 0;
- }
-
- Time time = new Time();
- if (allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- }
-
- ContentValues busyValues = new ContentValues();
- computeTimezoneDependentFields(dtstartMillis, dtendMillis, time, busyValues);
-
- int startDay = busyValues.getAsInteger(Instances.START_DAY);
- int endDay = busyValues.getAsInteger(Instances.END_DAY);
-
- // If the event time is not in the expanded BusyBits range,
- // then return.
- if (startDay > fields.maxBusyBit || endDay < fields.minBusyBit) {
- return;
- }
-
- // Allocate space for the busy bits, one 32-bit integer for each day,
- // plus 24 bytes for the count of events that occur in each time slot.
- int numDays = endDay - startDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- int startMinute = busyValues.getAsInteger(Instances.START_MINUTE);
- int endMinute = busyValues.getAsInteger(Instances.END_MINUTE);
- fillBusyBits(startDay, startDay, endDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- mergeBusyBits(startDay, endDay, busybits, allDayCounts);
- }
-
- /**
- * Updates the busy bits for an event that is being updated. This is
- * called before the event is updated in the Events table because we need
- * to know the time of the event before it was changed.
- *
- * @param eventId the id of the event being updated
- * @param values the ContentValues for the updated event
- */
- private void updateBusyBitsLocked(long eventId, ContentValues values) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // If this is a recurring event, then clear the BusyBits table.
- if (isRecurrenceEvent(values)) {
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // If the event fields being updated don't contain the start or end
- // time, then we don't need to bother updating the BusyBits table.
- Long dtstartLong = values.getAsLong(Events.DTSTART);
- Long dtendLong = values.getAsLong(Events.DTEND);
- if (dtstartLong == null && dtendLong == null) {
- return;
- }
-
- // If the timezone has changed, then clear the busy bits table
- // and return.
- String dbTimezone = fields.timezone;
- String localTimezone = TimeZone.getDefault().getID();
- boolean timezoneChanged = (dbTimezone == null) || !dbTimezone.equals(localTimezone);
- if (timezoneChanged) {
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // Read the existing event start and end times from the Events table.
- TimeRange eventRange = readEventStartEnd(eventId);
-
- // Fill in the new start time (if missing) or the new end time (if
- // missing) from the existing event start and end times.
- long dtstartMillis;
- if (dtstartLong != null) {
- dtstartMillis = dtstartLong;
- } else {
- dtstartMillis = eventRange.begin;
- }
-
- long dtendMillis;
- if (dtendLong != null) {
- dtendMillis = dtendLong;
- } else {
- dtendMillis = eventRange.end;
- }
-
- // Compute the start and end Julian days for the event.
- Time time = new Time();
- if (eventRange.allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- }
- ContentValues busyValues = new ContentValues();
- computeTimezoneDependentFields(eventRange.begin, eventRange.end, time, busyValues);
- int oldStartDay = busyValues.getAsInteger(Instances.START_DAY);
- int oldEndDay = busyValues.getAsInteger(Instances.END_DAY);
-
- boolean allDay = false;
- Integer allDayInteger = values.getAsInteger(Events.ALL_DAY);
- if (allDayInteger != null) {
- allDay = allDayInteger != 0;
- }
-
- if (allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- } else {
- time.timezone = TimeZone.getDefault().getID();
- }
-
- computeTimezoneDependentFields(dtstartMillis, dtendMillis, time, busyValues);
- int newStartDay = busyValues.getAsInteger(Instances.START_DAY);
- int newEndDay = busyValues.getAsInteger(Instances.END_DAY);
-
- // If both the old and new event times are outside the expanded
- // BusyBits table, then return.
- if ((oldStartDay > fields.maxBusyBit || oldEndDay < fields.minBusyBit)
- && (newStartDay > fields.maxBusyBit || newEndDay < fields.minBusyBit)) {
- return;
- }
-
- // If the old event time is within the expanded Instances range,
- // then clear the BusyBits table and return.
- if (oldStartDay <= fields.maxBusyBit && oldEndDay >= fields.minBusyBit) {
- // We could recompute the busy bits for the days containing the
- // old event time. For now, just clear the BusyBits table.
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // The new event time is within the expanded Instances range.
- // So insert the busy bits for that day (or days).
-
- // Allocate space for the busy bits, one 32-bit integer for each day,
- // plus 24 bytes for the count of events that occur in each time slot.
- int numDays = newEndDay - newStartDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- int startMinute = busyValues.getAsInteger(Instances.START_MINUTE);
- int endMinute = busyValues.getAsInteger(Instances.END_MINUTE);
- fillBusyBits(newStartDay, newStartDay, newEndDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- mergeBusyBits(newStartDay, newEndDay, busybits, allDayCounts);
- }
-
- /**
- * This method is called just before an event is deleted.
- *
- * @param eventId
- */
- private void deleteBusyBitsLocked(long eventId) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // TODO: if the event being deleted is not a recurring event and the
- // start and end time are outside the BusyBit range, then we could
- // avoid clearing the BusyBits table. For now, always clear the
- // BusyBits table because deleting events is relatively rare.
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- }
-
// Read the start and end time for an event from the Events table.
// Also read the "all-day" indicator.
private TimeRange readEventStartEnd(long eventId) {
@@ -2324,9 +1844,8 @@
return "vnd.android.cursor.item/calendar-alert";
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
return "vnd.android.cursor.dir/event-instance";
- case BUSYBITS:
- return "vnd.android.cursor.dir/busybits";
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
@@ -2379,7 +1898,6 @@
if (!isTemporary() && rowId != -1) {
updateEventRawTimesLocked(rowId, updatedValues);
updateInstancesLocked(updatedValues, rowId, true /* new event */, db);
- insertBusyBitsLocked(rowId, updatedValues);
// If we inserted a new event that specified the self-attendee
// status, then we need to add an entry to the attendees table.
@@ -2462,6 +1980,7 @@
case EXTENDED_PROPERTIES_ID:
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
throw new UnsupportedOperationException("Cannot insert into that URL");
default:
throw new IllegalArgumentException("Unknown URL " + url);
@@ -2953,7 +2472,6 @@
+ match);
}
if (!isTemporary()) {
- deleteBusyBitsLocked(Integer.parseInt(id));
// Query this event to get the fields needed for inserting
// a new row in the DeletedEvents table.
@@ -3068,6 +2586,7 @@
return deleteMatchingCalendars(where);
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
throw new UnsupportedOperationException("Cannot delete that URL");
default:
throw new IllegalArgumentException("Unknown URL " + url);
@@ -3124,14 +2643,6 @@
}
int result = db.update("Calendars", values, "_id="+ id, null);
- if (!isTemporary()) {
- // When we change the display status of a Calendar
- // we need to update the busy bits.
- if (values.containsKey(Calendars.SELECTED) || (syncEvents != null)) {
- // Clear the BusyBits table.
- mMetaData.clearBusyBitRange();
- }
- }
return result;
}
@@ -3157,7 +2668,6 @@
+ " in Events table is not allowed.");
}
- updateBusyBitsLocked(id, values);
}
ContentValues updatedValues = updateContentValuesFromEvent(values);
@@ -3699,7 +3209,6 @@
insertExtendedPropertiesIfNecessary(diffs, diffsRowId, rowId, db);
updateEventRawTimesLocked(rowId, mValues);
updateInstancesLocked(mValues, rowId, true /* new event */, db);
- insertBusyBitsLocked(rowId, mValues);
// Update the _SYNC_DIRTY flag of the event. We have to do this
// after inserting since the update of the reminders and extended properties
@@ -3818,7 +3327,6 @@
Cursor diffsCursor) {
rowToContentValues(diffsCursor, mValues);
final SQLiteDatabase db = getDatabase();
- updateBusyBitsLocked(localId, mValues);
int numRows = db.update(mTable, mValues, "_id=" + localId, null /* selectionArgs */);
if (numRows <= 0) {
@@ -3864,7 +3372,6 @@
@Override
public void deleteRow(Cursor localCursor) {
long localId = localCursor.getLong(localCursor.getColumnIndexOrThrow(Events._ID));
- deleteBusyBitsLocked(localId);
// we have to read this row from the DB since the projection that is used
// by cursor doesn't necessarily contain the columns we need
@@ -3955,8 +3462,8 @@
private static final int CALENDAR_ALERTS = 13;
private static final int CALENDAR_ALERTS_ID = 14;
private static final int CALENDAR_ALERTS_BY_INSTANCE = 15;
- private static final int BUSYBITS = 16;
- private static final int INSTANCES_BY_DAY = 17;
+ private static final int INSTANCES_BY_DAY = 16;
+ private static final int EVENT_DAYS = 17;
private static final UriMatcher sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final HashMap<String, String> sInstancesProjectionMap;
@@ -3964,11 +3471,11 @@
private static final HashMap<String, String> sAttendeesProjectionMap;
private static final HashMap<String, String> sRemindersProjectionMap;
private static final HashMap<String, String> sCalendarAlertsProjectionMap;
- private static final HashMap<String, String> sBusyBitsProjectionMap;
static {
sURLMatcher.addURI("calendar", "instances/when/*/*", INSTANCES);
sURLMatcher.addURI("calendar", "instances/whenbyday/*/*", INSTANCES_BY_DAY);
+ sURLMatcher.addURI("calendar", "instances/groupbyday/*/*", EVENT_DAYS);
sURLMatcher.addURI("calendar", "events", EVENTS);
sURLMatcher.addURI("calendar", "events/#", EVENTS_ID);
sURLMatcher.addURI("calendar", "calendars", CALENDARS);
@@ -3983,7 +3490,6 @@
sURLMatcher.addURI("calendar", "calendar_alerts", CALENDAR_ALERTS);
sURLMatcher.addURI("calendar", "calendar_alerts/#", CALENDAR_ALERTS_ID);
sURLMatcher.addURI("calendar", "calendar_alerts/by_instance", CALENDAR_ALERTS_BY_INSTANCE);
- sURLMatcher.addURI("calendar", "busybits/when/*/*", BUSYBITS);
sEventsProjectionMap = new HashMap<String, String>();
@@ -4053,12 +3559,6 @@
sInstancesProjectionMap.put(Instances.START_MINUTE, "startMinute");
sInstancesProjectionMap.put(Instances.END_MINUTE, "endMinute");
- // BusyBits columns
- sBusyBitsProjectionMap = new HashMap<String, String>();
- sBusyBitsProjectionMap.put(BusyBits.DAY, "day");
- sBusyBitsProjectionMap.put(BusyBits.BUSYBITS, "busyBits");
- sBusyBitsProjectionMap.put(BusyBits.ALL_DAY_COUNT, "allDayCount");
-
// Attendees columns
sAttendeesProjectionMap.put(Attendees.EVENT_ID, "event_id");
sAttendeesProjectionMap.put(Attendees._ID, "Attendees._id AS _id");
diff --git a/src/com/android/providers/calendar/CalendarProvider2.java b/src/com/android/providers/calendar/CalendarProvider2.java
index b7879a2..ef0ca24 100644
--- a/src/com/android/providers/calendar/CalendarProvider2.java
+++ b/src/com/android/providers/calendar/CalendarProvider2.java
@@ -43,7 +43,6 @@
import android.provider.BaseColumns;
import android.provider.Calendar;
import android.provider.Calendar.Attendees;
-import android.provider.Calendar.BusyBits;
import android.provider.Calendar.CalendarAlerts;
import android.provider.Calendar.Calendars;
import android.provider.Calendar.Events;
@@ -111,24 +110,6 @@
private static final Uri SYNCSTATE_CONTENT_URI =
Uri.parse("content://syncstate/state");
- // The interval in minutes for calculating busy bits
- private static final int BUSYBIT_INTERVAL = 60;
-
- // A lookup table for getting a bit mask of length N, for N <= 32
- // For example, BIT_MASKS[4] gives 0xf (which has 4 bits set to 1).
- // We use this for computing the busy bits for events.
- private static final int[] BIT_MASKS = {
- 0,
- 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
- 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
- 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
- 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
- 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
- 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
- 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
- };
-
// To determine if a recurrence exception originally overlapped the
// window, we need to assume a maximum duration, since we only know
// the original start time.
@@ -236,13 +217,6 @@
private static final int INSTANCES_INDEX_END_MINUTE = 3;
private static final int INSTANCES_INDEX_ALL_DAY = 4;
- private static final String[] sBusyBitProjection = new String[] {
- BusyBits.DAY, BusyBits.BUSYBITS, BusyBits.ALL_DAY_COUNT };
-
- private static final int BUSYBIT_INDEX_DAY = 0;
- private static final int BUSYBIT_INDEX_BUSYBITS= 1;
- private static final int BUSYBIT_INDEX_ALL_DAY_COUNT = 2;
-
private CalendarClient mCalendarClient = null;
private AlarmManager mAlarmManager;
@@ -371,12 +345,6 @@
handleInstanceQuery(qb, begin, end, new String[] { Instances._ID },
null /* selection */, null /* sort */, false /* searchByDayInsteadOfMillis */);
- // Also pre-compute the BusyBits table for this month.
- int startDay = Time.getJulianDay(begin, time.gmtoff);
- int endDay = startDay + 31;
- qb = new SQLiteQueryBuilder();
- handleBusyBitsQuery(qb, startDay, endDay, sBusyBitProjection,
- null /* selection */, null /* sort */);
rescheduleMissedAlarms();
}
@@ -481,7 +449,7 @@
}
return handleInstanceQuery(qb, begin, end, projection,
selection, sortOrder, match == INSTANCES_BY_DAY);
- case BUSYBITS:
+ case EVENT_DAYS:
int startDay;
int endDay;
try {
@@ -496,8 +464,7 @@
throw new IllegalArgumentException("Cannot parse end day "
+ uri.getPathSegments().get(3));
}
- return handleBusyBitsQuery(qb, startDay, endDay, projection,
- selection, sortOrder);
+ return handleEventDayQuery(qb, startDay, endDay, projection, selection);
case ATTENDEES:
qb.setTables("Attendees, Events, Calendars");
qb.setProjectionMap(sAttendeesProjectionMap);
@@ -617,18 +584,18 @@
null /* having */, sort);
}
- private Cursor handleBusyBitsQuery(SQLiteQueryBuilder qb, int startDay,
- int endDay, String[] projection,
- String selection, String sort) {
- acquireBusyBitRange(startDay, endDay);
- qb.setTables("BusyBits");
- qb.setProjectionMap(sBusyBitsProjectionMap);
- qb.appendWhere("day >= ");
- qb.appendWhere(String.valueOf(startDay));
- qb.appendWhere(" AND day <= ");
- qb.appendWhere(String.valueOf(endDay));
- return qb.query(mDb, projection, selection, null /* selectionArgs */, null /* groupBy */,
- null /* having */, sort);
+ private Cursor handleEventDayQuery(SQLiteQueryBuilder qb, int begin, int end,
+ String[] projection, String selection) {
+ qb.setTables("Instances INNER JOIN Events ON (Instances.event_id=Events._id) " +
+ "INNER JOIN Calendars ON (Events.calendar_id = Calendars._id)");
+ qb.setProjectionMap(sInstancesProjectionMap);
+ acquireInstanceRange(begin, end, true);
+ qb.appendWhere("startDay <= ");
+ qb.appendWhere(String.valueOf(end));
+ qb.appendWhere(" AND endDay >= ");
+ qb.appendWhere(String.valueOf(begin));
+ return qb.query(mDb, projection, selection, null /* selectionArgs */,
+ Instances.START_DAY /* groupBy */, null /* having */, null);
}
/**
@@ -652,20 +619,6 @@
}
/**
- * Expands the Instances table (if needed) and the BusyBits table.
- * Acquires the database lock and calls {@link #acquireBusyBitRangeLocked}.
- */
- private void acquireBusyBitRange(final int startDay, final int endDay) {
- mDb.beginTransaction();
- try {
- acquireBusyBitRangeLocked(startDay, endDay);
- mDb.setTransactionSuccessful();
- } finally {
- mDb.endTransaction();
- }
- }
-
- /**
* Ensure that the date range given has all elements in the instance
* table. The database lock must be held when calling this method.
*
@@ -703,9 +656,8 @@
if (maxInstance == 0 || timezoneChanged) {
// Empty the Instances table and expand from scratch.
mDb.execSQL("DELETE FROM Instances;");
- mDb.execSQL("DELETE FROM BusyBits;");
if (Config.LOGV) {
- Log.v(TAG, "acquireInstanceRangeLocked() deleted Instances and Busybits,"
+ Log.v(TAG, "acquireInstanceRangeLocked() deleted Instances,"
+ " timezone changed: " + timezoneChanged);
}
expandInstanceRangeLocked(expandBegin, expandEnd, localTimezone);
@@ -750,124 +702,7 @@
// Update the bounds on the Instances table.
mMetaData.writeLocked(localTimezone, minInstance, maxInstance,
- fields.minBusyBit, fields.maxBusyBit);
- }
-
- private void acquireBusyBitRangeLocked(int firstDay, int lastDay) {
- if (firstDay > lastDay) {
- throw new IllegalArgumentException("firstDay must not be greater than lastDay");
- }
- String localTimezone = TimeZone.getDefault().getID();
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- String dbTimezone = fields.timezone;
- int minBusyBit = fields.minBusyBit;
- int maxBusyBit = fields.maxBusyBit;
- boolean timezoneChanged = (dbTimezone == null) || !dbTimezone.equals(localTimezone);
- if (firstDay >= minBusyBit && lastDay <= maxBusyBit && !timezoneChanged) {
- if (Config.LOGV) {
- Log.v(TAG, "acquireBusyBitRangeLocked() no expansion needed");
- }
- return;
- }
-
- // Avoid gaps in the BusyBit table and avoid recomputing the busy bits
- // that are already in the table. If the busy bit range has been cleared,
- // don't bother checking.
- if (maxBusyBit != 0) {
- if (firstDay > maxBusyBit) {
- firstDay = maxBusyBit;
- } else if (lastDay < minBusyBit) {
- lastDay = minBusyBit;
- } else if (firstDay < minBusyBit && lastDay <= maxBusyBit) {
- lastDay = minBusyBit;
- } else if (lastDay > maxBusyBit && firstDay >= minBusyBit) {
- firstDay = maxBusyBit;
- }
- }
-
- // Allocate space for the busy bits, one 32-bit integer for each day.
- int numDays = lastDay - firstDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- // Convert the first and last Julian day range to a range that uses
- // UTC milliseconds.
- Time time = new Time();
- long begin = time.setJulianDay(firstDay);
-
- // We add one to lastDay because the time is set to 12am on the given
- // Julian day and we want to include all the events on the last day.
- long end = time.setJulianDay(lastDay + 1);
-
- // Make sure the Instances table includes events in the range
- // [begin, end].
- acquireInstanceRange(begin, end, true /* use minimum expansion window */);
-
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- qb.setTables("Instances INNER JOIN Events ON (Instances.event_id=Events._id) " +
- "INNER JOIN Calendars ON (Events.calendar_id = Calendars._id)");
- qb.setProjectionMap(sInstancesProjectionMap);
- qb.appendWhere("begin <= ");
- qb.appendWhere(String.valueOf(end));
- qb.appendWhere(" AND end >= ");
- qb.appendWhere(String.valueOf(begin));
- qb.appendWhere(" AND ");
- qb.appendWhere(Instances.SELECTED);
- qb.appendWhere("=1");
-
- // Get all the instances that overlap the range [begin,end]
- Cursor cursor = qb.query(mDb, sInstancesProjection, null /* selection */,
- null /* selectionArgs */, null /* groupBy */,
- null /* having */, null /* sortOrder */);
- int count = 0;
- try {
- count = cursor.getCount();
- while (cursor.moveToNext()) {
- int startDay = cursor.getInt(INSTANCES_INDEX_START_DAY);
- int endDay = cursor.getInt(INSTANCES_INDEX_END_DAY);
- int startMinute = cursor.getInt(INSTANCES_INDEX_START_MINUTE);
- int endMinute = cursor.getInt(INSTANCES_INDEX_END_MINUTE);
- boolean allDay = cursor.getInt(INSTANCES_INDEX_ALL_DAY) != 0;
- fillBusyBits(firstDay, startDay, endDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- if (count == 0) {
- return;
- }
-
- // Read the busybit range again because that may have changed when we
- // called acquireInstanceRange().
- fields = mMetaData.getFieldsLocked();
- minBusyBit = fields.minBusyBit;
- maxBusyBit = fields.maxBusyBit;
-
- // If the busybit range was cleared, then delete all the entries.
- if (maxBusyBit == 0) {
- mDb.execSQL("DELETE FROM BusyBits;");
- }
-
- // Merge the busy bits with the database.
- mergeBusyBits(firstDay, lastDay, busybits, allDayCounts);
- if (maxBusyBit == 0) {
- minBusyBit = firstDay;
- maxBusyBit = lastDay;
- } else {
- if (firstDay < minBusyBit) {
- minBusyBit = firstDay;
- }
- if (lastDay > maxBusyBit) {
- maxBusyBit = lastDay;
- }
- }
- // Update the busy bit range
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- minBusyBit, maxBusyBit);
+ 0 /*unused*/, 0 /*unused*/);
}
private static final String[] EXPAND_COLUMNS = new String[] {
@@ -1311,351 +1146,6 @@
values.put(Instances.END_MINUTE, endMinute);
}
- private void fillBusyBits(int minDay, int startDay, int endDay, int startMinute,
- int endMinute, boolean allDay, int[] busybits, int[] allDayCounts) {
-
- // The startDay can be less than the minDay if we have an event
- // that starts earlier than the time range we are interested in.
- // In that case, we ignore the time range that falls outside the
- // the range we are interested in.
- if (startDay < minDay) {
- startDay = minDay;
- startMinute = 0;
- }
-
- // Likewise, truncate the event's end day so that it doesn't go past
- // the expected range.
- int numDays = busybits.length;
- int stopDay = endDay;
- if (stopDay > minDay + numDays - 1) {
- stopDay = minDay + numDays - 1;
- }
- int dayIndex = startDay - minDay;
-
- if (allDay) {
- for (int day = startDay; day <= stopDay; day++, dayIndex++) {
- allDayCounts[dayIndex] += 1;
- }
- return;
- }
-
- for (int day = startDay; day <= stopDay; day++, dayIndex++) {
- int endTime = endMinute;
- // If the event ends on a future day, then show it extending to
- // the end of this day.
- if (endDay > day) {
- endTime = 24 * 60;
- }
-
- int startBit = startMinute / BUSYBIT_INTERVAL ;
- int endBit = (endTime + BUSYBIT_INTERVAL - 1) / BUSYBIT_INTERVAL;
- int len = endBit - startBit;
- if (len == 0) {
- len = 1;
- }
- if (len < 0 || len > 24) {
- Log.e("Cal", "fillBusyBits() error: len " + len
- + " startMinute,endTime " + startMinute + " , " + endTime
- + " startDay,endDay " + startDay + " , " + endDay);
- } else {
- int oneBits = BIT_MASKS[len];
- busybits[dayIndex] |= oneBits << startBit;
- }
-
- // Set the start minute to the beginning of the day, in
- // case this event spans multiple days.
- startMinute = 0;
- }
- }
-
- private void mergeBusyBits(int startDay, int endDay, int[] busybits, int[] allDayCounts) {
- mDb.beginTransaction();
- try {
- mergeBusyBitsLocked(startDay, endDay, busybits, allDayCounts);
- mDb.setTransactionSuccessful();
- } finally {
- mDb.endTransaction();
- }
- }
-
- private void mergeBusyBitsLocked(int startDay, int endDay, int[] busybits,
- int[] allDayCounts) {
- Cursor cursor = null;
- try {
- String selection = "day>=" + startDay + " AND day<=" + endDay;
- cursor = mDb.query("BusyBits", sBusyBitProjection, selection,
- null /* selectionArgs */, null /* groupBy */,
- null /* having */, null /* sortOrder */);
- if (cursor == null) {
- return;
- }
- while (cursor.moveToNext()) {
- int day = cursor.getInt(BUSYBIT_INDEX_DAY);
- int busy = cursor.getInt(BUSYBIT_INDEX_BUSYBITS);
- int allDayCount = cursor.getInt(BUSYBIT_INDEX_ALL_DAY_COUNT);
-
- int dayIndex = day - startDay;
- busybits[dayIndex] |= busy;
- allDayCounts[dayIndex] += allDayCount;
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
-
- // Allocate a map that we can reuse
- ContentValues values = new ContentValues();
-
- // Write the busy bits to the database
- int len = busybits.length;
- for (int dayIndex = 0; dayIndex < len; dayIndex++) {
- int busy = busybits[dayIndex];
- int allDayCount = allDayCounts[dayIndex];
- if (busy == 0 && allDayCount == 0) {
- continue;
- }
- int day = startDay + dayIndex;
-
- values.clear();
- values.put(BusyBits.DAY, day);
- values.put(BusyBits.BUSYBITS, busy);
- values.put(BusyBits.ALL_DAY_COUNT, allDayCount);
- mDb.replace("BusyBits", null, values);
- }
- }
-
- /**
- * Updates the BusyBit table when a new event is inserted into the Events
- * table. This is called after the event has been entered into the Events
- * table. If the event time is not within the date range of the current
- * BusyBits table, then the busy bits are not updated. The BusyBits
- * table is not automatically expanded to include this event.
- *
- * @param eventId the id of the newly created event
- * @param values the ContentValues for the new event
- */
- private void insertBusyBitsLocked(long eventId, ContentValues values) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // If this is a recurrence event, then the expanded Instances range
- // should be 0 because this is called after updateInstancesLocked().
- // But for now check this condition and report an error if it occurs.
- // In the future, we could even support recurring events by
- // expanding them here and updating the busy bits for each instance.
- if (isRecurrenceEvent(values)) {
- Log.e(TAG, "insertBusyBitsLocked(): unexpected recurrence event\n");
- return;
- }
-
- long dtstartMillis = values.getAsLong(Events.DTSTART);
- Long dtendMillis = values.getAsLong(Events.DTEND);
- if (dtendMillis == null) {
- dtendMillis = dtstartMillis;
- }
-
- boolean allDay = false;
- Integer allDayInteger = values.getAsInteger(Events.ALL_DAY);
- if (allDayInteger != null) {
- allDay = allDayInteger != 0;
- }
-
- Time time = new Time();
- if (allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- }
-
- ContentValues busyValues = new ContentValues();
- computeTimezoneDependentFields(dtstartMillis, dtendMillis, time, busyValues);
-
- int startDay = busyValues.getAsInteger(Instances.START_DAY);
- int endDay = busyValues.getAsInteger(Instances.END_DAY);
-
- // If the event time is not in the expanded BusyBits range,
- // then return.
- if (startDay > fields.maxBusyBit || endDay < fields.minBusyBit) {
- return;
- }
-
- // Allocate space for the busy bits, one 32-bit integer for each day,
- // plus 24 bytes for the count of events that occur in each time slot.
- int numDays = endDay - startDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- int startMinute = busyValues.getAsInteger(Instances.START_MINUTE);
- int endMinute = busyValues.getAsInteger(Instances.END_MINUTE);
- fillBusyBits(startDay, startDay, endDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- mergeBusyBits(startDay, endDay, busybits, allDayCounts);
- }
-
- /**
- * Updates the busy bits for an event that is being updated. This is
- * called before the event is updated in the Events table because we need
- * to know the time of the event before it was changed.
- *
- * @param eventId the id of the event being updated
- * @param values the ContentValues for the updated event
- */
- private void updateBusyBitsLocked(long eventId, ContentValues values) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // If this is a recurring event, then clear the BusyBits table.
- if (isRecurrenceEvent(values)) {
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // If the event fields being updated don't contain the start or end
- // time, then we don't need to bother updating the BusyBits table.
- Long dtstartLong = values.getAsLong(Events.DTSTART);
- Long dtendLong = values.getAsLong(Events.DTEND);
- if (dtstartLong == null && dtendLong == null) {
- return;
- }
-
- // If the timezone has changed, then clear the busy bits table
- // and return.
- String dbTimezone = fields.timezone;
- String localTimezone = TimeZone.getDefault().getID();
- boolean timezoneChanged = (dbTimezone == null) || !dbTimezone.equals(localTimezone);
- if (timezoneChanged) {
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // Read the existing event start and end times from the Events table.
- TimeRange eventRange = readEventStartEnd(eventId);
-
- // Fill in the new start time (if missing) or the new end time (if
- // missing) from the existing event start and end times.
- long dtstartMillis;
- if (dtstartLong != null) {
- dtstartMillis = dtstartLong;
- } else {
- dtstartMillis = eventRange.begin;
- }
-
- long dtendMillis;
- if (dtendLong != null) {
- dtendMillis = dtendLong;
- } else {
- dtendMillis = eventRange.end;
- }
-
- // Compute the start and end Julian days for the event.
- Time time = new Time();
- if (eventRange.allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- }
- ContentValues busyValues = new ContentValues();
- computeTimezoneDependentFields(eventRange.begin, eventRange.end, time, busyValues);
- int oldStartDay = busyValues.getAsInteger(Instances.START_DAY);
- int oldEndDay = busyValues.getAsInteger(Instances.END_DAY);
-
- boolean allDay = false;
- Integer allDayInteger = values.getAsInteger(Events.ALL_DAY);
- if (allDayInteger != null) {
- allDay = allDayInteger != 0;
- }
-
- if (allDay) {
- time.timezone = Time.TIMEZONE_UTC;
- } else {
- time.timezone = TimeZone.getDefault().getID();
- }
-
- computeTimezoneDependentFields(dtstartMillis, dtendMillis, time, busyValues);
- int newStartDay = busyValues.getAsInteger(Instances.START_DAY);
- int newEndDay = busyValues.getAsInteger(Instances.END_DAY);
-
- // If both the old and new event times are outside the expanded
- // BusyBits table, then return.
- if ((oldStartDay > fields.maxBusyBit || oldEndDay < fields.minBusyBit)
- && (newStartDay > fields.maxBusyBit || newEndDay < fields.minBusyBit)) {
- return;
- }
-
- // If the old event time is within the expanded Instances range,
- // then clear the BusyBits table and return.
- if (oldStartDay <= fields.maxBusyBit && oldEndDay >= fields.minBusyBit) {
- // We could recompute the busy bits for the days containing the
- // old event time. For now, just clear the BusyBits table.
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- return;
- }
-
- // The new event time is within the expanded Instances range.
- // So insert the busy bits for that day (or days).
-
- // Allocate space for the busy bits, one 32-bit integer for each day,
- // plus 24 bytes for the count of events that occur in each time slot.
- int numDays = newEndDay - newStartDay + 1;
- int[] busybits = new int[numDays];
- int[] allDayCounts = new int[numDays];
-
- int startMinute = busyValues.getAsInteger(Instances.START_MINUTE);
- int endMinute = busyValues.getAsInteger(Instances.END_MINUTE);
- fillBusyBits(newStartDay, newStartDay, newEndDay, startMinute, endMinute,
- allDay, busybits, allDayCounts);
- mergeBusyBits(newStartDay, newEndDay, busybits, allDayCounts);
- }
-
- /**
- * This method is called just before an event is deleted.
- *
- * @param eventId
- */
- private void deleteBusyBitsLocked(long eventId) {
- MetaData.Fields fields = mMetaData.getFieldsLocked();
- if (fields.maxBusyBit == 0) {
- return;
- }
-
- // TODO: if the event being deleted is not a recurring event and the
- // start and end time are outside the BusyBit range, then we could
- // avoid clearing the BusyBits table. For now, always clear the
- // BusyBits table because deleting events is relatively rare.
- mMetaData.writeLocked(fields.timezone, fields.minInstance, fields.maxInstance,
- 0 /* startDay */, 0 /* endDay */);
- }
-
- // Read the start and end time for an event from the Events table.
- // Also read the "all-day" indicator.
- private TimeRange readEventStartEnd(long eventId) {
- Cursor cursor = null;
- TimeRange range = new TimeRange();
- try {
- cursor = query(ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
- new String[] { Events.DTSTART, Events.DTEND, Events.ALL_DAY },
- null /* selection */,
- null /* selectionArgs */,
- null /* sort */);
- if (cursor == null || !cursor.moveToFirst()) {
- Log.d(TAG, "Couldn't find " + eventId + " in Events table");
- return null;
- }
- range.begin = cursor.getLong(0);
- range.end = cursor.getLong(1);
- range.allDay = cursor.getInt(2) != 0;
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return range;
- }
-
@Override
public String getType(Uri url) {
int match = sUriMatcher.match(url);
@@ -1676,9 +1166,8 @@
return "vnd.android.cursor.item/calendar-alert";
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
return "vnd.android.cursor.dir/event-instance";
- case BUSYBITS:
- return "vnd.android.cursor.dir/busybits";
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
@@ -1738,7 +1227,6 @@
if (id != -1) {
updateEventRawTimesLocked(id, updatedValues);
updateInstancesLocked(updatedValues, id, true /* new event */, mDb);
- insertBusyBitsLocked(id, updatedValues);
// If we inserted a new event that specified the self-attendee
// status, then we need to add an entry to the attendees table.
@@ -1819,6 +1307,7 @@
case EXTENDED_PROPERTIES_ID:
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
throw new UnsupportedOperationException("Cannot insert into that URL: " + uri);
default:
throw new IllegalArgumentException("Unknown URL " + uri);
@@ -2333,7 +1822,6 @@
+ "doesn't support selection based deletion for type "
+ match);
}
- deleteBusyBitsLocked(id);
if (callerIsSyncAdapter) {
mDb.delete("Events", "_id = " + id, null);
@@ -2486,6 +1974,7 @@
return deleteMatchingCalendars(selection); // TODO: handle in sync adapter
case INSTANCES:
case INSTANCES_BY_DAY:
+ case EVENT_DAYS:
throw new UnsupportedOperationException("Cannot delete that URL");
default:
throw new IllegalArgumentException("Unknown URL " + uri);
@@ -2622,12 +2111,6 @@
}
int result = mDb.update("Calendars", values, "_id="+ id, null /* selectionArgs */);
- // When we change the display status of a Calendar
- // we need to update the busy bits.
- if (values.containsKey(Calendars.SELECTED) || (syncEvents != null)) {
- // Clear the BusyBits table.
- mMetaData.clearBusyBitRange();
- }
return result;
}
@@ -2670,8 +2153,6 @@
+ " in Events table is not allowed.");
}
- updateBusyBitsLocked(id, values);
-
ContentValues updatedValues = updateContentValuesFromEvent(values);
if (updatedValues == null) {
Log.w(TAG, "Could not update event.");
@@ -3236,12 +2717,12 @@
private static final int CALENDAR_ALERTS = 13;
private static final int CALENDAR_ALERTS_ID = 14;
private static final int CALENDAR_ALERTS_BY_INSTANCE = 15;
- private static final int BUSYBITS = 16;
- private static final int INSTANCES_BY_DAY = 17;
- private static final int SYNCSTATE = 18;
- private static final int SYNCSTATE_ID = 19;
- private static final int EVENT_ENTITIES = 20;
- private static final int EVENT_ENTITIES_ID = 21;
+ private static final int INSTANCES_BY_DAY = 16;
+ private static final int SYNCSTATE = 17;
+ private static final int SYNCSTATE_ID = 18;
+ private static final int EVENT_ENTITIES = 19;
+ private static final int EVENT_ENTITIES_ID = 20;
+ private static final int EVENT_DAYS = 21;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final HashMap<String, String> sInstancesProjectionMap;
@@ -3250,11 +2731,11 @@
private static final HashMap<String, String> sAttendeesProjectionMap;
private static final HashMap<String, String> sRemindersProjectionMap;
private static final HashMap<String, String> sCalendarAlertsProjectionMap;
- private static final HashMap<String, String> sBusyBitsProjectionMap;
static {
sUriMatcher.addURI("calendar", "instances/when/*/*", INSTANCES);
sUriMatcher.addURI("calendar", "instances/whenbyday/*/*", INSTANCES_BY_DAY);
+ sUriMatcher.addURI("calendar", "instances/groupbyday/*/*", EVENT_DAYS);
sUriMatcher.addURI("calendar", "events", EVENTS);
sUriMatcher.addURI("calendar", "events/#", EVENTS_ID);
sUriMatcher.addURI("calendar", "event_entities", EVENT_ENTITIES);
@@ -3271,7 +2752,6 @@
sUriMatcher.addURI("calendar", "calendar_alerts", CALENDAR_ALERTS);
sUriMatcher.addURI("calendar", "calendar_alerts/#", CALENDAR_ALERTS_ID);
sUriMatcher.addURI("calendar", "calendar_alerts/by_instance", CALENDAR_ALERTS_BY_INSTANCE);
- sUriMatcher.addURI("calendar", "busybits/when/*/*", BUSYBITS);
sUriMatcher.addURI("calendar", SyncStateContentProviderHelper.PATH, SYNCSTATE);
sUriMatcher.addURI("calendar", SyncStateContentProviderHelper.PATH + "/#", SYNCSTATE_ID);
@@ -3381,12 +2861,6 @@
sInstancesProjectionMap.put(Instances.START_MINUTE, "startMinute");
sInstancesProjectionMap.put(Instances.END_MINUTE, "endMinute");
- // BusyBits columns
- sBusyBitsProjectionMap = new HashMap<String, String>();
- sBusyBitsProjectionMap.put(BusyBits.DAY, "day");
- sBusyBitsProjectionMap.put(BusyBits.BUSYBITS, "busyBits");
- sBusyBitsProjectionMap.put(BusyBits.ALL_DAY_COUNT, "allDayCount");
-
// Attendees columns
sAttendeesProjectionMap.put(Attendees.EVENT_ID, "event_id");
sAttendeesProjectionMap.put(Attendees._ID, "Attendees._id AS _id");
diff --git a/src/com/android/providers/calendar/MetaData.java b/src/com/android/providers/calendar/MetaData.java
index ed7f9d9..ded6d4f 100644
--- a/src/com/android/providers/calendar/MetaData.java
+++ b/src/com/android/providers/calendar/MetaData.java
@@ -44,12 +44,12 @@
public int minBusyBit; // Julian start day
public int maxBusyBit; // Julian end day
}
-
+
/**
* The cached copy of the meta-data fields from the database.
*/
private Fields mFields = new Fields();
-
+
private final SQLiteOpenHelper mOpenHelper;
private boolean mInitialized;
@@ -60,24 +60,20 @@
private static final String[] sCalendarMetaDataProjection = {
CalendarMetaData.LOCAL_TIMEZONE,
CalendarMetaData.MIN_INSTANCE,
- CalendarMetaData.MAX_INSTANCE,
- CalendarMetaData.MIN_BUSYBITS,
- CalendarMetaData.MAX_BUSYBITS };
-
+ CalendarMetaData.MAX_INSTANCE};
+
private static final int METADATA_INDEX_LOCAL_TIMEZONE = 0;
private static final int METADATA_INDEX_MIN_INSTANCE = 1;
private static final int METADATA_INDEX_MAX_INSTANCE = 2;
- private static final int METADATA_INDEX_MIN_BUSYBIT = 3;
- private static final int METADATA_INDEX_MAX_BUSYBIT = 4;
-
+
public MetaData(SQLiteOpenHelper openHelper) {
mOpenHelper = openHelper;
}
-
+
/**
* Returns a copy of all the MetaData fields. This method grabs a
* database lock to read all the fields atomically.
- *
+ *
* @return a copy of all the MetaData fields.
*/
public Fields getFields() {
@@ -104,12 +100,12 @@
/**
* This method must be called only while holding a database lock.
- *
+ *
* <p>
* Returns a copy of all the MetaData fields. This method assumes
* the database lock has already been acquired.
* </p>
- *
+ *
* @return a copy of all the MetaData fields.
*/
public Fields getFieldsLocked() {
@@ -128,7 +124,7 @@
fields.maxBusyBit = mFields.maxBusyBit;
return fields;
}
-
+
/**
* Reads the meta-data for the CalendarProvider from the database and
* updates the member variables. This method executes while the database
@@ -149,8 +145,6 @@
timezone = cursor.getString(METADATA_INDEX_LOCAL_TIMEZONE);
minInstance = cursor.getLong(METADATA_INDEX_MIN_INSTANCE);
maxInstance = cursor.getLong(METADATA_INDEX_MAX_INSTANCE);
- minBusyBit = cursor.getInt(METADATA_INDEX_MIN_BUSYBIT);
- maxBusyBit = cursor.getInt(METADATA_INDEX_MAX_BUSYBIT);
}
} finally {
if (cursor != null) {
@@ -164,7 +158,7 @@
mFields.maxInstance = maxInstance;
mFields.minBusyBit = minBusyBit;
mFields.maxBusyBit = maxBusyBit;
-
+
// Mark the fields as initialized
mInitialized = true;
}
@@ -173,7 +167,7 @@
* Writes the meta-data for the CalendarProvider. The values to write are
* passed in as parameters. All of the values are updated atomically,
* including the cached copy of the meta-data.
- *
+ *
* @param timezone the local timezone used for Instance expansion
* @param begin the start of the Instance expansion in UTC milliseconds
* @param end the end of the Instance expansion in UTC milliseconds
@@ -193,13 +187,13 @@
/**
* This method must be called only while holding a database lock.
- *
+ *
* <p>
* Writes the meta-data for the CalendarProvider. The values to write are
* passed in as parameters. All of the values are updated atomically,
* including the cached copy of the meta-data.
* </p>
- *
+ *
* @param timezone the local timezone used for Instance expansion
* @param begin the start of the Instance expansion in UTC milliseconds
* @param end the end of the Instance expansion in UTC milliseconds
@@ -212,8 +206,6 @@
values.put(CalendarMetaData.LOCAL_TIMEZONE, timezone);
values.put(CalendarMetaData.MIN_INSTANCE, begin);
values.put(CalendarMetaData.MAX_INSTANCE, end);
- values.put(CalendarMetaData.MIN_BUSYBITS, startDay);
- values.put(CalendarMetaData.MAX_BUSYBITS, endDay);
// Atomically update the database and the cached members.
try {
@@ -239,7 +231,7 @@
* Clears the time range for the Instances table. The rows in the
* Instances table will be deleted (and regenerated) the next time
* that the Instances table is queried.
- *
+ *
* Also clears the time range for the BusyBits table because that depends
* on the Instances table.
*/