tyczj
tyczj

Reputation: 73753

Calendar Instances provider source code?

I am looking through the android calendar source code for the Instances Content Provider to see how it works and gets populated.

The reason being is that I am trying to replicate its workings in my app but I have not found where it gets populated from in the source.

I know the Instances database cannot be written to but somewhere it has to be getting written to since its getting populated. I just want to see how they do some of the calculations for the values.

The only thing I can find about the Instances is this but that does not tell me what I want to know and just tells me the the query and the uri's not the code behind the values.

does anyone know where it is?

Upvotes: 2

Views: 1172

Answers (2)

A machan
A machan

Reputation: 809

Instances are being populated in "updateInstancesLocked" method in CalendarInstancesHelper.java. Also please check "performInstanceExpansion" method in the same file.

Link to the above mention method in GrepCode

I have provided the snippet of the method below

  /**
 * Updates the instances table when an event is added or updated.
 * @param values The new values of the event.
 * @param rowId The database row id of the event.
 * @param newEvent true if the event is new.
 * @param db The database
 */
private void updateInstancesLocked(ContentValues values,
        long rowId,
        boolean newEvent,
        SQLiteDatabase db) {

    // If there are no expanded Instances, then return.
    MetaData.Fields fields = mMetaData.getFieldsLocked();
    if (fields.maxInstance == 0) {
        return;
    }

    Long dtstartMillis = values.getAsLong(Events.DTSTART);
    if (dtstartMillis == null) {
        if (newEvent) {
            // must be present for a new event.
            throw new RuntimeException("DTSTART missing.");
        }
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Missing DTSTART.  No need to update instance.");
        }
        return;
    }

    Long lastDateMillis = values.getAsLong(Events.LAST_DATE);
    Long originalInstanceTime = values.getAsLong(Events.ORIGINAL_INSTANCE_TIME);

    if (!newEvent) {
        // Want to do this for regular event, recurrence, or exception.
        // For recurrence or exception, more deletion may happen below if we
        // do an instance expansion.  This deletion will suffice if the exception
        // is moved outside the window, for instance.
        db.delete("Instances", "event_id=?", new String[] {String.valueOf(rowId)});
    }

    String rrule = values.getAsString(Events.RRULE);
    String rdate = values.getAsString(Events.RDATE);
    String originalEvent = values.getAsString(Events.ORIGINAL_EVENT);
    if (isRecurrenceEvent(rrule, rdate, originalEvent))  {
        // The recurrence or exception needs to be (re-)expanded if:
        // a) Exception or recurrence that falls inside window
        boolean insideWindow = dtstartMillis <= fields.maxInstance &&
                (lastDateMillis == null || lastDateMillis >= fields.minInstance);
        // b) Exception that affects instance inside window
        // These conditions match the query in getEntries
        //  See getEntries comment for explanation of subtracting 1 week.
        boolean affectsWindow = originalInstanceTime != null &&
                originalInstanceTime <= fields.maxInstance &&
                originalInstanceTime >= fields.minInstance - MAX_ASSUMED_DURATION;
        if (insideWindow || affectsWindow) {
            updateRecurrenceInstancesLocked(values, rowId, db);
        }
        // TODO: an exception creation or update could be optimized by
        // updating just the affected instances, instead of regenerating
        // the recurrence.
        return;
    }

    Long dtendMillis = values.getAsLong(Events.DTEND);
    if (dtendMillis == null) {
        dtendMillis = dtstartMillis;
    }

    // if the event is in the expanded range, insert
    // into the instances table.
    // TODO: deal with durations.  currently, durations are only used in
    // recurrences.

    if (dtstartMillis <= fields.maxInstance && dtendMillis >= fields.minInstance) {
        ContentValues instanceValues = new ContentValues();
        instanceValues.put(Instances.EVENT_ID, rowId);
        instanceValues.put(Instances.BEGIN, dtstartMillis);
        instanceValues.put(Instances.END, dtendMillis);

        boolean allDay = false;
        Integer allDayInteger = values.getAsInteger(Events.ALL_DAY);
        if (allDayInteger != null) {
            allDay = allDayInteger != 0;
        }

        // Update the timezone-dependent fields.
        Time local = new Time();
        if (allDay) {
            local.timezone = Time.TIMEZONE_UTC;
        } else {
            local.timezone = fields.timezone;
        }

        computeTimezoneDependentFields(dtstartMillis, dtendMillis, local, instanceValues);
        mDbHelper.instancesInsert(instanceValues);
    }
}

Hope this helps!!!

Let me know if you are expecting something different

Upvotes: 0

Martin Nordholts
Martin Nordholts

Reputation: 10358

The code that handles Content Provider URIs that start with content://com.android.calendar/instances/* is in packages/providers/CalendarProvider/src/com/android/providers/calendar/CalendarProvider2.java.

From that file it is possible to look up further implementation details. For example, a lot of the initialization code, like CREATE TABLE calls, is in CalendarDatabaseHelper.java in the same project.

I hope this helps!

Upvotes: 1

Related Questions