/*
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** See the License for the specific language governing permissions and
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** limitations under the License.
*/

package com.android.providers.calendar;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Binder;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.BaseColumns;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.CalendarAlerts;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Colors;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Instances;
import android.provider.CalendarContract.Reminders;
import android.provider.CalendarContract.SyncState;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;
import android.util.TimeUtils;

import com.android.calendarcommon2.DateException;
import com.android.calendarcommon2.Duration;
import com.android.calendarcommon2.EventRecurrence;
import com.android.calendarcommon2.RecurrenceProcessor;
import com.android.calendarcommon2.RecurrenceSet;
import com.android.internal.util.ProviderAccessStats;
import com.android.providers.calendar.CalendarDatabaseHelper.Tables;
import com.android.providers.calendar.CalendarDatabaseHelper.Views;
import com.android.providers.calendar.enterprise.CrossProfileCalendarHelper;

import com.google.android.collect.Sets;
import com.google.common.annotations.VisibleForTesting;

import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Calendar content provider. The contract between this provider and applications
 * is defined in {@link android.provider.CalendarContract}.
 */
public class CalendarProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener {


    protected static final String TAG = "CalendarProvider2";
    // Turn on for b/22449592
    static final boolean DEBUG_INSTANCES = Log.isLoggable(TAG, Log.DEBUG);

    private static final String TIMEZONE_GMT = "GMT";
    private static final String ACCOUNT_SELECTION_PREFIX = Calendars.ACCOUNT_NAME + "=? AND "
            + Calendars.ACCOUNT_TYPE + "=?";

    protected static final boolean PROFILE = false;
    private static final boolean MULTIPLE_ATTENDEES_PER_EVENT = true;

    private static final String[] ID_ONLY_PROJECTION =
            new String[] {Events._ID};

    private static final String[] EVENTS_PROJECTION = new String[] {
            Events._SYNC_ID,
            Events.RRULE,
            Events.RDATE,
            Events.ORIGINAL_ID,
            Events.ORIGINAL_SYNC_ID,
    };

    private static final int EVENTS_SYNC_ID_INDEX = 0;
    private static final int EVENTS_RRULE_INDEX = 1;
    private static final int EVENTS_RDATE_INDEX = 2;
    private static final int EVENTS_ORIGINAL_ID_INDEX = 3;
    private static final int EVENTS_ORIGINAL_SYNC_ID_INDEX = 4;

    private static final String[] COLORS_PROJECTION = new String[] {
        Colors.ACCOUNT_NAME,
        Colors.ACCOUNT_TYPE,
        Colors.COLOR_TYPE,
        Colors.COLOR_KEY,
        Colors.COLOR,
    };
    private static final int COLORS_ACCOUNT_NAME_INDEX = 0;
    private static final int COLORS_ACCOUNT_TYPE_INDEX = 1;
    private static final int COLORS_COLOR_TYPE_INDEX = 2;
    private static final int COLORS_COLOR_INDEX_INDEX = 3;
    private static final int COLORS_COLOR_INDEX = 4;

    private static final String COLOR_FULL_SELECTION = Colors.ACCOUNT_NAME + "=? AND "
            + Colors.ACCOUNT_TYPE + "=? AND " + Colors.COLOR_TYPE + "=? AND " + Colors.COLOR_KEY
            + "=?";

    private static final String GENERIC_ACCOUNT_NAME = Calendars.ACCOUNT_NAME;
    private static final String GENERIC_ACCOUNT_TYPE = Calendars.ACCOUNT_TYPE;
    private static final String[] ACCOUNT_PROJECTION = new String[] {
        GENERIC_ACCOUNT_NAME,
        GENERIC_ACCOUNT_TYPE,
    };
    private static final int ACCOUNT_NAME_INDEX = 0;
    private static final int ACCOUNT_TYPE_INDEX = 1;

    // many tables have _id and event_id; pick a representative version to use as our generic
    private static final String GENERIC_ID = Attendees._ID;
    private static final String GENERIC_EVENT_ID = Attendees.EVENT_ID;

    private static final String[] ID_PROJECTION = new String[] {
            GENERIC_ID,
            GENERIC_EVENT_ID,
    };
    private static final int ID_INDEX = 0;
    private static final int EVENT_ID_INDEX = 1;

    /**
     * Projection to query for correcting times in allDay events.
     */
    private static final String[] ALLDAY_TIME_PROJECTION = new String[] {
        Events._ID,
        Events.DTSTART,
        Events.DTEND,
        Events.DURATION
    };
    private static final int ALLDAY_ID_INDEX = 0;
    private static final int ALLDAY_DTSTART_INDEX = 1;
    private static final int ALLDAY_DTEND_INDEX = 2;
    private static final int ALLDAY_DURATION_INDEX = 3;

    private static final int DAY_IN_SECONDS = 24 * 60 * 60;

    /**
     * The cached copy of the CalendarMetaData database table.
     * Make this "package private" instead of "private" so that test code
     * can access it.
     */
    MetaData mMetaData;
    CalendarCache mCalendarCache;

    private CalendarDatabaseHelper mDbHelper;
    private CalendarInstancesHelper mInstancesHelper;

    protected CrossProfileCalendarHelper mCrossProfileCalendarHelper;

    private static final String SQL_SELECT_EVENTSRAWTIMES = "SELECT " +
            CalendarContract.EventsRawTimes.EVENT_ID + ", " +
            CalendarContract.EventsRawTimes.DTSTART_2445 + ", " +
            CalendarContract.EventsRawTimes.DTEND_2445 + ", " +
            Events.EVENT_TIMEZONE +
            " FROM " +
            Tables.EVENTS_RAW_TIMES + ", " +
            Tables.EVENTS +
            " WHERE " +
            CalendarContract.EventsRawTimes.EVENT_ID + " = " + Tables.EVENTS + "." + Events._ID;

    private static final String SQL_UPDATE_EVENT_SET_DIRTY_AND_MUTATORS = "UPDATE " +
            Tables.EVENTS + " SET " +
            Events.DIRTY + "=1," +
            Events.MUTATORS + "=? " +
            " WHERE " + Events._ID + "=?";

    private static final String SQL_QUERY_EVENT_MUTATORS = "SELECT " + Events.MUTATORS +
            " FROM " + Tables.EVENTS +
            " WHERE " + Events._ID + "=?";

    private static final String SQL_WHERE_CALENDAR_COLOR = Calendars.ACCOUNT_NAME + "=? AND "
            + Calendars.ACCOUNT_TYPE + "=? AND " + Calendars.CALENDAR_COLOR_KEY + "=?";

    private static final String SQL_WHERE_EVENT_COLOR = "calendar_id in (SELECT _id from "
            + Tables.CALENDARS + " WHERE " + Events.ACCOUNT_NAME + "=? AND " + Events.ACCOUNT_TYPE
            + "=?) AND " + Events.EVENT_COLOR_KEY + "=?";

    protected static final String SQL_WHERE_ID = GENERIC_ID + "=?";
    private static final String SQL_WHERE_EVENT_ID = GENERIC_EVENT_ID + "=?";
    private static final String SQL_WHERE_ORIGINAL_ID = Events.ORIGINAL_ID + "=?";
    private static final String SQL_WHERE_ORIGINAL_ID_NO_SYNC_ID = Events.ORIGINAL_ID +
            "=? AND " + Events._SYNC_ID + " IS NULL";

    private static final String SQL_WHERE_ATTENDEE_BASE =
            Tables.EVENTS + "." + Events._ID + "=" + Tables.ATTENDEES + "." + Attendees.EVENT_ID
            + " AND " +
            Tables.EVENTS + "." + Events.CALENDAR_ID + "=" + Tables.CALENDARS + "." + Calendars._ID;

    private static final String SQL_WHERE_ATTENDEES_ID =
            Tables.ATTENDEES + "." + Attendees._ID + "=? AND " + SQL_WHERE_ATTENDEE_BASE;

    private static final String SQL_WHERE_REMINDERS_ID =
            Tables.REMINDERS + "." + Reminders._ID + "=? AND " +
            Tables.EVENTS + "." + Events._ID + "=" + Tables.REMINDERS + "." + Reminders.EVENT_ID +
            " AND " +
            Tables.EVENTS + "." + Events.CALENDAR_ID + "=" + Tables.CALENDARS + "." + Calendars._ID;

    private static final String SQL_WHERE_CALENDAR_ALERT =
            Views.EVENTS + "." + Events._ID + "=" +
                    Tables.CALENDAR_ALERTS + "." + CalendarAlerts.EVENT_ID;

    private static final String SQL_WHERE_CALENDAR_ALERT_ID =
            Views.EVENTS + "." + Events._ID + "=" +
                    Tables.CALENDAR_ALERTS + "." + CalendarAlerts.EVENT_ID +
            " AND " +
            Tables.CALENDAR_ALERTS + "." + CalendarAlerts._ID + "=?";

    private static final String SQL_WHERE_EXTENDED_PROPERTIES_ID =
            Tables.EXTENDED_PROPERTIES + "." + CalendarContract.ExtendedProperties._ID + "=?";

    private static final String SQL_DELETE_FROM_CALENDARS = "DELETE FROM " + Tables.CALENDARS +
                " WHERE " + Calendars.ACCOUNT_NAME + "=? AND " +
                    Calendars.ACCOUNT_TYPE + "=?";

    private static final String SQL_DELETE_FROM_COLORS = "DELETE FROM " + Tables.COLORS + " WHERE "
            + Calendars.ACCOUNT_NAME + "=? AND " + Calendars.ACCOUNT_TYPE + "=?";

    private static final String SQL_SELECT_COUNT_FOR_SYNC_ID =
            "SELECT COUNT(*) FROM " + Tables.EVENTS + " WHERE " + Events._SYNC_ID + "=?";

    // Make sure we load at least two months worth of data.
    // Client apps can load more data in a background thread.
    private static final long MINIMUM_EXPANSION_SPAN =
            2L * 31 * 24 * 60 * 60 * 1000;

    private static final String[] sCalendarsIdProjection = new String[] { Calendars._ID };
    private static final int CALENDARS_INDEX_ID = 0;

    private static final String INSTANCE_QUERY_TABLES =
        CalendarDatabaseHelper.Tables.INSTANCES + " INNER JOIN " +
        CalendarDatabaseHelper.Views.EVENTS + " AS " +
        CalendarDatabaseHelper.Tables.EVENTS +
        " ON (" + CalendarDatabaseHelper.Tables.INSTANCES + "."
        + CalendarContract.Instances.EVENT_ID + "=" +
        CalendarDatabaseHelper.Tables.EVENTS + "."
        + CalendarContract.Events._ID + ")";

    private static final String INSTANCE_SEARCH_QUERY_TABLES = "(" +
        CalendarDatabaseHelper.Tables.INSTANCES + " INNER JOIN " +
        CalendarDatabaseHelper.Views.EVENTS + " AS " +
        CalendarDatabaseHelper.Tables.EVENTS +
        " ON (" + CalendarDatabaseHelper.Tables.INSTANCES + "."
        + CalendarContract.Instances.EVENT_ID + "=" +
        CalendarDatabaseHelper.Tables.EVENTS + "."
        + CalendarContract.Events._ID + ")" + ") LEFT OUTER JOIN " +
        CalendarDatabaseHelper.Tables.ATTENDEES +
        " ON (" + CalendarDatabaseHelper.Tables.ATTENDEES + "."
        + CalendarContract.Attendees.EVENT_ID + "=" +
        CalendarDatabaseHelper.Tables.EVENTS + "."
        + CalendarContract.Events._ID + ")";

    private static final String SQL_WHERE_INSTANCES_BETWEEN_DAY =
        CalendarContract.Instances.START_DAY + "<=? AND " +
        CalendarContract.Instances.END_DAY + ">=?";

    private static final String SQL_WHERE_INSTANCES_BETWEEN =
        CalendarContract.Instances.BEGIN + "<=? AND " +
        CalendarContract.Instances.END + ">=?";

    private static final int INSTANCES_INDEX_START_DAY = 0;
    private static final int INSTANCES_INDEX_END_DAY = 1;
    private static final int INSTANCES_INDEX_START_MINUTE = 2;
    private static final int INSTANCES_INDEX_END_MINUTE = 3;
    private static final int INSTANCES_INDEX_ALL_DAY = 4;

    /**
     * The sort order is: events with an earlier start time occur first and if
     * the start times are the same, then events with a later end time occur
     * first. The later end time is ordered first so that long-running events in
     * the calendar views appear first. If the start and end times of two events
     * are the same then we sort alphabetically on the title. This isn't
     * required for correctness, it just adds a nice touch.
     */
    public static final String SORT_CALENDAR_VIEW = "begin ASC, end DESC, title ASC";

    /**
     * A regex for describing how we split search queries into tokens. Keeps
     * quoted phrases as one token. "one \"two three\"" ==> ["one" "two three"]
     */
    private static final Pattern SEARCH_TOKEN_PATTERN =
        Pattern.compile("[^\\s\"'.?!,]+|" // first part matches unquoted words
                      + "\"([^\"]*)\"");  // second part matches quoted phrases
    /**
     * A special character that was use to escape potentially problematic
     * characters in search queries.
     *
     * Note: do not use backslash for this, as it interferes with the regex
     * escaping mechanism.
     */
    private static final String SEARCH_ESCAPE_CHAR = "#";

    /**
     * A regex for matching any characters in an incoming search query that we
     * need to escape with {@link #SEARCH_ESCAPE_CHAR}, including the escape
     * character itself.
     */
    private static final Pattern SEARCH_ESCAPE_PATTERN =
        Pattern.compile("([%_" + SEARCH_ESCAPE_CHAR + "])");

    /**
     * Alias used for aggregate concatenation of attendee e-mails when grouping
     * attendees by instance.
     */
    private static final String ATTENDEES_EMAIL_CONCAT =
        "group_concat(" + CalendarContract.Attendees.ATTENDEE_EMAIL + ")";

    /**
     * Alias used for aggregate concatenation of attendee names when grouping
     * attendees by instance.
     */
    private static final String ATTENDEES_NAME_CONCAT =
        "group_concat(" + CalendarContract.Attendees.ATTENDEE_NAME + ")";

    private static final String[] SEARCH_COLUMNS = new String[] {
        CalendarContract.Events.TITLE,
        CalendarContract.Events.DESCRIPTION,
        CalendarContract.Events.EVENT_LOCATION,
        ATTENDEES_EMAIL_CONCAT,
        ATTENDEES_NAME_CONCAT
    };

    /**
     * Arbitrary integer that we assign to the messages that we send to this
     * thread's handler, indicating that these are requests to send an update
     * notification intent.
     */
    private static final int UPDATE_BROADCAST_MSG = 1;

    /**
     * Any requests to send a PROVIDER_CHANGED intent will be collapsed over
     * this window, to prevent spamming too many intents at once.
     */
    private static final long UPDATE_BROADCAST_TIMEOUT_MILLIS =
        DateUtils.SECOND_IN_MILLIS;

    private static final long SYNC_UPDATE_BROADCAST_TIMEOUT_MILLIS =
        30 * DateUtils.SECOND_IN_MILLIS;

    private static final HashSet<String> ALLOWED_URI_PARAMETERS = Sets.newHashSet(
            CalendarContract.CALLER_IS_SYNCADAPTER,
            CalendarContract.EventsEntity.ACCOUNT_NAME,
            CalendarContract.EventsEntity.ACCOUNT_TYPE);

    /** Set of columns allowed to be altered when creating an exception to a recurring event. */
    private static final HashSet<String> ALLOWED_IN_EXCEPTION = new HashSet<String>();
    static {
        // _id, _sync_account, _sync_account_type, dirty, _sync_mark, calendar_id
        ALLOWED_IN_EXCEPTION.add(Events._SYNC_ID);
        ALLOWED_IN_EXCEPTION.add(Events.SYNC_DATA1);
        ALLOWED_IN_EXCEPTION.add(Events.SYNC_DATA7);
        ALLOWED_IN_EXCEPTION.add(Events.SYNC_DATA3);
        ALLOWED_IN_EXCEPTION.add(Events.TITLE);
        ALLOWED_IN_EXCEPTION.add(Events.EVENT_LOCATION);
        ALLOWED_IN_EXCEPTION.add(Events.DESCRIPTION);
        ALLOWED_IN_EXCEPTION.add(Events.EVENT_COLOR);
        ALLOWED_IN_EXCEPTION.add(Events.EVENT_COLOR_KEY);
        ALLOWED_IN_EXCEPTION.add(Events.STATUS);
        ALLOWED_IN_EXCEPTION.add(Events.SELF_ATTENDEE_STATUS);
        ALLOWED_IN_EXCEPTION.add(Events.SYNC_DATA6);
        ALLOWED_IN_EXCEPTION.add(Events.DTSTART);
        // dtend -- set from duration as part of creating the exception
        ALLOWED_IN_EXCEPTION.add(Events.EVENT_TIMEZONE);
        ALLOWED_IN_EXCEPTION.add(Events.EVENT_END_TIMEZONE);
        ALLOWED_IN_EXCEPTION.add(Events.DURATION);
        ALLOWED_IN_EXCEPTION.add(Events.ALL_DAY);
        ALLOWED_IN_EXCEPTION.add(Events.ACCESS_LEVEL);
        ALLOWED_IN_EXCEPTION.add(Events.AVAILABILITY);
        ALLOWED_IN_EXCEPTION.add(Events.HAS_ALARM);
        ALLOWED_IN_EXCEPTION.add(Events.HAS_EXTENDED_PROPERTIES);
        ALLOWED_IN_EXCEPTION.add(Events.RRULE);
        ALLOWED_IN_EXCEPTION.add(Events.RDATE);
        ALLOWED_IN_EXCEPTION.add(Events.EXRULE);
        ALLOWED_IN_EXCEPTION.add(Events.EXDATE);
        ALLOWED_IN_EXCEPTION.add(Events.ORIGINAL_SYNC_ID);
        ALLOWED_IN_EXCEPTION.add(Events.ORIGINAL_INSTANCE_TIME);
        // originalAllDay, lastDate
        ALLOWED_IN_EXCEPTION.add(Events.HAS_ATTENDEE_DATA);
        ALLOWED_IN_EXCEPTION.add(Events.GUESTS_CAN_MODIFY);
        ALLOWED_IN_EXCEPTION.add(Events.GUESTS_CAN_INVITE_OTHERS);
        ALLOWED_IN_EXCEPTION.add(Events.GUESTS_CAN_SEE_GUESTS);
        ALLOWED_IN_EXCEPTION.add(Events.ORGANIZER);
        ALLOWED_IN_EXCEPTION.add(Events.CUSTOM_APP_PACKAGE);
        ALLOWED_IN_EXCEPTION.add(Events.CUSTOM_APP_URI);
        ALLOWED_IN_EXCEPTION.add(Events.UID_2445);
        // deleted, original_id, alerts
    }

    /** Don't clone these from the base event into the exception event. */
    private static final String[] DONT_CLONE_INTO_EXCEPTION = {
        Events._SYNC_ID,
        Events.SYNC_DATA1,
        Events.SYNC_DATA2,
        Events.SYNC_DATA3,
        Events.SYNC_DATA4,
        Events.SYNC_DATA5,
        Events.SYNC_DATA6,
        Events.SYNC_DATA7,
        Events.SYNC_DATA8,
        Events.SYNC_DATA9,
        Events.SYNC_DATA10,
    };

    /** set to 'true' to enable debug logging for recurrence exception code */
    private static final boolean DEBUG_EXCEPTION = false;
    
    private static final String SELECTION_PRIMARY_CALENDAR =
            Calendars.IS_PRIMARY + "= 1"
                    + " OR " + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT;

    private final ThreadLocal<Boolean> mCallingPackageErrorLogged = new ThreadLocal<Boolean>();

    private Context mContext;
    private ContentResolver mContentResolver;

    @VisibleForTesting
    protected CalendarAlarmManager mCalendarAlarm;

    private final ThreadLocal<Integer> mCallingUid = new ThreadLocal<>();
    private final ProviderAccessStats mStats = new ProviderAccessStats();

    private int mParentUserId;

    /**
     * Listens for timezone changes and disk-no-longer-full events
     */
    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onReceive() " + action);
            }
            if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
                updateTimezoneDependentFields();
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
            } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                // Try to clean up if things were screwy due to a full disk
                updateTimezoneDependentFields();
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
            } else if (Intent.ACTION_TIME_CHANGED.equals(action)) {
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
            }
        }
    };

    /* Visible for testing */
    @Override
    protected CalendarDatabaseHelper getDatabaseHelper(final Context context) {
        return CalendarDatabaseHelper.getInstance(context);
    }

    @Override
    public void shutdown() {
        if (mDbHelper != null) {
            mDbHelper.close();
            mDbHelper = null;
            mDb = null;
        }
    }

    @Override
    public boolean onCreate() {
        super.onCreate();
        setAppOps(AppOpsManager.OP_READ_CALENDAR, AppOpsManager.OP_WRITE_CALENDAR);
        try {
            return initialize();
        } catch (RuntimeException e) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "Cannot start provider", e);
            }
            return false;
        }
    }

    private boolean initialize() {
        mContext = getContext();
        mContentResolver = mContext.getContentResolver();

        mDbHelper = (CalendarDatabaseHelper)getDatabaseHelper();
        mDb = mDbHelper.getWritableDatabase();

        mMetaData = new MetaData(mDbHelper);
        mInstancesHelper = new CalendarInstancesHelper(mDbHelper, mMetaData);

        // Register for Intent broadcasts
        IntentFilter filter = new IntentFilter();

        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
        filter.addAction(Intent.ACTION_TIME_CHANGED);

        // We don't ever unregister this because this thread always wants
        // to receive notifications, even in the background.  And if this
        // thread is killed then the whole process will be killed and the
        // memory resources will be reclaimed.
        mContext.registerReceiver(mIntentReceiver, filter);

        mCalendarCache = new CalendarCache(mDbHelper);

        // Unit test overrides this method to get a mock helper.
        initCrossProfileCalendarHelper();

        // This is pulled out for testing
        initCalendarAlarm();

        mParentUserId = getParentUserId();

        postInitialize();

        return true;
    }

    @VisibleForTesting
    protected void initCrossProfileCalendarHelper() {
        mCrossProfileCalendarHelper = new CrossProfileCalendarHelper(mContext);
    }

    protected void initCalendarAlarm() {
        mCalendarAlarm = getOrCreateCalendarAlarmManager();
    }

    synchronized CalendarAlarmManager getOrCreateCalendarAlarmManager() {
        if (mCalendarAlarm == null) {
            mCalendarAlarm = new CalendarAlarmManager(mContext);
            Log.i(TAG, "Created " + mCalendarAlarm + "(" + this + ")");
        }
        return mCalendarAlarm;
    }

    protected void postInitialize() {
        Thread thread = new PostInitializeThread();
        thread.start();
    }

    private class PostInitializeThread extends Thread {
        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            verifyAccounts();

            try {
                doUpdateTimezoneDependentFields();
            } catch (IllegalStateException e) {
                // Added this because tests would fail if the provider is
                // closed by the time this is executed

                // Nothing actionable here anyways.
            }
        }
    }

    private void verifyAccounts() {
        AccountManager.get(getContext()).addOnAccountsUpdatedListener(this, null, false);
        removeStaleAccounts(AccountManager.get(getContext()).getAccounts());
    }


    /**
     * This creates a background thread to check the timezone and update
     * the timezone dependent fields in the Instances table if the timezone
     * has changed.
     */
    protected void updateTimezoneDependentFields() {
        Thread thread = new TimezoneCheckerThread();
        thread.start();
    }

    private class TimezoneCheckerThread extends Thread {
        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            doUpdateTimezoneDependentFields();
        }
    }

    /**
     * Check if we are in the same time zone
     */
    private boolean isLocalSameAsInstancesTimezone() {
        String localTimezone = TimeZone.getDefault().getID();
        return TextUtils.equals(mCalendarCache.readTimezoneInstances(), localTimezone);
    }

    /**
     * This method runs in a background thread.  If the timezone has changed
     * then the Instances table will be regenerated.
     */
    protected void doUpdateTimezoneDependentFields() {
        try {
            String timezoneType = mCalendarCache.readTimezoneType();
            // Nothing to do if we have the "home" timezone type (timezone is sticky)
            if (timezoneType != null && timezoneType.equals(CalendarCache.TIMEZONE_TYPE_HOME)) {
                return;
            }
            // We are here in "auto" mode, the timezone is coming from the device
            if (! isSameTimezoneDatabaseVersion()) {
                String localTimezone = TimeZone.getDefault().getID();
                doProcessEventRawTimes(localTimezone, TimeUtils.getTimeZoneDatabaseVersion());
            }
            if (isLocalSameAsInstancesTimezone()) {
                // Even if the timezone hasn't changed, check for missed alarms.
                // This code executes when the CalendarProvider2 is created and
                // helps to catch missed alarms when the Calendar process is
                // killed (because of low-memory conditions) and then restarted.
                mCalendarAlarm.rescheduleMissedAlarms();
            }
        } catch (SQLException e) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "doUpdateTimezoneDependentFields() failed", e);
            }
            try {
                // Clear at least the in-memory data (and if possible the
                // database fields) to force a re-computation of Instances.
                mMetaData.clearInstanceRange();
            } catch (SQLException e2) {
                if (Log.isLoggable(TAG, Log.ERROR)) {
                    Log.e(TAG, "clearInstanceRange() also failed: " + e2);
                }
            }
        }
    }

    protected void doProcessEventRawTimes(String localTimezone, String timeZoneDatabaseVersion) {
        mDb.beginTransaction();
        try {
            updateEventsStartEndFromEventRawTimesLocked();
            updateTimezoneDatabaseVersion(timeZoneDatabaseVersion);
            mCalendarCache.writeTimezoneInstances(localTimezone);
            regenerateInstancesTable();
            mDb.setTransactionSuccessful();
        } finally {
            mDb.endTransaction();
        }
    }

    private void updateEventsStartEndFromEventRawTimesLocked() {
        Cursor cursor = mDb.rawQuery(SQL_SELECT_EVENTSRAWTIMES, null /* selection args */);
        try {
            while (cursor.moveToNext()) {
                long eventId = cursor.getLong(0);
                String dtStart2445 = cursor.getString(1);
                String dtEnd2445 = cursor.getString(2);
                String eventTimezone = cursor.getString(3);
                if (dtStart2445 == null && dtEnd2445 == null) {
                    if (Log.isLoggable(TAG, Log.ERROR)) {
                        Log.e(TAG, "Event " + eventId + " has dtStart2445 and dtEnd2445 null "
                                + "at the same time in EventsRawTimes!");
                    }
                    continue;
                }
                updateEventsStartEndLocked(eventId,
                        eventTimezone,
                        dtStart2445,
                        dtEnd2445);
            }
        } finally {
            cursor.close();
            cursor = null;
        }
    }

    private long get2445ToMillis(String timezone, String dt2445) {
        if (null == dt2445) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Cannot parse null RFC2445 date");
            }
            return 0;
        }
        Time time = (timezone != null) ? new Time(timezone) : new Time();
        try {
            time.parse(dt2445);
        } catch (TimeFormatException e) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "Cannot parse RFC2445 date " + dt2445);
            }
            return 0;
        }
        return time.toMillis(true /* ignore DST */);
    }

    private void updateEventsStartEndLocked(long eventId,
            String timezone, String dtStart2445, String dtEnd2445) {

        ContentValues values = new ContentValues();
        values.put(Events.DTSTART, get2445ToMillis(timezone, dtStart2445));
        values.put(Events.DTEND, get2445ToMillis(timezone, dtEnd2445));

        int result = mDb.update(Tables.EVENTS, values, SQL_WHERE_ID,
                new String[] {String.valueOf(eventId)});
        if (0 == result) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Could not update Events table with values " + values);
            }
        }
    }

    private void updateTimezoneDatabaseVersion(String timeZoneDatabaseVersion) {
        try {
            mCalendarCache.writeTimezoneDatabaseVersion(timeZoneDatabaseVersion);
        } catch (CalendarCache.CacheException e) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "Could not write timezone database version in the cache");
            }
        }
    }

    /**
     * Check if the time zone database version is the same as the cached one
     */
    protected boolean isSameTimezoneDatabaseVersion() {
        String timezoneDatabaseVersion = mCalendarCache.readTimezoneDatabaseVersion();
        if (timezoneDatabaseVersion == null) {
            return false;
        }
        return TextUtils.equals(timezoneDatabaseVersion, TimeUtils.getTimeZoneDatabaseVersion());
    }

    @VisibleForTesting
    protected String getTimezoneDatabaseVersion() {
        String timezoneDatabaseVersion = mCalendarCache.readTimezoneDatabaseVersion();
        if (timezoneDatabaseVersion == null) {
            return "";
        }
        if (Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, "timezoneDatabaseVersion = " + timezoneDatabaseVersion);
        }
        return timezoneDatabaseVersion;
    }

    private boolean isHomeTimezone() {
        final String type = mCalendarCache.readTimezoneType();
        return CalendarCache.TIMEZONE_TYPE_HOME.equals(type);
    }

    private void regenerateInstancesTable() {
        // The database timezone is different from the current timezone.
        // Regenerate the Instances table for this month.  Include events
        // starting at the beginning of this month.
        long now = System.currentTimeMillis();
        String instancesTimezone = mCalendarCache.readTimezoneInstances();
        Time time = new Time(instancesTimezone);
        time.set(now);
        time.monthDay = 1;
        time.hour = 0;
        time.minute = 0;
        time.second = 0;

        long begin = time.normalize(true);
        long end = begin + MINIMUM_EXPANSION_SPAN;

        Cursor cursor = null;
        try {
            cursor = handleInstanceQuery(new SQLiteQueryBuilder(),
                    begin, end,
                    new String[] { Instances._ID },
                    null /* selection */, null,
                    null /* sort */,
                    false /* searchByDayInsteadOfMillis */,
                    true /* force Instances deletion and expansion */,
                    instancesTimezone, isHomeTimezone());
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        mCalendarAlarm.rescheduleMissedAlarms();
    }

    @VisibleForTesting
    protected int getParentUserId() {
        final UserManager userManager = mContext.getSystemService(UserManager.class);
        final UserInfo parentUser = userManager.getProfileParent(UserHandle.myUserId());
        return parentUser == null ? UserHandle.USER_NULL : parentUser.id;
    }

    @Override
    protected void notifyChange(boolean syncToNetwork) {
        // Note that semantics are changed: notification is for CONTENT_URI, not the specific
        // Uri that was modified.
        mContentResolver.notifyChange(CalendarContract.CONTENT_URI, null, syncToNetwork);
        // If this is a managed profile CalendarProvider, notify the content observers of
        // enterprise uris in the parent profile.
        if (mParentUserId != UserHandle.USER_NULL) {
            mContentResolver.notifyChange(
                    CalendarContract.ENTERPRISE_CONTENT_URI,
                    /* observer = */ null, /* syncToNetwork = */ false, mParentUserId);
        }
    }

    /**
     * ALERT table is maintained locally so don't request a sync for changes in it
     */
    @Override
    protected boolean shouldSyncFor(Uri uri) {
        final int match = sUriMatcher.match(uri);
        return !(match == CALENDAR_ALERTS ||
                match == CALENDAR_ALERTS_ID ||
                match == CALENDAR_ALERTS_BY_INSTANCE);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        CalendarSanityChecker.getInstance(mContext).checkLastCheckTime();

        // Note don't use mCallingUid here. That's only used by mutation functions.
        final int callingUid = Binder.getCallingUid();

        mStats.incrementQueryStats(callingUid);
        final long identity = clearCallingIdentityInternal();
        try {
            return queryInternal(uri, projection, selection, selectionArgs, sortOrder);
        } finally {
            restoreCallingIdentityInternal(identity);
            mStats.finishOperation(callingUid);
        }
    }

    /**
     * @return {@link UserInfo} of the work profile user that is linked to the current user,
     * if any. {@code null} if there is no such user.
     */
    private UserInfo getWorkProfileUserInfo(Context context) {
        final UserManager userManager = context.getSystemService(UserManager.class);
        final int currentUserId = userManager.getUserHandle();

        // Check each user.
        for (UserInfo userInfo : userManager.getUsers()) {
            if (!userInfo.isManagedProfile()) {
                continue; // Not a managed user.
            }
            final UserInfo parent = userManager.getProfileParent(userInfo.id);
            if (parent == null) {
                continue; // No parent.
            }
            // Check if it's linked to the current user, and if work profile is disabled.
            if (parent.id == currentUserId
                    && !userManager.isQuietModeEnabled(UserHandle.of(userInfo.id))) {
                return userInfo;
            }
        }
        return null;
    }

    /**
     * @return the user ID of the work profile user that is linked to the current user
     * if any. {@link UserHandle#USER_NULL} if there's no such user.
     *
     * @VisibleForTesting
     */
    protected int getWorkProfileUserId() {
        final UserInfo ui = getWorkProfileUserInfo(getContext());
        return ui == null ? UserHandle.USER_NULL : ui.id;
    }

    private static Cursor createEmptyCursor(String[] projection) {
        return new MatrixCursor(projection);
    }

    /**
     * @return {@code true} if the calling package can access cross profile calendar. {@code false}
     * otherwise.
     */
    private boolean canAccessCrossProfileCalendar(int workProfileUserId) {
        // The criteria include:
        // 1. There exists a work profile linked to the current user and the work profile is not
        //    disabled.
        // 2. Profile owner of the work profile has allowed the calling package for cross
        //    profile calendar.
        // 3. CROSS_PROFILE_CALENDAR_ENABLED is turned on in Settings.
        return workProfileUserId != UserHandle.USER_NULL
                && mCrossProfileCalendarHelper.isPackageAllowedToAccessCalendar(
                        getCallingPackageName(), workProfileUserId);
    }

    private String appendPrimaryOnlyToSelection(String selection) {
        return TextUtils.isEmpty(selection)
                ? SELECTION_PRIMARY_CALENDAR
                : selection + " AND (" +  SELECTION_PRIMARY_CALENDAR + ")";
    }

    /*
     * Throw UnsupportedOperationException if
     * <p>1. Work profile doesn't exits or disabled.
     * <p>2. Calling package is not allowed to access cross profile calendar.
     * <p>3. CROSS_PROFILE_CALENDAR_ENABLED is turned off in Settings.
     */
    private Cursor queryWorkProfileProvider(Uri localUri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder,
            List<String> additionalPathSegments) {
        // If projection is not empty, check if it's valid. Otherwise fill it with all
        // allowed columns.
        projection = mCrossProfileCalendarHelper.getCalibratedProjection(
                projection, localUri);
        // Throw exception if cross profile calendar is currently not available.
        final int workProfileUserId = getWorkProfileUserId();
        if (!canAccessCrossProfileCalendar(workProfileUserId)) {
            throw new UnsupportedOperationException("Can't access cross profile for " + localUri);
        }

        Uri remoteUri = maybeAddUserId(
                localUri, workProfileUserId).buildUpon().build();
        if (additionalPathSegments != null) {
            for (String segment : additionalPathSegments) {
                remoteUri = Uri.withAppendedPath(remoteUri, segment);
            }
        }

        selection = appendPrimaryOnlyToSelection(selection);

        final Cursor cursor = getContext().getContentResolver().query(remoteUri, projection,
                selection, selectionArgs, sortOrder);
        return cursor == null ? createEmptyCursor(projection) : cursor;
    }

    private Cursor queryInternal(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "query uri - " + uri);
        }
        validateUriParameters(uri.getQueryParameterNames());
        final SQLiteDatabase db = mDbHelper.getReadableDatabase();

        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        String groupBy = null;
        String limit = null; // Not currently implemented
        String instancesTimezone;

        List<String> corpAdditionalPathSegments = null;
        final List<String> uriPathSegments = uri.getPathSegments();

        final int match = sUriMatcher.match(uri);
        switch (match) {
            case SYNCSTATE:
                return mDbHelper.getSyncState().query(db, projection, selection, selectionArgs,
                        sortOrder);
            case SYNCSTATE_ID:
                String selectionWithId = (SyncState._ID + "=?")
                    + (selection == null ? "" : " AND (" + selection + ")");
                // Prepend id to selectionArgs
                selectionArgs = insertSelectionArg(selectionArgs,
                        String.valueOf(ContentUris.parseId(uri)));
                return mDbHelper.getSyncState().query(db, projection, selectionWithId,
                        selectionArgs, sortOrder);

            case ENTERPRISE_EVENTS_ID:
                corpAdditionalPathSegments = uriPathSegments.subList(2, uriPathSegments.size());
            // Intentional fall from the above case.
            case ENTERPRISE_EVENTS:
                return queryWorkProfileProvider(Events.CONTENT_URI, projection, selection,
                        selectionArgs, sortOrder, corpAdditionalPathSegments);

            case EVENTS:
                qb.setTables(CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sEventsProjectionMap);
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                selection = appendLastSyncedColumnToSelection(selection, uri);
                break;
            case EVENTS_ID:
                qb.setTables(CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sEventsProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getPathSegments().get(1));
                qb.appendWhere(SQL_WHERE_ID);
                break;

            case EVENT_ENTITIES:
                qb.setTables(CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sEventEntitiesProjectionMap);
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                selection = appendLastSyncedColumnToSelection(selection, uri);
                break;
            case EVENT_ENTITIES_ID:
                qb.setTables(CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sEventEntitiesProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getPathSegments().get(1));
                qb.appendWhere(SQL_WHERE_ID);
                break;

            case COLORS:
                qb.setTables(Tables.COLORS);
                qb.setProjectionMap(sColorsProjectionMap);
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                break;

            case ENTERPRISE_CALENDARS_ID:
                corpAdditionalPathSegments = uriPathSegments.subList(2, uriPathSegments.size());
                // Intentional fall from the above case.
            case ENTERPRISE_CALENDARS:
                return queryWorkProfileProvider(Calendars.CONTENT_URI, projection, selection,
                        selectionArgs, sortOrder, corpAdditionalPathSegments);

            case CALENDARS:
            case CALENDAR_ENTITIES:
                qb.setTables(Tables.CALENDARS);
                qb.setProjectionMap(sCalendarsProjectionMap);
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                break;
            case CALENDARS_ID:
            case CALENDAR_ENTITIES_ID:
                qb.setTables(Tables.CALENDARS);
                qb.setProjectionMap(sCalendarsProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getPathSegments().get(1));
                qb.appendWhere(SQL_WHERE_ID);
                break;
            case INSTANCES:
            case INSTANCES_BY_DAY:
                long begin;
                long end;
                try {
                    begin = Long.valueOf(uri.getPathSegments().get(2));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse begin "
                            + uri.getPathSegments().get(2));
                }
                try {
                    end = Long.valueOf(uri.getPathSegments().get(3));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse end "
                            + uri.getPathSegments().get(3));
                }
                instancesTimezone = mCalendarCache.readTimezoneInstances();
                return handleInstanceQuery(qb, begin, end, projection, selection, selectionArgs,
                        sortOrder, match == INSTANCES_BY_DAY, false /* don't force an expansion */,
                        instancesTimezone, isHomeTimezone());
            case INSTANCES_SEARCH:
            case INSTANCES_SEARCH_BY_DAY:
                try {
                    begin = Long.valueOf(uri.getPathSegments().get(2));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse begin "
                            + uri.getPathSegments().get(2));
                }
                try {
                    end = Long.valueOf(uri.getPathSegments().get(3));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse end "
                            + uri.getPathSegments().get(3));
                }
                instancesTimezone = mCalendarCache.readTimezoneInstances();
                // this is already decoded
                String query = uri.getPathSegments().get(4);
                return handleInstanceSearchQuery(qb, begin, end, query, projection, selection,
                        selectionArgs, sortOrder, match == INSTANCES_SEARCH_BY_DAY,
                        instancesTimezone, isHomeTimezone());
            case ENTERPRISE_INSTANCES:
                corpAdditionalPathSegments = uriPathSegments.subList(3, uriPathSegments.size());
                return queryWorkProfileProvider(Instances.CONTENT_URI, projection, selection,
                        selectionArgs, sortOrder, corpAdditionalPathSegments);
            case ENTERPRISE_INSTANCES_BY_DAY:
                corpAdditionalPathSegments = uriPathSegments.subList(3, uriPathSegments.size());
                return queryWorkProfileProvider(Instances.CONTENT_BY_DAY_URI, projection, selection,
                        selectionArgs, sortOrder, corpAdditionalPathSegments);
            case ENTERPRISE_INSTANCES_SEARCH:
                corpAdditionalPathSegments = uriPathSegments.subList(3, uriPathSegments.size());
                return queryWorkProfileProvider(Instances.CONTENT_SEARCH_URI, projection, selection,
                        selectionArgs, sortOrder, corpAdditionalPathSegments);
            case ENTERPRISE_INSTANCES_SEARCH_BY_DAY:
                corpAdditionalPathSegments = uriPathSegments.subList(3, uriPathSegments.size());
                return queryWorkProfileProvider(Instances.CONTENT_SEARCH_BY_DAY_URI, projection,
                        selection, selectionArgs, sortOrder, corpAdditionalPathSegments);
            case EVENT_DAYS:
                int startDay;
                int endDay;
                try {
                    startDay = Integer.parseInt(uri.getPathSegments().get(2));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse start day "
                            + uri.getPathSegments().get(2));
                }
                try {
                    endDay = Integer.parseInt(uri.getPathSegments().get(3));
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException("Cannot parse end day "
                            + uri.getPathSegments().get(3));
                }
                instancesTimezone = mCalendarCache.readTimezoneInstances();
                return handleEventDayQuery(qb, startDay, endDay, projection, selection,
                        instancesTimezone, isHomeTimezone());
            case ATTENDEES:
                qb.setTables(Tables.ATTENDEES + ", " + Tables.EVENTS + ", " + Tables.CALENDARS);
                qb.setProjectionMap(sAttendeesProjectionMap);
                qb.appendWhere(SQL_WHERE_ATTENDEE_BASE);
                break;
            case ATTENDEES_ID:
                qb.setTables(Tables.ATTENDEES + ", " + Tables.EVENTS + ", " + Tables.CALENDARS);
                qb.setProjectionMap(sAttendeesProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getPathSegments().get(1));
                qb.appendWhere(SQL_WHERE_ATTENDEES_ID);
                break;
            case REMINDERS:
                qb.setTables(Tables.REMINDERS);
                break;
            case REMINDERS_ID:
                qb.setTables(Tables.REMINDERS + ", " + Tables.EVENTS + ", " + Tables.CALENDARS);
                qb.setProjectionMap(sRemindersProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment());
                qb.appendWhere(SQL_WHERE_REMINDERS_ID);
                break;
            case CALENDAR_ALERTS:
                qb.setTables(Tables.CALENDAR_ALERTS + ", " + CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sCalendarAlertsProjectionMap);
                qb.appendWhere(SQL_WHERE_CALENDAR_ALERT);
                break;
            case CALENDAR_ALERTS_BY_INSTANCE:
                qb.setTables(Tables.CALENDAR_ALERTS + ", " + CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sCalendarAlertsProjectionMap);
                qb.appendWhere(SQL_WHERE_CALENDAR_ALERT);
                groupBy = CalendarAlerts.EVENT_ID + "," + CalendarAlerts.BEGIN;
                break;
            case CALENDAR_ALERTS_ID:
                qb.setTables(Tables.CALENDAR_ALERTS + ", " + CalendarDatabaseHelper.Views.EVENTS);
                qb.setProjectionMap(sCalendarAlertsProjectionMap);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getLastPathSegment());
                qb.appendWhere(SQL_WHERE_CALENDAR_ALERT_ID);
                break;
            case EXTENDED_PROPERTIES:
                qb.setTables(Tables.EXTENDED_PROPERTIES);
                break;
            case EXTENDED_PROPERTIES_ID:
                qb.setTables(Tables.EXTENDED_PROPERTIES);
                selectionArgs = insertSelectionArg(selectionArgs, uri.getPathSegments().get(1));
                qb.appendWhere(SQL_WHERE_EXTENDED_PROPERTIES_ID);
                break;
            case PROVIDER_PROPERTIES:
                qb.setTables(Tables.CALENDAR_CACHE);
                qb.setProjectionMap(sCalendarCacheProjectionMap);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }

        // run the query
        return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit);
    }

    private void validateUriParameters(Set<String> queryParameterNames) {
        final Set<String> parameterNames = queryParameterNames;
        for (String parameterName : parameterNames) {
            if (!ALLOWED_URI_PARAMETERS.contains(parameterName)) {
                throw new IllegalArgumentException("Invalid URI parameter: " + parameterName);
            }
        }
    }

    private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection,
            String selection, String[] selectionArgs, String sortOrder, String groupBy,
            String limit) {

        if (projection != null && projection.length == 1
                && BaseColumns._COUNT.equals(projection[0])) {
            qb.setProjectionMap(sCountProjectionMap);
        }

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "query sql - projection: " + Arrays.toString(projection) +
                    " selection: " + selection +
                    " selectionArgs: " + Arrays.toString(selectionArgs) +
                    " sortOrder: " + sortOrder +
                    " groupBy: " + groupBy +
                    " limit: " + limit);
        }
        final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null,
                sortOrder, limit);
        if (c != null) {
            // TODO: is this the right notification Uri?
            c.setNotificationUri(mContentResolver, CalendarContract.Events.CONTENT_URI);
        }
        return c;
    }

    /*
     * Fills the Instances table, if necessary, for the given range and then
     * queries the Instances table.
     *
     * @param qb The query
     * @param rangeBegin start of range (Julian days or ms)
     * @param rangeEnd end of range (Julian days or ms)
     * @param projection The projection
     * @param selection The selection
     * @param sort How to sort
     * @param searchByDay if true, range is in Julian days, if false, range is in ms
     * @param forceExpansion force the Instance deletion and expansion if set to true
     * @param instancesTimezone timezone we need to use for computing the instances
     * @param isHomeTimezone if true, we are in the "home" timezone
     * @return
     */
    private Cursor handleInstanceQuery(SQLiteQueryBuilder qb, long rangeBegin,
            long rangeEnd, String[] projection, String selection, String[] selectionArgs,
            String sort, boolean searchByDay, boolean forceExpansion,
            String instancesTimezone, boolean isHomeTimezone) {
        mDb = mDbHelper.getWritableDatabase();
        qb.setTables(INSTANCE_QUERY_TABLES);
        qb.setProjectionMap(sInstancesProjectionMap);
        if (searchByDay) {
            // Convert the first and last Julian day range to a range that uses
            // UTC milliseconds.
            Time time = new Time(instancesTimezone);
            long beginMs = time.setJulianDay((int) rangeBegin);
            // 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 endMs = time.setJulianDay((int) rangeEnd + 1);
            // will lock the database.
            acquireInstanceRange(beginMs, endMs, true /* use minimum expansion window */,
                    forceExpansion, instancesTimezone, isHomeTimezone);
            qb.appendWhere(SQL_WHERE_INSTANCES_BETWEEN_DAY);
        } else {
            // will lock the database.
            acquireInstanceRange(rangeBegin, rangeEnd, true /* use minimum expansion window */,
                    forceExpansion, instancesTimezone, isHomeTimezone);
            qb.appendWhere(SQL_WHERE_INSTANCES_BETWEEN);
        }

        String[] newSelectionArgs = new String[] {String.valueOf(rangeEnd),
                String.valueOf(rangeBegin)};
        if (selectionArgs == null) {
            selectionArgs = newSelectionArgs;
        } else {
            selectionArgs = combine(newSelectionArgs, selectionArgs);
        }
        return qb.query(mDb, projection, selection, selectionArgs, null /* groupBy */,
                null /* having */, sort);
    }

    /**
     * Combine a set of arrays in the order they are passed in. All arrays must
     * be of the same type.
     */
    private static <T> T[] combine(T[]... arrays) {
        if (arrays.length == 0) {
            throw new IllegalArgumentException("Must supply at least 1 array to combine");
        }

        int totalSize = 0;
        for (T[] array : arrays) {
            totalSize += array.length;
        }

        T[] finalArray = (T[]) (Array.newInstance(arrays[0].getClass().getComponentType(),
                totalSize));

        int currentPos = 0;
        for (T[] array : arrays) {
            int length = array.length;
            System.arraycopy(array, 0, finalArray, currentPos, length);
            currentPos += array.length;
        }
        return finalArray;
    }

    /**
     * Escape any special characters in the search token
     * @param token the token to escape
     * @return the escaped token
     */
    @VisibleForTesting
    String escapeSearchToken(String token) {
        Matcher matcher = SEARCH_ESCAPE_PATTERN.matcher(token);
        return matcher.replaceAll(SEARCH_ESCAPE_CHAR + "$1");
    }

    /**
     * Splits the search query into individual search tokens based on whitespace
     * and punctuation. Leaves both single quoted and double quoted strings
     * intact.
     *
     * @param query the search query
     * @return an array of tokens from the search query
     */
    @VisibleForTesting
    String[] tokenizeSearchQuery(String query) {
        List<String> matchList = new ArrayList<String>();
        Matcher matcher = SEARCH_TOKEN_PATTERN.matcher(query);
        String token;
        while (matcher.find()) {
            if (matcher.group(1) != null) {
                // double quoted string
                token = matcher.group(1);
            } else {
                // unquoted token
                token = matcher.group();
            }
            matchList.add(escapeSearchToken(token));
        }
        return matchList.toArray(new String[matchList.size()]);
    }

    /**
     * In order to support what most people would consider a reasonable
     * search behavior, we have to do some interesting things here. We
     * assume that when a user searches for something like "lunch meeting",
     * they really want any event that matches both "lunch" and "meeting",
     * not events that match the string "lunch meeting" itself. In order to
     * do this across multiple columns, we have to construct a WHERE clause
     * that looks like:
     * <code>
     *   WHERE (title LIKE "%lunch%"
     *      OR description LIKE "%lunch%"
     *      OR eventLocation LIKE "%lunch%")
     *     AND (title LIKE "%meeting%"
     *      OR description LIKE "%meeting%"
     *      OR eventLocation LIKE "%meeting%")
     * </code>
     * This "product of clauses" is a bit ugly, but produced a fairly good
     * approximation of full-text search across multiple columns.  The set
     * of columns is specified by the SEARCH_COLUMNS constant.
     * <p>
     * Note the "WHERE" token isn't part of the returned string.  The value
     * may be passed into a query as the "HAVING" clause.
     */
    @VisibleForTesting
    String constructSearchWhere(String[] tokens) {
        if (tokens.length == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        String column, token;
        for (int j = 0; j < tokens.length; j++) {
            sb.append("(");
            for (int i = 0; i < SEARCH_COLUMNS.length; i++) {
                sb.append(SEARCH_COLUMNS[i]);
                sb.append(" LIKE ? ESCAPE \"");
                sb.append(SEARCH_ESCAPE_CHAR);
                sb.append("\" ");
                if (i < SEARCH_COLUMNS.length - 1) {
                    sb.append("OR ");
                }
            }
            sb.append(")");
            if (j < tokens.length - 1) {
                sb.append(" AND ");
            }
        }
        return sb.toString();
    }

    @VisibleForTesting
    String[] constructSearchArgs(String[] tokens) {
        int numCols = SEARCH_COLUMNS.length;
        int numArgs = tokens.length * numCols;
        String[] selectionArgs = new String[numArgs];
        for (int j = 0; j < tokens.length; j++) {
            int start = numCols * j;
            for (int i = start; i < start + numCols; i++) {
                selectionArgs[i] = "%" + tokens[j] + "%";
            }
        }
        return selectionArgs;
    }

    private Cursor handleInstanceSearchQuery(SQLiteQueryBuilder qb,
            long rangeBegin, long rangeEnd, String query, String[] projection,
            String selection, String[] selectionArgs, String sort, boolean searchByDay,
            String instancesTimezone, boolean isHomeTimezone) {
        mDb = mDbHelper.getWritableDatabase();
        qb.setTables(INSTANCE_SEARCH_QUERY_TABLES);
        qb.setProjectionMap(sInstancesProjectionMap);

        String[] tokens = tokenizeSearchQuery(query);
        String[] searchArgs = constructSearchArgs(tokens);
        String[] timeRange = new String[] {String.valueOf(rangeEnd), String.valueOf(rangeBegin)};
        if (selectionArgs == null) {
            selectionArgs = combine(timeRange, searchArgs);
        } else {
            // where clause comes first, so put selectionArgs before searchArgs.
            selectionArgs = combine(timeRange, selectionArgs, searchArgs);
        }
        // we pass this in as a HAVING instead of a WHERE so the filtering
        // happens after the grouping
        String searchWhere = constructSearchWhere(tokens);

        if (searchByDay) {
            // Convert the first and last Julian day range to a range that uses
            // UTC milliseconds.
            Time time = new Time(instancesTimezone);
            long beginMs = time.setJulianDay((int) rangeBegin);
            // 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 endMs = time.setJulianDay((int) rangeEnd + 1);
            // will lock the database.
            // we expand the instances here because we might be searching over
            // a range where instance expansion has not occurred yet
            acquireInstanceRange(beginMs, endMs,
                    true /* use minimum expansion window */,
                    false /* do not force Instances deletion and expansion */,
                    instancesTimezone,
                    isHomeTimezone
            );
            qb.appendWhere(SQL_WHERE_INSTANCES_BETWEEN_DAY);
        } else {
            // will lock the database.
            // we expand the instances here because we might be searching over
            // a range where instance expansion has not occurred yet
            acquireInstanceRange(rangeBegin, rangeEnd,
                    true /* use minimum expansion window */,
                    false /* do not force Instances deletion and expansion */,
                    instancesTimezone,
                    isHomeTimezone
            );
            qb.appendWhere(SQL_WHERE_INSTANCES_BETWEEN);
        }
        return qb.query(mDb, projection, selection, selectionArgs,
                Tables.INSTANCES + "." + Instances._ID /* groupBy */,
                searchWhere /* having */, sort);
    }

    private Cursor handleEventDayQuery(SQLiteQueryBuilder qb, int begin, int end,
            String[] projection, String selection, String instancesTimezone,
            boolean isHomeTimezone) {
        mDb = mDbHelper.getWritableDatabase();
        qb.setTables(INSTANCE_QUERY_TABLES);
        qb.setProjectionMap(sInstancesProjectionMap);
        // Convert the first and last Julian day range to a range that uses
        // UTC milliseconds.
        Time time = new Time(instancesTimezone);
        long beginMs = time.setJulianDay(begin);
        // 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 endMs = time.setJulianDay(end + 1);

        acquireInstanceRange(beginMs, endMs, true,
                false /* do not force Instances expansion */, instancesTimezone, isHomeTimezone);
        qb.appendWhere(SQL_WHERE_INSTANCES_BETWEEN_DAY);
        String selectionArgs[] = new String[] {String.valueOf(end), String.valueOf(begin)};

        return qb.query(mDb, projection, selection, selectionArgs,
                Instances.START_DAY /* groupBy */, null /* having */, null);
    }

    /**
     * Ensure that the date range given has all elements in the instance
     * table.  Acquires the database lock and calls
     * {@link #acquireInstanceRangeLocked(long, long, boolean, boolean, String, boolean)}.
     *
     * @param begin start of range (ms)
     * @param end end of range (ms)
     * @param useMinimumExpansionWindow expand by at least MINIMUM_EXPANSION_SPAN
     * @param forceExpansion force the Instance deletion and expansion if set to true
     * @param instancesTimezone timezone we need to use for computing the instances
     * @param isHomeTimezone if true, we are in the "home" timezone
     */
    private void acquireInstanceRange(final long begin, final long end,
            final boolean useMinimumExpansionWindow, final boolean forceExpansion,
            final String instancesTimezone, final boolean isHomeTimezone) {
        mDb.beginTransaction();
        try {
            acquireInstanceRangeLocked(begin, end, useMinimumExpansionWindow,
                    forceExpansion, instancesTimezone, isHomeTimezone);
            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.
     *
     * @param begin start of range (ms)
     * @param end end of range (ms)
     * @param useMinimumExpansionWindow expand by at least MINIMUM_EXPANSION_SPAN
     * @param forceExpansion force the Instance deletion and expansion if set to true
     * @param instancesTimezone timezone we need to use for computing the instances
     * @param isHomeTimezone if true, we are in the "home" timezone
     */
    void acquireInstanceRangeLocked(long begin, long end, boolean useMinimumExpansionWindow,
            boolean forceExpansion, String instancesTimezone, boolean isHomeTimezone) {
        long expandBegin = begin;
        long expandEnd = end;

        if (DEBUG_INSTANCES) {
            Log.d(TAG + "-i", "acquireInstanceRange begin=" + begin + " end=" + end +
                    " useMin=" + useMinimumExpansionWindow + " force=" + forceExpansion);
        }

        if (instancesTimezone == null) {
            Log.e(TAG, "Cannot run acquireInstanceRangeLocked() because instancesTimezone is null");
            return;
        }

        if (useMinimumExpansionWindow) {
            // if we end up having to expand events into the instances table, expand
            // events for a minimal amount of time, so we do not have to perform
            // expansions frequently.
            long span = end - begin;
            if (span < MINIMUM_EXPANSION_SPAN) {
                long additionalRange = (MINIMUM_EXPANSION_SPAN - span) / 2;
                expandBegin -= additionalRange;
                expandEnd += additionalRange;
            }
        }

        // Check if the timezone has changed.
        // We do this check here because the database is locked and we can
        // safely delete all the entries in the Instances table.
        MetaData.Fields fields = mMetaData.getFieldsLocked();
        long maxInstance = fields.maxInstance;
        long minInstance = fields.minInstance;
        boolean timezoneChanged;
        if (isHomeTimezone) {
            String previousTimezone = mCalendarCache.readTimezoneInstancesPrevious();
            timezoneChanged = !instancesTimezone.equals(previousTimezone);
        } else {
            String localTimezone = TimeZone.getDefault().getID();
            timezoneChanged = !instancesTimezone.equals(localTimezone);
            // if we're in auto make sure we are using the device time zone
            if (timezoneChanged) {
                instancesTimezone = localTimezone;
            }
        }
        // if "home", then timezoneChanged only if current != previous
        // if "auto", then timezoneChanged, if !instancesTimezone.equals(localTimezone);
        if (maxInstance == 0 || timezoneChanged || forceExpansion) {
            if (DEBUG_INSTANCES) {
                Log.d(TAG + "-i", "Wiping instances and expanding from scratch");
            }

            // Empty the Instances table and expand from scratch.
            mDb.execSQL("DELETE FROM " + Tables.INSTANCES + ";");
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "acquireInstanceRangeLocked() deleted Instances,"
                        + " timezone changed: " + timezoneChanged);
            }
            mInstancesHelper.expandInstanceRangeLocked(expandBegin, expandEnd, instancesTimezone);

            mMetaData.writeLocked(instancesTimezone, expandBegin, expandEnd);

            final String timezoneType = mCalendarCache.readTimezoneType();
            // This may cause some double writes but guarantees the time zone in
            // the db and the time zone the instances are in is the same, which
            // future changes may affect.
            mCalendarCache.writeTimezoneInstances(instancesTimezone);

            // If we're in auto check if we need to fix the previous tz value
            if (CalendarCache.TIMEZONE_TYPE_AUTO.equals(timezoneType)) {
                String prevTZ = mCalendarCache.readTimezoneInstancesPrevious();
                if (TextUtils.equals(TIMEZONE_GMT, prevTZ)) {
                    mCalendarCache.writeTimezoneInstancesPrevious(instancesTimezone);
                }
            }
            return;
        }

        // If the desired range [begin, end] has already been
        // expanded, then simply return.  The range is inclusive, that is,
        // events that touch either endpoint are included in the expansion.
        // This means that a zero-duration event that starts and ends at
        // the endpoint will be included.
        // We use [begin, end] here and not [expandBegin, expandEnd] for
        // checking the range because a common case is for the client to
        // request successive days or weeks, for example.  If we checked
        // that the expanded range [expandBegin, expandEnd] then we would
        // always be expanding because there would always be one more day
        // or week that hasn't been expanded.
        if ((begin >= minInstance) && (end <= maxInstance)) {
            if (DEBUG_INSTANCES) {
                Log.d(TAG + "-i", "instances are already expanded");
            }
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Canceled instance query (" + expandBegin + ", " + expandEnd
                        + ") falls within previously expanded range.");
            }
            return;
        }

        // If the requested begin point has not been expanded, then include
        // more events than requested in the expansion (use "expandBegin").
        if (begin < minInstance) {
            mInstancesHelper.expandInstanceRangeLocked(expandBegin, minInstance, instancesTimezone);
            minInstance = expandBegin;
        }

        // If the requested end point has not been expanded, then include
        // more events than requested in the expansion (use "expandEnd").
        if (end > maxInstance) {
            mInstancesHelper.expandInstanceRangeLocked(maxInstance, expandEnd, instancesTimezone);
            maxInstance = expandEnd;
        }

        // Update the bounds on the Instances table.
        mMetaData.writeLocked(instancesTimezone, minInstance, maxInstance);
    }

    @Override
    public String getType(Uri url) {
        int match = sUriMatcher.match(url);
        switch (match) {
            case EVENTS:
                return "vnd.android.cursor.dir/event";
            case EVENTS_ID:
                return "vnd.android.cursor.item/event";
            case REMINDERS:
                return "vnd.android.cursor.dir/reminder";
            case REMINDERS_ID:
                return "vnd.android.cursor.item/reminder";
            case CALENDAR_ALERTS:
                return "vnd.android.cursor.dir/calendar-alert";
            case CALENDAR_ALERTS_BY_INSTANCE:
                return "vnd.android.cursor.dir/calendar-alert-by-instance";
            case CALENDAR_ALERTS_ID:
                return "vnd.android.cursor.item/calendar-alert";
            case INSTANCES:
            case INSTANCES_BY_DAY:
            case EVENT_DAYS:
                return "vnd.android.cursor.dir/event-instance";
            case TIME:
                return "time/epoch";
            case PROVIDER_PROPERTIES:
                return "vnd.android.cursor.dir/property";
            default:
                throw new IllegalArgumentException("Unknown URL " + url);
        }
    }

    /**
     * Determines if the event is recurrent, based on the provided values.
     */
    public static boolean isRecurrenceEvent(String rrule, String rdate, String originalId,
            String originalSyncId) {
        return (!TextUtils.isEmpty(rrule) ||
                !TextUtils.isEmpty(rdate) ||
                !TextUtils.isEmpty(originalId) ||
                !TextUtils.isEmpty(originalSyncId));
    }

    /**
     * Takes an event and corrects the hrs, mins, secs if it is an allDay event.
     * <p>
     * AllDay events should have hrs, mins, secs set to zero. This checks if this is true and
     * corrects the fields DTSTART, DTEND, and DURATION if necessary.
     *
     * @param values The values to check and correct
     * @param modValues Any updates will be stored here.  This may be the same object as
     *   <strong>values</strong>.
     * @return Returns true if a correction was necessary, false otherwise
     */
    private boolean fixAllDayTime(ContentValues values, ContentValues modValues) {
        Integer allDayObj = values.getAsInteger(Events.ALL_DAY);
        if (allDayObj == null || allDayObj == 0) {
            return false;
        }

        boolean neededCorrection = false;

        Long dtstart = values.getAsLong(Events.DTSTART);
        Long dtend = values.getAsLong(Events.DTEND);
        String duration = values.getAsString(Events.DURATION);
        Time time = new Time();
        String tempValue;

        // Change dtstart so h,m,s are 0 if necessary.
        time.clear(Time.TIMEZONE_UTC);
        time.set(dtstart.longValue());
        if (time.hour != 0 || time.minute != 0 || time.second != 0) {
            time.hour = 0;
            time.minute = 0;
            time.second = 0;
            modValues.put(Events.DTSTART, time.toMillis(true));
            neededCorrection = true;
        }

        // If dtend exists for this event make sure it's h,m,s are 0.
        if (dtend != null) {
            time.clear(Time.TIMEZONE_UTC);
            time.set(dtend.longValue());
            if (time.hour != 0 || time.minute != 0 || time.second != 0) {
                time.hour = 0;
                time.minute = 0;
                time.second = 0;
                dtend = time.toMillis(true);
                modValues.put(Events.DTEND, dtend);
                neededCorrection = true;
            }
        }

        if (duration != null) {
            int len = duration.length();
            /* duration is stored as either "P<seconds>S" or "P<days>D". This checks if it's
             * in the seconds format, and if so converts it to days.
             */
            if (len == 0) {
                duration = null;
            } else if (duration.charAt(0) == 'P' &&
                    duration.charAt(len - 1) == 'S') {
                int seconds = Integer.parseInt(duration.substring(1, len - 1));
                int days = (seconds + DAY_IN_SECONDS - 1) / DAY_IN_SECONDS;
                duration = "P" + days + "D";
                modValues.put(Events.DURATION, duration);
                neededCorrection = true;
            }
        }

        return neededCorrection;
    }


    /**
     * Determines whether the strings in the set name columns that may be overridden
     * when creating a recurring event exception.
     * <p>
     * This uses a white list because it screens out unknown columns and is a bit safer to
     * maintain than a black list.
     */
    private void checkAllowedInException(Set<String> keys) {
        for (String str : keys) {
            if (!ALLOWED_IN_EXCEPTION.contains(str.intern())) {
                throw new IllegalArgumentException("Exceptions can't overwrite " + str);
            }
        }
    }

    /**
     * Splits a recurrent event at a specified instance.  This is useful when modifying "this
     * and all future events".
     *<p>
     * If the recurrence rule has a COUNT specified, we need to split that at the point of the
     * exception.  If the exception is instance N (0-based), the original COUNT is reduced
     * to N, and the exception's COUNT is set to (COUNT - N).
     *<p>
     * If the recurrence doesn't have a COUNT, we need to update or introduce an UNTIL value,
     * so that the original recurrence will end just before the exception instance.  (Note
     * that UNTIL dates are inclusive.)
     *<p>
     * This should not be used to update the first instance ("update all events" action).
     *
     * @param values The original event values; must include EVENT_TIMEZONE and DTSTART.
     *        The RRULE value may be modified (with the expectation that this will propagate
     *        into the exception event).
     * @param endTimeMillis The time before which the event must end (i.e. the start time of the
     *        exception event instance).
     * @return Values to apply to the original event.
     */
    private static ContentValues setRecurrenceEnd(ContentValues values, long endTimeMillis) {
        boolean origAllDay = values.getAsBoolean(Events.ALL_DAY);
        String origRrule = values.getAsString(Events.RRULE);

        EventRecurrence origRecurrence = new EventRecurrence();
        origRecurrence.parse(origRrule);

        // Get the start time of the first instance in the original recurrence.
        long startTimeMillis = values.getAsLong(Events.DTSTART);
        Time dtstart = new Time();
        dtstart.timezone = values.getAsString(Events.EVENT_TIMEZONE);
        dtstart.set(startTimeMillis);

        ContentValues updateValues = new ContentValues();

        if (origRecurrence.count > 0) {
            /*
             * Generate the full set of instances for this recurrence, from the first to the
             * one just before endTimeMillis.  The list should never be empty, because this method
             * should not be called for the first instance.  All we're really interested in is
             * the *number* of instances found.
             */
            RecurrenceSet recurSet = new RecurrenceSet(values);
            RecurrenceProcessor recurProc = new RecurrenceProcessor();
            long[] recurrences;
            try {
                recurrences = recurProc.expand(dtstart, recurSet, startTimeMillis, endTimeMillis);
            } catch (DateException de) {
                throw new RuntimeException(de);
            }

            if (recurrences.length == 0) {
                throw new RuntimeException("can't use this method on first instance");
            }

            EventRecurrence excepRecurrence = new EventRecurrence();
            excepRecurrence.parse(origRrule); // TODO: add/use a copy constructor to EventRecurrence
            excepRecurrence.count -= recurrences.length;
            values.put(Events.RRULE, excepRecurrence.toString());

            origRecurrence.count = recurrences.length;

        } else {
            Time untilTime = new Time();

            // The "until" time must be in UTC time in order for Google calendar
            // to display it properly. For all-day events, the "until" time string
            // must include just the date field, and not the time field. The
            // repeating events repeat up to and including the "until" time.
            untilTime.timezone = Time.TIMEZONE_UTC;

            // Subtract one second from the exception begin time to get the "until" time.
            untilTime.set(endTimeMillis - 1000); // subtract one second (1000 millis)
            if (origAllDay) {
                untilTime.hour = untilTime.minute = untilTime.second = 0;
                untilTime.allDay = true;
                untilTime.normalize(false);

                // This should no longer be necessary -- DTSTART should already be in the correct
                // format for an all-day event.
                dtstart.hour = dtstart.minute = dtstart.second = 0;
                dtstart.allDay = true;
                dtstart.timezone = Time.TIMEZONE_UTC;
            }
            origRecurrence.until = untilTime.format2445();
        }

        updateValues.put(Events.RRULE, origRecurrence.toString());
        updateValues.put(Events.DTSTART, dtstart.normalize(true));
        return updateValues;
    }

    /**
     * Handles insertion of an exception to a recurring event.
     * <p>
     * There are two modes, selected based on the presence of "rrule" in modValues:
     * <ol>
     * <li> Create a single instance exception ("modify current event only").
     * <li> Cap the original event, and create a new recurring event ("modify this and all
     * future events").
     * </ol>
     * This may be used for "modify all instances of the event" by simply selecting the
     * very first instance as the exception target.  In that case, the ID of the "new"
     * exception event will be the same as the originalEventId.
     *
     * @param originalEventId The _id of the event to be modified
     * @param modValues Event columns to update
     * @param callerIsSyncAdapter Set if the content provider client is the sync adapter
     * @return the ID of the new "exception" event, or -1 on failure
     */
    private long handleInsertException(long originalEventId, ContentValues modValues,
            boolean callerIsSyncAdapter) {
        if (DEBUG_EXCEPTION) {
            Log.i(TAG, "RE: values: " + modValues.toString());
        }

        // Make sure they have specified an instance via originalInstanceTime.
        Long originalInstanceTime = modValues.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
        if (originalInstanceTime == null) {
            throw new IllegalArgumentException("Exceptions must specify " +
                    Events.ORIGINAL_INSTANCE_TIME);
        }

        // Check for attempts to override values that shouldn't be touched.
        checkAllowedInException(modValues.keySet());

        // If this isn't the sync adapter, set the "dirty" flag in any Event we modify.
        if (!callerIsSyncAdapter) {
            modValues.put(Events.DIRTY, true);
            addMutator(modValues, Events.MUTATORS);
        }

        // Wrap all database accesses in a transaction.
        mDb.beginTransaction();
        Cursor cursor = null;
        try {
            // TODO: verify that there's an instance corresponding to the specified time
            //       (does this matter? it's weird, but not fatal?)

            // Grab the full set of columns for this event.
            cursor = mDb.query(Tables.EVENTS, null /* columns */,
                    SQL_WHERE_ID, new String[] { String.valueOf(originalEventId) },
                    null /* groupBy */, null /* having */, null /* sortOrder */);
            if (cursor.getCount() != 1) {
                Log.e(TAG, "Original event ID " + originalEventId + " lookup failed (count is " +
                        cursor.getCount() + ")");
                return -1;
            }
            //DatabaseUtils.dumpCursor(cursor);

            // If there's a color index check that it's valid
            String color_index = modValues.getAsString(Events.EVENT_COLOR_KEY);
            if (!TextUtils.isEmpty(color_index)) {
                int calIdCol = cursor.getColumnIndex(Events.CALENDAR_ID);
                Long calId = cursor.getLong(calIdCol);
                String accountName = null;
                String accountType = null;
                if (calId != null) {
                    Account account = getAccount(calId);
                    if (account != null) {
                        accountName = account.name;
                        accountType = account.type;
                    }
                }
                verifyColorExists(accountName, accountType, color_index, Colors.TYPE_EVENT);
            }

            /*
             * Verify that the original event is in fact a recurring event by checking for the
             * presence of an RRULE.  If it's there, we assume that the event is otherwise
             * properly constructed (e.g. no DTEND).
             */
            cursor.moveToFirst();
            int rruleCol = cursor.getColumnIndex(Events.RRULE);
            if (TextUtils.isEmpty(cursor.getString(rruleCol))) {
                Log.e(TAG, "Original event has no rrule");
                return -1;
            }
            if (DEBUG_EXCEPTION) {
                Log.d(TAG, "RE: old RRULE is " + cursor.getString(rruleCol));
            }

            // Verify that the original event is not itself a (single-instance) exception.
            int originalIdCol = cursor.getColumnIndex(Events.ORIGINAL_ID);
            if (!TextUtils.isEmpty(cursor.getString(originalIdCol))) {
                Log.e(TAG, "Original event is an exception");
                return -1;
            }

            boolean createSingleException = TextUtils.isEmpty(modValues.getAsString(Events.RRULE));

            // TODO: check for the presence of an existing exception on this event+instance?
            //       The caller should be modifying that, not creating another exception.
            //       (Alternatively, we could do that for them.)

            // Create a new ContentValues for the new event.  Start with the original event,
            // and drop in the new caller-supplied values.  This will set originalInstanceTime.
            ContentValues values = new ContentValues();
            DatabaseUtils.cursorRowToContentValues(cursor, values);
            cursor.close();
            cursor = null;

            // TODO: if we're changing this to an all-day event, we should ensure that
            //       hours/mins/secs on DTSTART are zeroed out (before computing DTEND).
            //       See fixAllDayTime().

            boolean createNewEvent = true;
            if (createSingleException) {
                /*
                 * Save a copy of a few fields that will migrate to new places.
                 */
                String _id = values.getAsString(Events._ID);
                String _sync_id = values.getAsString(Events._SYNC_ID);
                boolean allDay = values.getAsBoolean(Events.ALL_DAY);

                /*
                 * Wipe out some fields that we don't want to clone into the exception event.
                 */
                for (String str : DONT_CLONE_INTO_EXCEPTION) {
                    values.remove(str);
                }

                /*
                 * Merge the new values on top of the existing values.  Note this sets
                 * originalInstanceTime.
                 */
                values.putAll(modValues);

                /*
                 * Copy some fields to their "original" counterparts:
                 *   _id --> original_id
                 *   _sync_id --> original_sync_id
                 *   allDay --> originalAllDay
                 *
                 * If this event hasn't been sync'ed with the server yet, the _sync_id field will
                 * be null.  We will need to fill original_sync_id in later.  (May not be able to
                 * do it right when our own _sync_id field gets populated, because the order of
                 * events from the server may not be what we want -- could update the exception
                 * before updating the original event.)
                 *
                 * _id is removed later (right before we write the event).
                 */
                values.put(Events.ORIGINAL_ID, _id);
                values.put(Events.ORIGINAL_SYNC_ID, _sync_id);
                values.put(Events.ORIGINAL_ALL_DAY, allDay);

                // Mark the exception event status as "tentative", unless the caller has some
                // other value in mind (like STATUS_CANCELED).
                if (!values.containsKey(Events.STATUS)) {
                    values.put(Events.STATUS, Events.STATUS_TENTATIVE);
                }

                // We're converting from recurring to non-recurring.
                // Clear out RRULE, RDATE, EXRULE & EXDATE
                // Replace DURATION with DTEND.
                values.remove(Events.RRULE);
                values.remove(Events.RDATE);
                values.remove(Events.EXRULE);
                values.remove(Events.EXDATE);

                Duration duration = new Duration();
                String durationStr = values.getAsString(Events.DURATION);
                try {
                    duration.parse(durationStr);
                } catch (Exception ex) {
                    // NullPointerException if the original event had no duration.
                    // DateException if the duration was malformed.
                    Log.w(TAG, "Bad duration in recurring event: " + durationStr, ex);
                    return -1;
                }

                /*
                 * We want to compute DTEND as an offset from the start time of the instance.
                 * If the caller specified a new value for DTSTART, we want to use that; if not,
                 * the DTSTART in "values" will be the start time of the first instance in the
                 * recurrence, so we want to replace it with ORIGINAL_INSTANCE_TIME.
                 */
                long start;
                if (modValues.containsKey(Events.DTSTART)) {
                    start = values.getAsLong(Events.DTSTART);
                } else {
                    start = values.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
                    values.put(Events.DTSTART, start);
                }
                values.put(Events.DTEND, start + duration.getMillis());
                if (DEBUG_EXCEPTION) {
                    Log.d(TAG, "RE: ORIG_INST_TIME=" + start +
                            ", duration=" + duration.getMillis() +
                            ", generated DTEND=" + values.getAsLong(Events.DTEND));
                }
                values.remove(Events.DURATION);
            } else {
                /*
                 * We're going to "split" the recurring event, making the old one stop before
                 * this instance, and creating a new recurring event that starts here.
                 *
                 * No need to fill out the "original" fields -- the new event is not tied to
                 * the previous event in any way.
                 *
                 * If this is the first event in the series, we can just update the existing
                 * event with the values.
                 */
                boolean canceling = (values.getAsInteger(Events.STATUS) == Events.STATUS_CANCELED);

                if (originalInstanceTime.equals(values.getAsLong(Events.DTSTART))) {
                    /*
                     * Update fields in the existing event.  Rather than use the merged data
                     * from the cursor, we just do the update with the new value set after
                     * removing the ORIGINAL_INSTANCE_TIME entry.
                     */
                    if (canceling) {
                        // TODO: should we just call deleteEventInternal?
                        Log.d(TAG, "Note: canceling entire event via exception call");
                    }
                    if (DEBUG_EXCEPTION) {
                        Log.d(TAG, "RE: updating full event");
                    }
                    if (!validateRecurrenceRule(modValues)) {
                        throw new IllegalArgumentException("Invalid recurrence rule: " +
                                values.getAsString(Events.RRULE));
                    }
                    modValues.remove(Events.ORIGINAL_INSTANCE_TIME);
                    mDb.update(Tables.EVENTS, modValues, SQL_WHERE_ID,
                            new String[] { Long.toString(originalEventId) });
                    createNewEvent = false; // skip event creation and related-table cloning
                } else {
                    if (DEBUG_EXCEPTION) {
                        Log.d(TAG, "RE: splitting event");
                    }

                    /*
                     * Cap the original event so it ends just before the target instance.  In
                     * some cases (nonzero COUNT) this will also update the RRULE in "values",
                     * so that the exception we're creating terminates appropriately.  If a
                     * new RRULE was specified by the caller, the new rule will overwrite our
                     * changes when we merge the new values in below (which is the desired
                     * behavior).
                     */
                    ContentValues splitValues = setRecurrenceEnd(values, originalInstanceTime);
                    mDb.update(Tables.EVENTS, splitValues, SQL_WHERE_ID,
                            new String[] { Long.toString(originalEventId) });

                    /*
                     * Prepare the new event.  We remove originalInstanceTime, because we're now
                     * creating a new event rather than an exception.
                     *
                     * We're always cloning a non-exception event (we tested to make sure the
                     * event doesn't specify original_id, and we don't allow original_id in the
                     * modValues), so we shouldn't end up creating a new event that looks like
                     * an exception.
                     */
                    values.putAll(modValues);
                    values.remove(Events.ORIGINAL_INSTANCE_TIME);
                }
            }

            long newEventId;
            if (createNewEvent) {
                values.remove(Events._ID);      // don't try to set this explicitly
                if (callerIsSyncAdapter) {
                    scrubEventData(values, null);
                } else {
                    validateEventData(values);
                }

                newEventId = mDb.insert(Tables.EVENTS, null, values);
                if (newEventId < 0) {
                    Log.w(TAG, "Unable to add exception to recurring event");
                    Log.w(TAG, "Values: " + values);
                    return -1;
                }
                if (DEBUG_EXCEPTION) {
                    Log.d(TAG, "RE: new ID is " + newEventId);
                }

                // TODO: do we need to do something like this?
                //updateEventRawTimesLocked(id, updatedValues);

                /*
                 * Force re-computation of the Instances associated with the recurrence event.
                 */
                mInstancesHelper.updateInstancesLocked(values, newEventId, true, mDb);

                /*
                 * Some of the other tables (Attendees, Reminders, ExtendedProperties) reference
                 * the Event ID.  We need to copy the entries from the old event, filling in the
                 * new event ID, so that somebody doing a SELECT on those tables will find
                 * matching entries.
                 */
                CalendarDatabaseHelper.copyEventRelatedTables(mDb, newEventId, originalEventId);

                /*
                 * If we modified Event.selfAttendeeStatus, we need to keep the corresponding
                 * entry in the Attendees table in sync.
                 */
                if (modValues.containsKey(Events.SELF_ATTENDEE_STATUS)) {
                    /*
                     * Each Attendee is identified by email address.  To find the entry that
                     * corresponds to "self", we want to compare that address to the owner of
                     * the Calendar.  We're expecting to find one matching entry in Attendees.
                     */
                    long calendarId = values.getAsLong(Events.CALENDAR_ID);
                    String accountName = getOwner(calendarId);

                    if (accountName != null) {
                        ContentValues attValues = new ContentValues();
                        attValues.put(Attendees.ATTENDEE_STATUS,
                                modValues.getAsString(Events.SELF_ATTENDEE_STATUS));

                        if (DEBUG_EXCEPTION) {
                            Log.d(TAG, "Updating attendee status for event=" + newEventId +
                                    " name=" + accountName + " to " +
                                    attValues.getAsString(Attendees.ATTENDEE_STATUS));
                        }
                        int count = mDb.update(Tables.ATTENDEES, attValues,
                                Attendees.EVENT_ID + "=? AND " + Attendees.ATTENDEE_EMAIL + "=?",
                                new String[] { String.valueOf(newEventId), accountName });
                        if (count != 1 && count != 2) {
                            // We're only expecting one matching entry.  We might briefly see
                            // two during a server sync.
                            Log.e(TAG, "Attendee status update on event=" + newEventId
                                    + " touched " + count + " rows. Expected one or two rows.");
                            if (false) {
                                // This dumps PII in the log, don't ship with it enabled.
                                Cursor debugCursor = mDb.query(Tables.ATTENDEES, null,
                                        Attendees.EVENT_ID + "=? AND " +
                                            Attendees.ATTENDEE_EMAIL + "=?",
                                        new String[] { String.valueOf(newEventId), accountName },
                                        null, null, null);
                                DatabaseUtils.dumpCursor(debugCursor);
                                if (debugCursor != null) {
                                    debugCursor.close();
                                }
                            }
                            throw new RuntimeException("Status update WTF");
                        }
                    }
                }
            } else {
                /*
                 * Update any Instances changed by the update to this Event.
                 */
                mInstancesHelper.updateInstancesLocked(values, originalEventId, false, mDb);
                newEventId = originalEventId;
            }

            mDb.setTransactionSuccessful();
            return newEventId;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
            mDb.endTransaction();
        }
    }

    /**
     * Fills in the originalId column for previously-created exceptions to this event.  If
     * this event is not recurring or does not have a _sync_id, this does nothing.
     * <p>
     * The server might send exceptions before the event they refer to.  When
     * this happens, the originalId field will not have been set in the
     * exception events (it's the recurrence events' _id field, so it can't be
     * known until the recurrence event is created).  When we add a recurrence
     * event with a non-empty _sync_id field, we write that event's _id to the
     * originalId field of any events whose originalSyncId matches _sync_id.
     * <p>
     * Note _sync_id is only expected to be unique within a particular calendar.
     *
     * @param id The ID of the Event
     * @param values Values for the Event being inserted
     */
    private void backfillExceptionOriginalIds(long id, ContentValues values) {
        String syncId = values.getAsString(Events._SYNC_ID);
        String rrule = values.getAsString(Events.RRULE);
        String rdate = values.getAsString(Events.RDATE);
        String calendarId = values.getAsString(Events.CALENDAR_ID);

        if (TextUtils.isEmpty(syncId) || TextUtils.isEmpty(calendarId) ||
                (TextUtils.isEmpty(rrule) && TextUtils.isEmpty(rdate))) {
            // Not a recurring event, or doesn't have a server-provided sync ID.
            return;
        }

        ContentValues originalValues = new ContentValues();
        originalValues.put(Events.ORIGINAL_ID, id);
        mDb.update(Tables.EVENTS, originalValues,
                Events.ORIGINAL_SYNC_ID + "=? AND " + Events.CALENDAR_ID + "=?",
                new String[] { syncId, calendarId });
    }

    @Override
    public int bulkInsert(Uri uri, ContentValues[] values) {
        final int callingUid = Binder.getCallingUid();
        mCallingUid.set(callingUid);

        mStats.incrementBatchStats(callingUid);
        try {
            return super.bulkInsert(uri, values);
        } finally {
            mStats.finishOperation(callingUid);
        }
    }

    @Override
    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
            throws OperationApplicationException {
        final int callingUid = Binder.getCallingUid();
        mCallingUid.set(callingUid);

        mStats.incrementBatchStats(callingUid);
        try {
            return super.applyBatch(operations);
        } finally {
            mStats.finishOperation(callingUid);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        if (!applyingBatch()) {
            mCallingUid.set(Binder.getCallingUid());
        }

        return super.insert(uri, values);
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        if (!applyingBatch()) {
            mCallingUid.set(Binder.getCallingUid());
        }

        return super.update(uri, values, selection, selectionArgs);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if (!applyingBatch()) {
            mCallingUid.set(Binder.getCallingUid());
        }

        return super.delete(uri, selection, selectionArgs);
    }

    @Override
    protected Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
        final int callingUid = mCallingUid.get();

        mStats.incrementInsertStats(callingUid, applyingBatch());
        try {
            return insertInTransactionInner(uri, values, callerIsSyncAdapter);
        } finally {
            mStats.finishOperation(callingUid);
        }
    }

    private Uri insertInTransactionInner(
            Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "insertInTransaction: " + uri);
        }
        CalendarSanityChecker.getInstance(mContext).checkLastCheckTime();

        validateUriParameters(uri.getQueryParameterNames());
        final int match = sUriMatcher.match(uri);
        verifyTransactionAllowed(TRANSACTION_INSERT, uri, values, callerIsSyncAdapter, match,
                null /* selection */, null /* selection args */);
        mDb = mDbHelper.getWritableDatabase();

        long id = 0;

        switch (match) {
            case SYNCSTATE:
                id = mDbHelper.getSyncState().insert(mDb, values);
                break;
            case EVENTS:
                if (!callerIsSyncAdapter) {
                    values.put(Events.DIRTY, 1);
                    addMutator(values, Events.MUTATORS);
                }
                if (!values.containsKey(Events.DTSTART)) {
                    if (values.containsKey(Events.ORIGINAL_SYNC_ID)
                            && values.containsKey(Events.ORIGINAL_INSTANCE_TIME)
                            && Events.STATUS_CANCELED == values.getAsInteger(Events.STATUS)) {
                        // event is a canceled instance of a recurring event, it doesn't these
                        // values but lets fake some to satisfy curious consumers.
                        final long origStart = values.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
                        values.put(Events.DTSTART, origStart);
                        values.put(Events.DTEND, origStart);
                        values.put(Events.EVENT_TIMEZONE, Time.TIMEZONE_UTC);
                    } else {
                        throw new RuntimeException("DTSTART field missing from event");
                    }
                }
                // TODO: do we really need to make a copy?
                ContentValues updatedValues = new ContentValues(values);
                if (callerIsSyncAdapter) {
                    scrubEventData(updatedValues, null);
                } else {
                    validateEventData(updatedValues);
                }
                // updateLastDate must be after validation, to ensure proper last date computation
                updatedValues = updateLastDate(updatedValues);
                if (updatedValues == null) {
                    throw new RuntimeException("Could not insert event.");
                    // return null;
                }
                Long calendar_id = updatedValues.getAsLong(Events.CALENDAR_ID);
                if (calendar_id == null) {
                    // validateEventData checks this for non-sync adapter
                    // inserts
                    throw new IllegalArgumentException("New events must specify a calendar id");
                }
                // Verify the color is valid if it is being set
                String color_id = updatedValues.getAsString(Events.EVENT_COLOR_KEY);
                if (!TextUtils.isEmpty(color_id)) {
                    Account account = getAccount(calendar_id);
                    String accountName = null;
                    String accountType = null;
                    if (account != null) {
                        accountName = account.name;
                        accountType = account.type;
                    }
                    int color = verifyColorExists(accountName, accountType, color_id,
                            Colors.TYPE_EVENT);
                    updatedValues.put(Events.EVENT_COLOR, color);
                }
                String owner = null;
                if (!updatedValues.containsKey(Events.ORGANIZER)) {
                    owner = getOwner(calendar_id);
                    // TODO: This isn't entirely correct.  If a guest is adding a recurrence
                    // exception to an event, the organizer should stay the original organizer.
                    // This value doesn't go to the server and it will get fixed on sync,
                    // so it shouldn't really matter.
                    if (owner != null) {
                        updatedValues.put(Events.ORGANIZER, owner);
                    }
                }
                if (updatedValues.containsKey(Events.ORIGINAL_SYNC_ID)
                        && !updatedValues.containsKey(Events.ORIGINAL_ID)) {
                    long originalId = getOriginalId(updatedValues
                            .getAsString(Events.ORIGINAL_SYNC_ID),
                            updatedValues.getAsString(Events.CALENDAR_ID));
                    if (originalId != -1) {
                        updatedValues.put(Events.ORIGINAL_ID, originalId);
                    }
                } else if (!updatedValues.containsKey(Events.ORIGINAL_SYNC_ID)
                        && updatedValues.containsKey(Events.ORIGINAL_ID)) {
                    String originalSyncId = getOriginalSyncId(updatedValues
                            .getAsLong(Events.ORIGINAL_ID));
                    if (!TextUtils.isEmpty(originalSyncId)) {
                        updatedValues.put(Events.ORIGINAL_SYNC_ID, originalSyncId);
                    }
                }
                if (fixAllDayTime(updatedValues, updatedValues)) {
                    if (Log.isLoggable(TAG, Log.WARN)) {
                        Log.w(TAG, "insertInTransaction: " +
                                "allDay is true but sec, min, hour were not 0.");
                    }
                }
                updatedValues.remove(Events.HAS_ALARM);     // should not be set by caller
                // Insert the row
                id = mDbHelper.eventsInsert(updatedValues);
                if (id != -1) {
                    updateEventRawTimesLocked(id, updatedValues);
                    mInstancesHelper.updateInstancesLocked(updatedValues, id,
                            true /* new event */, mDb);

                    // If we inserted a new event that specified the self-attendee
                    // status, then we need to add an entry to the attendees table.
                    if (values.containsKey(Events.SELF_ATTENDEE_STATUS)) {
                        int status = values.getAsInteger(Events.SELF_ATTENDEE_STATUS);
                        if (owner == null) {
                            owner = getOwner(calendar_id);
                        }
                        createAttendeeEntry(id, status, owner);
                    }

                    backfillExceptionOriginalIds(id, values);

                    sendUpdateNotification(id, callerIsSyncAdapter);
                }
                break;
            case EXCEPTION_ID:
                long originalEventId = ContentUris.parseId(uri);
                id = handleInsertException(originalEventId, values, callerIsSyncAdapter);
                break;
            case CALENDARS:
                // TODO: verify that all required fields are present
                Integer syncEvents = values.getAsInteger(Calendars.SYNC_EVENTS);
                if (syncEvents != null && syncEvents == 1) {
                    String accountName = values.getAsString(Calendars.ACCOUNT_NAME);
                    String accountType = values.getAsString(
                            Calendars.ACCOUNT_TYPE);
                    final Account account = new Account(accountName, accountType);
                    String eventsUrl = values.getAsString(Calendars.CAL_SYNC1);
                    mDbHelper.scheduleSync(account, false /* two-way sync */, eventsUrl);
                }
                String cal_color_id = values.getAsString(Calendars.CALENDAR_COLOR_KEY);
                if (!TextUtils.isEmpty(cal_color_id)) {
                    String accountName = values.getAsString(Calendars.ACCOUNT_NAME);
                    String accountType = values.getAsString(Calendars.ACCOUNT_TYPE);
                    int color = verifyColorExists(accountName, accountType, cal_color_id,
                            Colors.TYPE_CALENDAR);
                    values.put(Calendars.CALENDAR_COLOR, color);
                }
                id = mDbHelper.calendarsInsert(values);
                sendUpdateNotification(id, callerIsSyncAdapter);
                break;
            case COLORS:
                // verifyTransactionAllowed requires this be from a sync
                // adapter, all of the required fields are marked NOT NULL in
                // the db. TODO Do we need explicit checks here or should we
                // just let sqlite throw if something isn't specified?
                String accountName = uri.getQueryParameter(Colors.ACCOUNT_NAME);
                String accountType = uri.getQueryParameter(Colors.ACCOUNT_TYPE);
                String colorIndex = values.getAsString(Colors.COLOR_KEY);
                if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
                    throw new IllegalArgumentException("Account name and type must be non"
                            + " empty parameters for " + uri);
                }
                if (TextUtils.isEmpty(colorIndex)) {
                    throw new IllegalArgumentException("COLOR_INDEX must be non empty for " + uri);
                }
                if (!values.containsKey(Colors.COLOR_TYPE) || !values.containsKey(Colors.COLOR)) {
                    throw new IllegalArgumentException(
                            "New colors must contain COLOR_TYPE and COLOR");
                }
                // Make sure the account we're inserting for is the same one the
                // adapter is claiming to be. TODO should we throw if they
                // aren't the same?
                values.put(Colors.ACCOUNT_NAME, accountName);
                values.put(Colors.ACCOUNT_TYPE, accountType);

                // Verify the color doesn't already exist
                Cursor c = null;
                try {
                    final long colorType = values.getAsLong(Colors.COLOR_TYPE);
                    c = getColorByTypeIndex(accountName, accountType, colorType, colorIndex);
                    if (c.getCount() != 0) {
                        throw new IllegalArgumentException("color type " + colorType
                                + " and index " + colorIndex
                                + " already exists for account and type provided");
                    }
                } finally {
                    if (c != null)
                        c.close();
                }
                id = mDbHelper.colorsInsert(values);
                break;
            case ATTENDEES: {
                if (!values.containsKey(Attendees.EVENT_ID)) {
                    throw new IllegalArgumentException("Attendees values must "
                            + "contain an event_id");
                }
                Long eventIdObj = values.getAsLong(Reminders.EVENT_ID);
                if (!doesEventExist(eventIdObj)) {
                    Log.i(TAG, "Trying to insert a attendee to a non-existent event");
                    return null;
                }
                if (!callerIsSyncAdapter) {
                    final Long eventId = values.getAsLong(Attendees.EVENT_ID);
                    mDbHelper.duplicateEvent(eventId);
                    setEventDirty(eventId);
                }
                id = mDbHelper.attendeesInsert(values);

                // Copy the attendee status value to the Events table.
                updateEventAttendeeStatus(mDb, values);
                break;
            }
            case REMINDERS: {
                Long eventIdObj = values.getAsLong(Reminders.EVENT_ID);
                if (eventIdObj == null) {
                    throw new IllegalArgumentException("Reminders values must "
                            + "contain a numeric event_id");
                }
                if (!doesEventExist(eventIdObj)) {
                    Log.i(TAG, "Trying to insert a reminder to a non-existent event");
                    return null;
                }

                if (!callerIsSyncAdapter) {
                    mDbHelper.duplicateEvent(eventIdObj);
                    setEventDirty(eventIdObj);
                }
                id = mDbHelper.remindersInsert(values);

                // We know this event has at least one reminder, so make sure "hasAlarm" is 1.
                setHasAlarm(eventIdObj, 1);

                // Schedule another event alarm, if necessary
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "insertInternal() changing reminder");
                }
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
                break;
            }
            case CALENDAR_ALERTS: {
                Long eventIdObj = values.getAsLong(Reminders.EVENT_ID);
                if (eventIdObj == null) {
                    throw new IllegalArgumentException("CalendarAlerts values must "
                            + "contain a numeric event_id");
                }
                if (!doesEventExist(eventIdObj)) {
                    Log.i(TAG, "Trying to insert an alert to a non-existent event");
                    return null;
                }
                id = mDbHelper.calendarAlertsInsert(values);
                // Note: dirty bit is not set for Alerts because it is not synced.
                // It is generated from Reminders, which is synced.
                break;
            }
            case EXTENDED_PROPERTIES: {
                Long eventIdObj = values.getAsLong(Reminders.EVENT_ID);
                if (eventIdObj == null) {
                    throw new IllegalArgumentException("ExtendedProperties values must "
                            + "contain a numeric event_id");
                }
                if (!doesEventExist(eventIdObj)) {
                    Log.i(TAG, "Trying to insert extended properties to a non-existent event id = "
                            + eventIdObj);
                    return null;
                }
                if (!callerIsSyncAdapter) {
                    final Long eventId = values
                            .getAsLong(CalendarContract.ExtendedProperties.EVENT_ID);
                    mDbHelper.duplicateEvent(eventId);
                    setEventDirty(eventId);
                }
                id = mDbHelper.extendedPropertiesInsert(values);
                break;
            }
            case EMMA:
                // Special target used during code-coverage evaluation.
                handleEmmaRequest(values);
                break;
            case EVENTS_ID:
            case REMINDERS_ID:
            case CALENDAR_ALERTS_ID:
            case EXTENDED_PROPERTIES_ID:
            case INSTANCES:
            case INSTANCES_BY_DAY:
            case EVENT_DAYS:
            case PROVIDER_PROPERTIES:
                throw new UnsupportedOperationException("Cannot insert into that URL: " + uri);
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }

        if (id < 0) {
            return null;
        }
        return ContentUris.withAppendedId(uri, id);
    }

    private boolean doesEventExist(long eventId) {
        return DatabaseUtils.queryNumEntries(mDb, Tables.EVENTS, Events._ID + "=?",
                new String[]{String.valueOf(eventId)}) > 0;
    }

    /**
     * Handles special commands related to EMMA code-coverage testing.
     *
     * @param values Parameters from the caller.
     */
    private static void handleEmmaRequest(ContentValues values) {
        /*
         * This is not part of the public API, so we can't share constants with the CTS
         * test code.
         *
         * Bad requests, or attempting to request EMMA coverage data when the coverage libs
         * aren't linked in, will cause an exception.
         */
        String cmd = values.getAsString("cmd");
        if (cmd.equals("start")) {
            // We'd like to reset the coverage data, but according to FAQ item 3.14 at
            // http://emma.sourceforge.net/faq.html, this isn't possible in 2.0.
            Log.d(TAG, "Emma coverage testing started");
        } else if (cmd.equals("stop")) {
            // Call com.vladium.emma.rt.RT.dumpCoverageData() to cause a data dump.  We
            // may not have been built with EMMA, so we need to do this through reflection.
            String filename = values.getAsString("outputFileName");

            File coverageFile = new File(filename);
            try {
                Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
                Method dumpCoverageMethod = emmaRTClass.getMethod("dumpCoverageData",
                        coverageFile.getClass(), boolean.class, boolean.class);

                dumpCoverageMethod.invoke(null, coverageFile, false /*merge*/,
                        false /*stopDataCollection*/);
                Log.d(TAG, "Emma coverage data written to " + filename);
            } catch (Exception e) {
                throw new RuntimeException("Emma coverage dump failed", e);
            }
        }
    }

    /**
     * Validates the recurrence rule, if any.  We allow single- and multi-rule RRULEs.
     * <p>
     * TODO: Validate RDATE, EXRULE, EXDATE (possibly passing in an indication of whether we
     * believe we have the full set, so we can reject EXRULE when not accompanied by RRULE).
     *
     * @return A boolean indicating successful validation.
     */
    private boolean validateRecurrenceRule(ContentValues values) {
        String rrule = values.getAsString(Events.RRULE);

        if (!TextUtils.isEmpty(rrule)) {
            String[] ruleList = rrule.split("\n");
            for (String recur : ruleList) {
                EventRecurrence er = new EventRecurrence();
                try {
                    er.parse(recur);
                } catch (EventRecurrence.InvalidFormatException ife) {
                    Log.w(TAG, "Invalid recurrence rule: " + recur);
                    dumpEventNoPII(values);
                    return false;
                }
            }
        }

        return true;
    }

    private void dumpEventNoPII(ContentValues values) {
        if (values == null) {
            return;
        }

        StringBuilder bob = new StringBuilder();
        bob.append("dtStart:       ").append(values.getAsLong(Events.DTSTART));
        bob.append("\ndtEnd:         ").append(values.getAsLong(Events.DTEND));
        bob.append("\nall_day:       ").append(values.getAsInteger(Events.ALL_DAY));
        bob.append("\ntz:            ").append(values.getAsString(Events.EVENT_TIMEZONE));
        bob.append("\ndur:           ").append(values.getAsString(Events.DURATION));
        bob.append("\nrrule:         ").append(values.getAsString(Events.RRULE));
        bob.append("\nrdate:         ").append(values.getAsString(Events.RDATE));
        bob.append("\nlast_date:     ").append(values.getAsLong(Events.LAST_DATE));

        bob.append("\nid:            ").append(values.getAsLong(Events._ID));
        bob.append("\nsync_id:       ").append(values.getAsString(Events._SYNC_ID));
        bob.append("\nori_id:        ").append(values.getAsLong(Events.ORIGINAL_ID));
        bob.append("\nori_sync_id:   ").append(values.getAsString(Events.ORIGINAL_SYNC_ID));
        bob.append("\nori_inst_time: ").append(values.getAsLong(Events.ORIGINAL_INSTANCE_TIME));
        bob.append("\nori_all_day:   ").append(values.getAsInteger(Events.ORIGINAL_ALL_DAY));

        Log.i(TAG, bob.toString());
    }

    /**
     * Do some scrubbing on event data before inserting or updating. In particular make
     * dtend, duration, etc make sense for the type of event (regular, recurrence, exception).
     * Remove any unexpected fields.
     *
     * @param values the ContentValues to insert.
     * @param modValues if non-null, explicit null entries will be added here whenever something
     *   is removed from <strong>values</strong>.
     */
    private void scrubEventData(ContentValues values, ContentValues modValues) {
        boolean hasDtend = values.getAsLong(Events.DTEND) != null;
        boolean hasDuration = !TextUtils.isEmpty(values.getAsString(Events.DURATION));
        boolean hasRrule = !TextUtils.isEmpty(values.getAsString(Events.RRULE));
        boolean hasRdate = !TextUtils.isEmpty(values.getAsString(Events.RDATE));
        boolean hasOriginalEvent = !TextUtils.isEmpty(values.getAsString(Events.ORIGINAL_SYNC_ID));
        boolean hasOriginalInstanceTime = values.getAsLong(Events.ORIGINAL_INSTANCE_TIME) != null;
        if (hasRrule || hasRdate) {
            // Recurrence:
            // dtstart is start time of first event
            // dtend is null
            // duration is the duration of the event
            // rrule is a valid recurrence rule
            // lastDate is the end of the last event or null if it repeats forever
            // originalEvent is null
            // originalInstanceTime is null
            if (!validateRecurrenceRule(values)) {
                throw new IllegalArgumentException("Invalid recurrence rule: " +
                        values.getAsString(Events.RRULE));
            }
            if (hasDtend || !hasDuration || hasOriginalEvent || hasOriginalInstanceTime) {
                Log.d(TAG, "Scrubbing DTEND, ORIGINAL_SYNC_ID, ORIGINAL_INSTANCE_TIME");
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Invalid values for recurrence: " + values);
                }
                values.remove(Events.DTEND);
                values.remove(Events.ORIGINAL_SYNC_ID);
                values.remove(Events.ORIGINAL_INSTANCE_TIME);
                if (modValues != null) {
                    modValues.putNull(Events.DTEND);
                    modValues.putNull(Events.ORIGINAL_SYNC_ID);
                    modValues.putNull(Events.ORIGINAL_INSTANCE_TIME);
                }
            }
        } else if (hasOriginalEvent || hasOriginalInstanceTime) {
            // Recurrence exception
            // dtstart is start time of exception event
            // dtend is end time of exception event
            // duration is null
            // rrule is null
            // lastdate is same as dtend
            // originalEvent is the _sync_id of the recurrence
            // originalInstanceTime is the start time of the event being replaced
            if (!hasDtend || hasDuration || !hasOriginalEvent || !hasOriginalInstanceTime) {
                Log.d(TAG, "Scrubbing DURATION");
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Invalid values for recurrence exception: " + values);
                }
                values.remove(Events.DURATION);
                if (modValues != null) {
                    modValues.putNull(Events.DURATION);
                }
            }
        } else {
            // Regular event
            // dtstart is the start time
            // dtend is the end time
            // duration is null
            // rrule is null
            // lastDate is the same as dtend
            // originalEvent is null
            // originalInstanceTime is null
            if (!hasDtend || hasDuration) {
                Log.d(TAG, "Scrubbing DURATION");
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Invalid values for event: " + values);
                }
                values.remove(Events.DURATION);
                if (modValues != null) {
                    modValues.putNull(Events.DURATION);
                }
            }
        }
    }

    /**
     * Validates event data.  Pass in the full set of values for the event (i.e. not just
     * a part that's being updated).
     *
     * @param values Event data.
     * @throws IllegalArgumentException if bad data is found.
     */
    private void validateEventData(ContentValues values) {
        if (TextUtils.isEmpty(values.getAsString(Events.CALENDAR_ID))) {
            throw new IllegalArgumentException("Event values must include a calendar_id");
        }
        if (TextUtils.isEmpty(values.getAsString(Events.EVENT_TIMEZONE))) {
            throw new IllegalArgumentException("Event values must include an eventTimezone");
        }

        boolean hasDtstart = values.getAsLong(Events.DTSTART) != null;
        boolean hasDtend = values.getAsLong(Events.DTEND) != null;
        boolean hasDuration = !TextUtils.isEmpty(values.getAsString(Events.DURATION));
        boolean hasRrule = !TextUtils.isEmpty(values.getAsString(Events.RRULE));
        boolean hasRdate = !TextUtils.isEmpty(values.getAsString(Events.RDATE));
        if (hasRrule || hasRdate) {
            if (!validateRecurrenceRule(values)) {
                throw new IllegalArgumentException("Invalid recurrence rule: " +
                        values.getAsString(Events.RRULE));
            }
        }

        if (!hasDtstart) {
            dumpEventNoPII(values);
            throw new IllegalArgumentException("DTSTART cannot be empty.");
        }
        if (!hasDuration && !hasDtend) {
            dumpEventNoPII(values);
            throw new IllegalArgumentException("DTEND and DURATION cannot both be null for " +
                    "an event.");
        }
        if (hasDuration && hasDtend) {
            dumpEventNoPII(values);
            throw new IllegalArgumentException("Cannot have both DTEND and DURATION in an event");
        }
    }

    private void setEventDirty(long eventId) {
        final String mutators = DatabaseUtils.stringForQuery(
                mDb,
                SQL_QUERY_EVENT_MUTATORS,
                new String[]{String.valueOf(eventId)});
        final String packageName = getCallingPackageName();
        final String newMutators;
        if (TextUtils.isEmpty(mutators)) {
            newMutators = packageName;
        } else  {
            final String[] strings = mutators.split(",");
            boolean found = false;
            for (String string : strings) {
                if (string.equals(packageName)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                newMutators = mutators + "," + packageName;
            } else {
                newMutators = mutators;
            }
        }
        mDb.execSQL(SQL_UPDATE_EVENT_SET_DIRTY_AND_MUTATORS,
                new Object[] {newMutators, eventId});
    }

    private long getOriginalId(String originalSyncId, String calendarId) {
        if (TextUtils.isEmpty(originalSyncId) || TextUtils.isEmpty(calendarId)) {
            return -1;
        }
        // Get the original id for this event
        long originalId = -1;
        Cursor c = null;
        try {
            c = query(Events.CONTENT_URI, ID_ONLY_PROJECTION,
                    Events._SYNC_ID + "=?"  + " AND " + Events.CALENDAR_ID + "=?",
                    new String[] {originalSyncId, calendarId}, null);
            if (c != null && c.moveToFirst()) {
                originalId = c.getLong(0);
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return originalId;
    }

    private String getOriginalSyncId(long originalId) {
        if (originalId == -1) {
            return null;
        }
        // Get the original id for this event
        String originalSyncId = null;
        Cursor c = null;
        try {
            c = query(Events.CONTENT_URI, new String[] {Events._SYNC_ID},
                    Events._ID + "=?", new String[] {Long.toString(originalId)}, null);
            if (c != null && c.moveToFirst()) {
                originalSyncId = c.getString(0);
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return originalSyncId;
    }

    private Cursor getColorByTypeIndex(String accountName, String accountType, long colorType,
            String colorIndex) {
        return mDb.query(Tables.COLORS, COLORS_PROJECTION, COLOR_FULL_SELECTION, new String[] {
                accountName, accountType, Long.toString(colorType), colorIndex
        }, null, null, null);
    }

    /**
     * Gets a calendar's "owner account", i.e. the e-mail address of the owner of the calendar.
     *
     * @param calId The calendar ID.
     * @return email of owner or null
     */
    private String getOwner(long calId) {
        if (calId < 0) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "Calendar Id is not valid: " + calId);
            }
            return null;
        }
        // Get the email address of this user from this Calendar
        String emailAddress = null;
        Cursor cursor = null;
        try {
            cursor = query(ContentUris.withAppendedId(Calendars.CONTENT_URI, calId),
                    new String[] { Calendars.OWNER_ACCOUNT },
                    null /* selection */,
                    null /* selectionArgs */,
                    null /* sort */);
            if (cursor == null || !cursor.moveToFirst()) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Couldn't find " + calId + " in Calendars table");
                }
                return null;
            }
            emailAddress = cursor.getString(0);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return emailAddress;
    }

    private Account getAccount(long calId) {
        Account account = null;
        Cursor cursor = null;
        try {
            cursor = query(ContentUris.withAppendedId(Calendars.CONTENT_URI, calId),
                    ACCOUNT_PROJECTION, null /* selection */, null /* selectionArgs */,
                    null /* sort */);
            if (cursor == null || !cursor.moveToFirst()) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Couldn't find " + calId + " in Calendars table");
                }
                return null;
            }
            account = new Account(cursor.getString(ACCOUNT_NAME_INDEX),
                    cursor.getString(ACCOUNT_TYPE_INDEX));
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return account;
    }

    /**
     * Creates an entry in the Attendees table that refers to the given event
     * and that has the given response status.
     *
     * @param eventId the event id that the new entry in the Attendees table
     * should refer to
     * @param status the response status
     * @param emailAddress the email of the attendee
     */
    private void createAttendeeEntry(long eventId, int status, String emailAddress) {
        ContentValues values = new ContentValues();
        values.put(Attendees.EVENT_ID, eventId);
        values.put(Attendees.ATTENDEE_STATUS, status);
        values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
        // TODO: The relationship could actually be ORGANIZER, but it will get straightened out
        // on sync.
        values.put(Attendees.ATTENDEE_RELATIONSHIP,
                Attendees.RELATIONSHIP_ATTENDEE);
        values.put(Attendees.ATTENDEE_EMAIL, emailAddress);

        // We don't know the ATTENDEE_NAME but that will be filled in by the
        // server and sent back to us.
        mDbHelper.attendeesInsert(values);
    }

    /**
     * Updates the attendee status in the Events table to be consistent with
     * the value in the Attendees table.
     *
     * @param db the database
     * @param attendeeValues the column values for one row in the Attendees table.
     */
    private void updateEventAttendeeStatus(SQLiteDatabase db, ContentValues attendeeValues) {
        // Get the event id for this attendee
        Long eventIdObj = attendeeValues.getAsLong(Attendees.EVENT_ID);
        if (eventIdObj == null) {
            Log.w(TAG, "Attendee update values don't include an event_id");
            return;
        }
        long eventId = eventIdObj;

        if (MULTIPLE_ATTENDEES_PER_EVENT) {
            // Get the calendar id for this event
            Cursor cursor = null;
            long calId;
            try {
                cursor = query(ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
                        new String[] { Events.CALENDAR_ID },
                        null /* selection */,
                        null /* selectionArgs */,
                        null /* sort */);
                if (cursor == null || !cursor.moveToFirst()) {
                    if (Log.isLoggable(TAG, Log.DEBUG)) {
                        Log.d(TAG, "Couldn't find " + eventId + " in Events table");
                    }
                    return;
                }
                calId = cursor.getLong(0);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }

            // Get the owner email for this Calendar
            String calendarEmail = null;
            cursor = null;
            try {
                cursor = query(ContentUris.withAppendedId(Calendars.CONTENT_URI, calId),
                        new String[] { Calendars.OWNER_ACCOUNT },
                        null /* selection */,
                        null /* selectionArgs */,
                        null /* sort */);
                if (cursor == null || !cursor.moveToFirst()) {
                    if (Log.isLoggable(TAG, Log.DEBUG)) {
                        Log.d(TAG, "Couldn't find " + calId + " in Calendars table");
                    }
                    return;
                }
                calendarEmail = cursor.getString(0);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }

            if (calendarEmail == null) {
                return;
            }

            // Get the email address for this attendee
            String attendeeEmail = null;
            if (attendeeValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
                attendeeEmail = attendeeValues.getAsString(Attendees.ATTENDEE_EMAIL);
            }

            // If the attendee email does not match the calendar email, then this
            // attendee is not the owner of this calendar so we don't update the
            // selfAttendeeStatus in the event.
            if (!calendarEmail.equals(attendeeEmail)) {
                return;
            }
        }

        // Select a default value for "status" based on the relationship.
        int status = Attendees.ATTENDEE_STATUS_NONE;
        Integer relationObj = attendeeValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
        if (relationObj != null) {
            int rel = relationObj;
            if (rel == Attendees.RELATIONSHIP_ORGANIZER) {
                status = Attendees.ATTENDEE_STATUS_ACCEPTED;
            }
        }

        // If the status is specified, use that.
        Integer statusObj = attendeeValues.getAsInteger(Attendees.ATTENDEE_STATUS);
        if (statusObj != null) {
            status = statusObj;
        }

        ContentValues values = new ContentValues();
        values.put(Events.SELF_ATTENDEE_STATUS, status);
        db.update(Tables.EVENTS, values, SQL_WHERE_ID,
                new String[] {String.valueOf(eventId)});
    }

    /**
     * Set the "hasAlarm" column in the database.
     *
     * @param eventId The _id of the Event to update.
     * @param val The value to set it to (0 or 1).
     */
    private void setHasAlarm(long eventId, int val) {
        ContentValues values = new ContentValues();
        values.put(Events.HAS_ALARM, val);
        int count = mDb.update(Tables.EVENTS, values, SQL_WHERE_ID,
                new String[] { String.valueOf(eventId) });
        if (count != 1) {
            Log.w(TAG, "setHasAlarm on event " + eventId + " updated " + count +
                    " rows (expected 1)");
        }
    }

    /**
     * Calculates the "last date" of the event.  For a regular event this is the start time
     * plus the duration.  For a recurring event this is the start date of the last event in
     * the recurrence, plus the duration.  The event recurs forever, this returns -1.  If
     * the recurrence rule can't be parsed, this returns -1.
     *
     * @param values
     * @return the date, in milliseconds, since the start of the epoch (UTC), or -1 if an
     *   exceptional condition exists.
     * @throws DateException
     */
    long calculateLastDate(ContentValues values)
            throws DateException {
        // Allow updates to some event fields like the title or hasAlarm
        // without requiring DTSTART.
        if (!values.containsKey(Events.DTSTART)) {
            if (values.containsKey(Events.DTEND) || values.containsKey(Events.RRULE)
                    || values.containsKey(Events.DURATION)
                    || values.containsKey(Events.EVENT_TIMEZONE)
                    || values.containsKey(Events.RDATE)
                    || values.containsKey(Events.EXRULE)
                    || values.containsKey(Events.EXDATE)) {
                throw new RuntimeException("DTSTART field missing from event");
            }
            return -1;
        }
        long dtstartMillis = values.getAsLong(Events.DTSTART);
        long lastMillis = -1;

        // Can we use dtend with a repeating event?  What does that even
        // mean?
        // NOTE: if the repeating event has a dtend, we convert it to a
        // duration during event processing, so this situation should not
        // occur.
        Long dtEnd = values.getAsLong(Events.DTEND);
        if (dtEnd != null) {
            lastMillis = dtEnd;
        } else {
            // find out how long it is
            Duration duration = new Duration();
            String durationStr = values.getAsString(Events.DURATION);
            if (durationStr != null) {
                duration.parse(durationStr);
            }

            RecurrenceSet recur = null;
            try {
                recur = new RecurrenceSet(values);
            } catch (EventRecurrence.InvalidFormatException e) {
                if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "Could not parse RRULE recurrence string: " +
                            values.get(CalendarContract.Events.RRULE), e);
                }
                // TODO: this should throw an exception or return a distinct error code
                return lastMillis; // -1
            }

            if (null != recur && recur.hasRecurrence()) {
                // the event is repeating, so find the last date it
                // could appear on

                String tz = values.getAsString(Events.EVENT_TIMEZONE);

                if (TextUtils.isEmpty(tz)) {
                    // floating timezone
                    tz = Time.TIMEZONE_UTC;
                }
                Time dtstartLocal = new Time(tz);

                dtstartLocal.set(dtstartMillis);

                RecurrenceProcessor rp = new RecurrenceProcessor();
                lastMillis = rp.getLastOccurence(dtstartLocal, recur);
                if (lastMillis == -1) {
                    // repeats forever
                    return lastMillis;  // -1
                }
            } else {
                // the event is not repeating, just use dtstartMillis
                lastMillis = dtstartMillis;
            }

            // that was the beginning of the event.  this is the end.
            lastMillis = duration.addTo(lastMillis);
        }
        return lastMillis;
    }

    /**
     * Add LAST_DATE to values.
     * @param values the ContentValues (in/out); must include DTSTART and, if the event is
     *   recurring, the columns necessary to process a recurrence rule (RRULE, DURATION,
     *   EVENT_TIMEZONE, etc).
     * @return values on success, null on failure
     */
    private ContentValues updateLastDate(ContentValues values) {
        try {
            long last = calculateLastDate(values);
            if (last != -1) {
                values.put(Events.LAST_DATE, last);
            }

            return values;
        } catch (DateException e) {
            // don't add it if there was an error
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Could not calculate last date.", e);
            }
            return null;
        }
    }

    /**
     * Creates or updates an entry in the EventsRawTimes table.
     *
     * @param eventId The ID of the event that was just created or is being updated.
     * @param values For a new event, the full set of event values; for an updated event,
     *   the set of values that are being changed.
     */
    private void updateEventRawTimesLocked(long eventId, ContentValues values) {
        ContentValues rawValues = new ContentValues();

        rawValues.put(CalendarContract.EventsRawTimes.EVENT_ID, eventId);

        String timezone = values.getAsString(Events.EVENT_TIMEZONE);

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

        if (allDay || TextUtils.isEmpty(timezone)) {
            // floating timezone
            timezone = Time.TIMEZONE_UTC;
        }

        Time time = new Time(timezone);
        time.allDay = allDay;
        Long dtstartMillis = values.getAsLong(Events.DTSTART);
        if (dtstartMillis != null) {
            time.set(dtstartMillis);
            rawValues.put(CalendarContract.EventsRawTimes.DTSTART_2445, time.format2445());
        }

        Long dtendMillis = values.getAsLong(Events.DTEND);
        if (dtendMillis != null) {
            time.set(dtendMillis);
            rawValues.put(CalendarContract.EventsRawTimes.DTEND_2445, time.format2445());
        }

        Long originalInstanceMillis = values.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
        if (originalInstanceMillis != null) {
            // This is a recurrence exception so we need to get the all-day
            // status of the original recurring event in order to format the
            // date correctly.
            allDayInteger = values.getAsInteger(Events.ORIGINAL_ALL_DAY);
            if (allDayInteger != null) {
                time.allDay = allDayInteger != 0;
            }
            time.set(originalInstanceMillis);
            rawValues.put(CalendarContract.EventsRawTimes.ORIGINAL_INSTANCE_TIME_2445,
                    time.format2445());
        }

        Long lastDateMillis = values.getAsLong(Events.LAST_DATE);
        if (lastDateMillis != null) {
            time.allDay = allDay;
            time.set(lastDateMillis);
            rawValues.put(CalendarContract.EventsRawTimes.LAST_DATE_2445, time.format2445());
        }

        mDbHelper.eventsRawTimesReplace(rawValues);
    }

    @Override
    protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
            boolean callerIsSyncAdapter) {
        final int callingUid = mCallingUid.get();
        mStats.incrementDeleteStats(callingUid, applyingBatch());
        try {
            return deleteInTransactionInner(uri, selection, selectionArgs, callerIsSyncAdapter);
        } finally {
            mStats.finishOperation(callingUid);
        }
    }

    private int deleteInTransactionInner(Uri uri, String selection, String[] selectionArgs,
            boolean callerIsSyncAdapter) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "deleteInTransaction: " + uri);
        }
        CalendarSanityChecker.getInstance(mContext).checkLastCheckTime();

        validateUriParameters(uri.getQueryParameterNames());
        final int match = sUriMatcher.match(uri);
        verifyTransactionAllowed(TRANSACTION_DELETE, uri, null, callerIsSyncAdapter, match,
                selection, selectionArgs);
        mDb = mDbHelper.getWritableDatabase();

        switch (match) {
            case SYNCSTATE:
                return mDbHelper.getSyncState().delete(mDb, selection, selectionArgs);

            case SYNCSTATE_ID:
                String selectionWithId = (SyncState._ID + "=?")
                        + (selection == null ? "" : " AND (" + selection + ")");
                // Prepend id to selectionArgs
                selectionArgs = insertSelectionArg(selectionArgs,
                        String.valueOf(ContentUris.parseId(uri)));
                return mDbHelper.getSyncState().delete(mDb, selectionWithId,
                        selectionArgs);

            case COLORS:
                return deleteMatchingColors(appendAccountToSelection(uri, selection,
                        Calendars.ACCOUNT_NAME, Calendars.ACCOUNT_TYPE),
                        selectionArgs);

            case EVENTS:
            {
                int result = 0;
                selection = appendAccountToSelection(
                        uri, selection, Events.ACCOUNT_NAME, Events.ACCOUNT_TYPE);

                // Query this event to get the ids to delete.
                Cursor cursor = mDb.query(Views.EVENTS, ID_ONLY_PROJECTION,
                        selection, selectionArgs, null /* groupBy */,
                        null /* having */, null /* sortOrder */);
                try {
                    while (cursor.moveToNext()) {
                        long id = cursor.getLong(0);
                        result += deleteEventInternal(id, callerIsSyncAdapter, true /* isBatch */);
                    }
                    mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
                    sendUpdateNotification(callerIsSyncAdapter);
                } finally {
                    cursor.close();
                    cursor = null;
                }
                return result;
            }
            case EVENTS_ID:
            {
                long id = ContentUris.parseId(uri);
                return deleteEventInternal(id, callerIsSyncAdapter, false /* isBatch */);
            }
            case EXCEPTION_ID2:
            {
                // This will throw NumberFormatException on missing or malformed input.
                List<String> segments = uri.getPathSegments();
                long eventId = Long.parseLong(segments.get(1));
                long excepId = Long.parseLong(segments.get(2));
                // TODO: verify that this is an exception instance (has an ORIGINAL_ID field
                //       that matches the supplied eventId)
                return deleteEventInternal(excepId, callerIsSyncAdapter, false /* isBatch */);
            }
            case ATTENDEES:
            {
                if (callerIsSyncAdapter) {
                    return mDb.delete(Tables.ATTENDEES, selection, selectionArgs);
                } else {
                    return deleteFromEventRelatedTable(Tables.ATTENDEES, uri, selection,
                            selectionArgs);
                }
            }
            case ATTENDEES_ID:
            {
                if (callerIsSyncAdapter) {
                    long id = ContentUris.parseId(uri);
                    return mDb.delete(Tables.ATTENDEES, SQL_WHERE_ID,
                            new String[] {String.valueOf(id)});
                } else {
                    return deleteFromEventRelatedTable(Tables.ATTENDEES, uri, null /* selection */,
                                           null /* selectionArgs */);
                }
            }
            case REMINDERS:
            {
                return deleteReminders(uri, false, selection, selectionArgs, callerIsSyncAdapter);
            }
            case REMINDERS_ID:
            {
                return deleteReminders(uri, true, null /*selection*/, null /*selectionArgs*/,
                        callerIsSyncAdapter);
            }
            case EXTENDED_PROPERTIES:
            {
                if (callerIsSyncAdapter) {
                    return mDb.delete(Tables.EXTENDED_PROPERTIES, selection, selectionArgs);
                } else {
                    return deleteFromEventRelatedTable(Tables.EXTENDED_PROPERTIES, uri, selection,
                            selectionArgs);
                }
            }
            case EXTENDED_PROPERTIES_ID:
            {
                if (callerIsSyncAdapter) {
                    long id = ContentUris.parseId(uri);
                    return mDb.delete(Tables.EXTENDED_PROPERTIES, SQL_WHERE_ID,
                            new String[] {String.valueOf(id)});
                } else {
                    return deleteFromEventRelatedTable(Tables.EXTENDED_PROPERTIES, uri,
                            null /* selection */, null /* selectionArgs */);
                }
            }
            case CALENDAR_ALERTS:
            {
                if (callerIsSyncAdapter) {
                    return mDb.delete(Tables.CALENDAR_ALERTS, selection, selectionArgs);
                } else {
                    return deleteFromEventRelatedTable(Tables.CALENDAR_ALERTS, uri, selection,
                            selectionArgs);
                }
            }
            case CALENDAR_ALERTS_ID:
            {
                // Note: dirty bit is not set for Alerts because it is not synced.
                // It is generated from Reminders, which is synced.
                long id = ContentUris.parseId(uri);
                return mDb.delete(Tables.CALENDAR_ALERTS, SQL_WHERE_ID,
                        new String[] {String.valueOf(id)});
            }
            case CALENDARS_ID:
                StringBuilder selectionSb = new StringBuilder(Calendars._ID + "=");
                selectionSb.append(uri.getPathSegments().get(1));
                if (!TextUtils.isEmpty(selection)) {
                    selectionSb.append(" AND (");
                    selectionSb.append(selection);
                    selectionSb.append(')');
                }
                selection = selectionSb.toString();
                // $FALL-THROUGH$ - fall through to CALENDARS for the actual delete
            case CALENDARS:
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                return deleteMatchingCalendars(selection, selectionArgs);
            case INSTANCES:
            case INSTANCES_BY_DAY:
            case EVENT_DAYS:
            case PROVIDER_PROPERTIES:
                throw new UnsupportedOperationException("Cannot delete that URL");
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
    }

    private int deleteEventInternal(long id, boolean callerIsSyncAdapter, boolean isBatch) {
        int result = 0;
        String selectionArgs[] = new String[] {String.valueOf(id)};

        // Query this event to get the fields needed for deleting.
        Cursor cursor = mDb.query(Tables.EVENTS, EVENTS_PROJECTION,
                SQL_WHERE_ID, selectionArgs,
                null /* groupBy */,
                null /* having */, null /* sortOrder */);
        try {
            if (cursor.moveToNext()) {
                result = 1;
                String syncId = cursor.getString(EVENTS_SYNC_ID_INDEX);
                boolean emptySyncId = TextUtils.isEmpty(syncId);

                // If this was a recurring event or a recurrence
                // exception, then force a recalculation of the
                // instances.
                String rrule = cursor.getString(EVENTS_RRULE_INDEX);
                String rdate = cursor.getString(EVENTS_RDATE_INDEX);
                String origId = cursor.getString(EVENTS_ORIGINAL_ID_INDEX);
                String origSyncId = cursor.getString(EVENTS_ORIGINAL_SYNC_ID_INDEX);
                if (isRecurrenceEvent(rrule, rdate, origId, origSyncId)) {
                    mMetaData.clearInstanceRange();
                }
                boolean isRecurrence = !TextUtils.isEmpty(rrule) || !TextUtils.isEmpty(rdate);

                // we clean the Events and Attendees table if the caller is CalendarSyncAdapter
                // or if the event is local (no syncId)
                //
                // The EVENTS_CLEANUP_TRIGGER_SQL trigger will remove all associated data
                // (Attendees, Instances, Reminders, etc).
                if (callerIsSyncAdapter || emptySyncId) {
                    mDb.delete(Tables.EVENTS, SQL_WHERE_ID, selectionArgs);

                    // If this is a recurrence, and the event was never synced with the server,
                    // we want to delete any exceptions as well.  (If it has been to the server,
                    // we'll let the sync adapter delete the events explicitly.)  We assume that,
                    // if the recurrence hasn't been synced, the exceptions haven't either.
                    if (isRecurrence && emptySyncId) {
                        mDb.delete(Tables.EVENTS, SQL_WHERE_ORIGINAL_ID, selectionArgs);
                    }
                } else {
                    // Event is on the server, so we "soft delete", i.e. mark as deleted so that
                    // the sync adapter has a chance to tell the server about the deletion.  After
                    // the server sees the change, the sync adapter will do the "hard delete"
                    // (above).
                    ContentValues values = new ContentValues();
                    values.put(Events.DELETED, 1);
                    values.put(Events.DIRTY, 1);
                    addMutator(values, Events.MUTATORS);
                    mDb.update(Tables.EVENTS, values, SQL_WHERE_ID, selectionArgs);

                    // Exceptions that have been synced shouldn't be deleted -- the sync
                    // adapter will take care of that -- but we want to "soft delete" them so
                    // that they will be removed from the instances list.
                    // TODO: this seems to confuse the sync adapter, and leaves you with an
                    //       invisible "ghost" event after the server sync.  Maybe we can fix
                    //       this by making instance generation smarter?  Not vital, since the
                    //       exception instances disappear after the server sync.
                    //mDb.update(Tables.EVENTS, values, SQL_WHERE_ORIGINAL_ID_HAS_SYNC_ID,
                    //        selectionArgs);

                    // It's possible for the original event to be on the server but have
                    // exceptions that aren't.  We want to remove all events with a matching
                    // original_id and an empty _sync_id.
                    mDb.delete(Tables.EVENTS, SQL_WHERE_ORIGINAL_ID_NO_SYNC_ID,
                            selectionArgs);

                    // Delete associated data; attendees, however, are deleted with the actual event
                    //  so that the sync adapter is able to notify attendees of the cancellation.
                    mDb.delete(Tables.INSTANCES, SQL_WHERE_EVENT_ID, selectionArgs);
                    mDb.delete(Tables.EVENTS_RAW_TIMES, SQL_WHERE_EVENT_ID, selectionArgs);
                    mDb.delete(Tables.REMINDERS, SQL_WHERE_EVENT_ID, selectionArgs);
                    mDb.delete(Tables.CALENDAR_ALERTS, SQL_WHERE_EVENT_ID, selectionArgs);
                    mDb.delete(Tables.EXTENDED_PROPERTIES, SQL_WHERE_EVENT_ID,
                            selectionArgs);
                }
            }
        } finally {
            cursor.close();
            cursor = null;
        }

        if (!isBatch) {
            mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
            sendUpdateNotification(callerIsSyncAdapter);
        }
        return result;
    }

    /**
     * Delete rows from an Event-related table (e.g. Attendees) and mark corresponding events
     * as dirty.
     *
     * @param table The table to delete from
     * @param uri The URI specifying the rows
     * @param selection for the query
     * @param selectionArgs for the query
     */
    private int deleteFromEventRelatedTable(String table, Uri uri, String selection,
            String[] selectionArgs) {
        if (table.equals(Tables.EVENTS)) {
            throw new IllegalArgumentException("Don't delete Events with this method "
                    + "(use deleteEventInternal)");
        }

        ContentValues dirtyValues = new ContentValues();
        dirtyValues.put(Events.DIRTY, "1");
        addMutator(dirtyValues, Events.MUTATORS);

        /*
         * Re-issue the delete URI as a query.  Note that, if this is a by-ID request, the ID
         * will be in the URI, not selection/selectionArgs.
         *
         * Note that the query will return data according to the access restrictions,
         * so we don't need to worry about deleting data we don't have permission to read.
         */
        Cursor c = query(uri, ID_PROJECTION, selection, selectionArgs, GENERIC_EVENT_ID);
        int count = 0;
        try {
            long prevEventId = -1;
            while (c.moveToNext()) {
                long id = c.getLong(ID_INDEX);
                long eventId = c.getLong(EVENT_ID_INDEX);
                // Duplicate the event.  As a minor optimization, don't try to duplicate an
                // event that we just duplicated on the previous iteration.
                if (eventId != prevEventId) {
                    mDbHelper.duplicateEvent(eventId);
                }
                mDb.delete(table, SQL_WHERE_ID, new String[]{String.valueOf(id)});
                if (eventId != prevEventId) {
                    mDb.update(Tables.EVENTS, dirtyValues, SQL_WHERE_ID,
                            new String[] { String.valueOf(eventId)} );
                }
                prevEventId = eventId;
                count++;
            }
        } finally {
            c.close();
        }
        return count;
    }

    /**
     * Deletes rows from the Reminders table and marks the corresponding events as dirty.
     * Ensures the hasAlarm column in the Event is updated.
     *
     * @return The number of rows deleted.
     */
    private int deleteReminders(Uri uri, boolean byId, String selection, String[] selectionArgs,
            boolean callerIsSyncAdapter) {
        /*
         * If this is a by-ID URI, make sure we have a good ID.  Also, confirm that the
         * selection is null, since we will be ignoring it.
         */
        long rowId = -1;
        if (byId) {
            if (!TextUtils.isEmpty(selection)) {
                throw new UnsupportedOperationException("Selection not allowed for " + uri);
            }
            rowId = ContentUris.parseId(uri);
            if (rowId < 0) {
                throw new IllegalArgumentException("ID expected but not found in " + uri);
            }
        }

        /*
         * Determine the set of events affected by this operation.  There can be multiple
         * reminders with the same event_id, so to avoid beating up the database with "how many
         * reminders are left" and "duplicate this event" requests, we want to generate a list
         * of affected event IDs and work off that.
         *
         * TODO: use GROUP BY to reduce the number of rows returned in the cursor.  (The content
         * provider query() doesn't take it as an argument.)
         */
        HashSet<Long> eventIdSet = new HashSet<Long>();
        Cursor c = query(uri, new String[] { Attendees.EVENT_ID }, selection, selectionArgs, null);
        try {
            while (c.moveToNext()) {
                eventIdSet.add(c.getLong(0));
            }
        } finally {
            c.close();
        }

        /*
         * If this isn't a sync adapter, duplicate each event (along with its associated tables),
         * and mark each as "dirty".  This is for the benefit of partial-update sync.
         */
        if (!callerIsSyncAdapter) {
            ContentValues dirtyValues = new ContentValues();
            dirtyValues.put(Events.DIRTY, "1");
            addMutator(dirtyValues, Events.MUTATORS);

            Iterator<Long> iter = eventIdSet.iterator();
            while (iter.hasNext()) {
                long eventId = iter.next();
                mDbHelper.duplicateEvent(eventId);
                mDb.update(Tables.EVENTS, dirtyValues, SQL_WHERE_ID,
                        new String[] { String.valueOf(eventId) });
            }
        }

        /*
         * Issue the original deletion request.  If we were called with a by-ID URI, generate
         * a selection.
         */
        if (byId) {
            selection = SQL_WHERE_ID;
            selectionArgs = new String[] { String.valueOf(rowId) };
        }
        int delCount = mDb.delete(Tables.REMINDERS, selection, selectionArgs);

        /*
         * For each event, set "hasAlarm" to zero if we've deleted the last of the reminders.
         * (If the event still has reminders, hasAlarm should already be 1.)  Because we're
         * executing in an exclusive transaction there's no risk of racing against other
         * database updates.
         */
        ContentValues noAlarmValues = new ContentValues();
        noAlarmValues.put(Events.HAS_ALARM, 0);
        Iterator<Long> iter = eventIdSet.iterator();
        while (iter.hasNext()) {
            long eventId = iter.next();

            // Count up the number of reminders still associated with this event.
            Cursor reminders = mDb.query(Tables.REMINDERS, new String[] { GENERIC_ID },
                    SQL_WHERE_EVENT_ID, new String[] { String.valueOf(eventId) },
                    null, null, null);
            int reminderCount = reminders.getCount();
            reminders.close();

            if (reminderCount == 0) {
                mDb.update(Tables.EVENTS, noAlarmValues, SQL_WHERE_ID,
                        new String[] { String.valueOf(eventId) });
            }
        }

        return delCount;
    }

    /**
     * Update rows in a table and, if this is a non-sync-adapter update, mark the corresponding
     * events as dirty.
     * <p>
     * This only works for tables that are associated with an event.  It is assumed that the
     * link to the Event row is a numeric identifier in a column called "event_id".
     *
     * @param uri The original request URI.
     * @param byId Set to true if the URI is expected to include an ID.
     * @param updateValues The new values to apply.  Not all columns need be represented.
     * @param selection For non-by-ID operations, the "where" clause to use.
     * @param selectionArgs For non-by-ID operations, arguments to apply to the "where" clause.
     * @param callerIsSyncAdapter Set to true if the caller is a sync adapter.
     * @return The number of rows updated.
     */
    private int updateEventRelatedTable(Uri uri, String table, boolean byId,
            ContentValues updateValues, String selection, String[] selectionArgs,
            boolean callerIsSyncAdapter)
    {
        /*
         * Confirm that the request has either an ID or a selection, but not both.  It's not
         * actually "wrong" to have both, but it's not useful, and having neither is likely
         * a mistake.
         *
         * If they provided an ID in the URI, convert it to an ID selection.
         */
        if (byId) {
            if (!TextUtils.isEmpty(selection)) {
                throw new UnsupportedOperationException("Selection not allowed for " + uri);
            }
            long rowId = ContentUris.parseId(uri);
            if (rowId < 0) {
                throw new IllegalArgumentException("ID expected but not found in " + uri);
            }
            selection = SQL_WHERE_ID;
            selectionArgs = new String[] { String.valueOf(rowId) };
        } else {
            if (TextUtils.isEmpty(selection)) {
                throw new UnsupportedOperationException("Selection is required for " + uri);
            }
        }

        /*
         * Query the events to update.  We want all the columns from the table, so we us a
         * null projection.
         */
        Cursor c = mDb.query(table, null /*projection*/, selection, selectionArgs,
                null, null, null);
        int count = 0;
        try {
            if (c.getCount() == 0) {
                Log.d(TAG, "No query results for " + uri + ", selection=" + selection +
                        " selectionArgs=" + Arrays.toString(selectionArgs));
                return 0;
            }

            ContentValues dirtyValues = null;
            if (!callerIsSyncAdapter) {
                dirtyValues = new ContentValues();
                dirtyValues.put(Events.DIRTY, "1");
                addMutator(dirtyValues, Events.MUTATORS);
            }

            final int idIndex = c.getColumnIndex(GENERIC_ID);
            final int eventIdIndex = c.getColumnIndex(GENERIC_EVENT_ID);
            if (idIndex < 0 || eventIdIndex < 0) {
                throw new RuntimeException("Lookup on _id/event_id failed for " + uri);
            }

            /*
             * For each row found:
             * - merge original values with update values
             * - update database
             * - if not sync adapter, set "dirty" flag in corresponding event to 1
             * - update Event attendee status
             */
            while (c.moveToNext()) {
                /* copy the original values into a ContentValues, then merge the changes in */
                ContentValues values = new ContentValues();
                DatabaseUtils.cursorRowToContentValues(c, values);
                values.putAll(updateValues);

                long id = c.getLong(idIndex);
                long eventId = c.getLong(eventIdIndex);
                if (!callerIsSyncAdapter) {
                    // Make a copy of the original, so partial-update code can see diff.
                    mDbHelper.duplicateEvent(eventId);
                }
                mDb.update(table, values, SQL_WHERE_ID, new String[] { String.valueOf(id) });
                if (!callerIsSyncAdapter) {
                    mDb.update(Tables.EVENTS, dirtyValues, SQL_WHERE_ID,
                            new String[] { String.valueOf(eventId) });
                }
                count++;

                /*
                 * The Events table has a "selfAttendeeStatus" field that usually mirrors the
                 * "attendeeStatus" column of one row in the Attendees table.  It's the provider's
                 * job to keep these in sync, so we have to check for changes here.  (We have
                 * to do it way down here because this is the only point where we have the
                 * merged Attendees values.)
                 *
                 * It's possible, but not expected, to have multiple Attendees entries with
                 * matching attendeeEmail.  The behavior in this case is not defined.
                 *
                 * We could do this more efficiently for "bulk" updates by caching the Calendar
                 * owner email and checking it here.
                 */
                if (table.equals(Tables.ATTENDEES)) {
                    updateEventAttendeeStatus(mDb, values);
                    sendUpdateNotification(eventId, callerIsSyncAdapter);
                }
            }
        } finally {
            c.close();
        }
        return count;
    }

    private int deleteMatchingColors(String selection, String[] selectionArgs) {
        // query to find all the colors that match, for each
        // - verify no one references it
        // - delete color
        Cursor c = mDb.query(Tables.COLORS, COLORS_PROJECTION, selection, selectionArgs, null,
                null, null);
        if (c == null) {
            return 0;
        }
        try {
            Cursor c2 = null;
            while (c.moveToNext()) {
                String index = c.getString(COLORS_COLOR_INDEX_INDEX);
                String accountName = c.getString(COLORS_ACCOUNT_NAME_INDEX);
                String accountType = c.getString(COLORS_ACCOUNT_TYPE_INDEX);
                boolean isCalendarColor = c.getInt(COLORS_COLOR_TYPE_INDEX) == Colors.TYPE_CALENDAR;
                try {
                    if (isCalendarColor) {
                        c2 = mDb.query(Tables.CALENDARS, ID_ONLY_PROJECTION,
                                SQL_WHERE_CALENDAR_COLOR, new String[] {
                                        accountName, accountType, index
                                }, null, null, null);
                        if (c2.getCount() != 0) {
                            throw new UnsupportedOperationException("Cannot delete color " + index
                                    + ". Referenced by " + c2.getCount() + " calendars.");

                        }
                    } else {
                        c2 = query(Events.CONTENT_URI, ID_ONLY_PROJECTION, SQL_WHERE_EVENT_COLOR,
                                new String[] {accountName, accountType, index}, null);
                        if (c2.getCount() != 0) {
                            throw new UnsupportedOperationException("Cannot delete color " + index
                                    + ". Referenced by " + c2.getCount() + " events.");

                        }
                    }
                } finally {
                    if (c2 != null) {
                        c2.close();
                    }
                }
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return mDb.delete(Tables.COLORS, selection, selectionArgs);
    }

    private int deleteMatchingCalendars(String selection, String[] selectionArgs) {
        // query to find all the calendars that match, for each
        // - delete calendar subscription
        // - delete calendar
        Cursor c = mDb.query(Tables.CALENDARS, sCalendarsIdProjection, selection,
                selectionArgs,
                null /* groupBy */,
                null /* having */,
                null /* sortOrder */);
        if (c == null) {
            return 0;
        }
        try {
            while (c.moveToNext()) {
                long id = c.getLong(CALENDARS_INDEX_ID);
                modifyCalendarSubscription(id, false /* not selected */);
            }
        } finally {
            c.close();
        }
        return mDb.delete(Tables.CALENDARS, selection, selectionArgs);
    }

    private boolean doesEventExistForSyncId(String syncId) {
        if (syncId == null) {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "SyncID cannot be null: " + syncId);
            }
            return false;
        }
        long count = DatabaseUtils.longForQuery(mDb, SQL_SELECT_COUNT_FOR_SYNC_ID,
                new String[] { syncId });
        return (count > 0);
    }

    // Check if an UPDATE with STATUS_CANCEL means that we will need to do an Update (instead of
    // a Deletion)
    //
    // Deletion will be done only and only if:
    // - event status = canceled
    // - event is a recurrence exception that does not have its original (parent) event anymore
    //
    // This is due to the Server semantics that generate STATUS_CANCELED for both creation
    // and deletion of a recurrence exception
    // See bug #3218104
    private boolean doesStatusCancelUpdateMeanUpdate(ContentValues values,
            ContentValues modValues) {
        boolean isStatusCanceled = modValues.containsKey(Events.STATUS) &&
                (modValues.getAsInteger(Events.STATUS) == Events.STATUS_CANCELED);
        if (isStatusCanceled) {
            String originalSyncId = values.getAsString(Events.ORIGINAL_SYNC_ID);

            if (!TextUtils.isEmpty(originalSyncId)) {
                // This event is an exception.  See if the recurring event still exists.
                return doesEventExistForSyncId(originalSyncId);
            }
        }
        // This is the normal case, we just want an UPDATE
        return true;
    }

    private int handleUpdateColors(ContentValues values, String selection, String[] selectionArgs) {
        Cursor c = null;
        int result = mDb.update(Tables.COLORS, values, selection, selectionArgs);
        if (values.containsKey(Colors.COLOR)) {
            try {
                c = mDb.query(Tables.COLORS, COLORS_PROJECTION, selection, selectionArgs,
                        null /* groupBy */, null /* having */, null /* orderBy */);
                while (c.moveToNext()) {
                    boolean calendarColor =
                            c.getInt(COLORS_COLOR_TYPE_INDEX) == Colors.TYPE_CALENDAR;
                    int color = c.getInt(COLORS_COLOR_INDEX);
                    String[] args = {
                            c.getString(COLORS_ACCOUNT_NAME_INDEX),
                            c.getString(COLORS_ACCOUNT_TYPE_INDEX),
                            c.getString(COLORS_COLOR_INDEX_INDEX)
                    };
                    ContentValues colorValue = new ContentValues();
                    if (calendarColor) {
                        colorValue.put(Calendars.CALENDAR_COLOR, color);
                        mDb.update(Tables.CALENDARS, colorValue, SQL_WHERE_CALENDAR_COLOR, args);
                    } else {
                        colorValue.put(Events.EVENT_COLOR, color);
                        mDb.update(Tables.EVENTS, colorValue, SQL_WHERE_EVENT_COLOR, args);
                    }
                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
        }
        return result;
    }


    /**
     * Handles a request to update one or more events.
     * <p>
     * The original event(s) will be loaded from the database, merged with the new values,
     * and the result checked for validity.  In some cases this will alter the supplied
     * arguments (e.g. zeroing out the times on all-day events), change additional fields (e.g.
     * update LAST_DATE when DTSTART changes), or cause modifications to other tables (e.g. reset
     * Instances when a recurrence rule changes).
     *
     * @param cursor The set of events to update.
     * @param updateValues The changes to apply to each event.
     * @param callerIsSyncAdapter Indicates if the request comes from the sync adapter.
     * @return the number of rows updated
     */
    private int handleUpdateEvents(Cursor cursor, ContentValues updateValues,
            boolean callerIsSyncAdapter) {
        /*
         * This field is considered read-only.  It should not be modified by applications or
         * by the sync adapter.
         */
        updateValues.remove(Events.HAS_ALARM);

        /*
         * For a single event, we can just load the event, merge modValues in, perform any
         * fix-ups (putting changes into modValues), check validity, and then update().  We have
         * to be careful that our fix-ups don't confuse the sync adapter.
         *
         * For multiple events, we need to load, merge, and validate each event individually.
         * If no single-event-specific changes need to be made, we could just issue the original
         * bulk update, which would be more efficient than a series of individual updates.
         * However, doing so would prevent us from taking advantage of the partial-update
         * mechanism.
         */
        if (cursor.getCount() > 1) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "Performing update on " + cursor.getCount() + " events");
            }
        }
        while (cursor.moveToNext()) {
            // Make a copy of updateValues so we can make some local changes.
            ContentValues modValues = new ContentValues(updateValues);

            // Load the event into a ContentValues object.
            ContentValues values = new ContentValues();
            DatabaseUtils.cursorRowToContentValues(cursor, values);
            boolean doValidate = false;
            if (!callerIsSyncAdapter) {
                try {
                    // Check to see if the data in the database is valid.  If not, we will skip
                    // validation of the update, so that we don't blow up on attempts to
                    // modify existing badly-formed events.
                    validateEventData(values);
                    doValidate = true;
                } catch (IllegalArgumentException iae) {
                    Log.d(TAG, "Event " + values.getAsString(Events._ID) +
                            " malformed, not validating update (" +
                            iae.getMessage() + ")");
                }
            }

            // Merge the modifications in.
            values.putAll(modValues);

            // If a color_index is being set make sure it's valid
            String color_id = modValues.getAsString(Events.EVENT_COLOR_KEY);
            if (!TextUtils.isEmpty(color_id)) {
                String accountName = null;
                String accountType = null;
                Cursor c = mDb.query(Tables.CALENDARS, ACCOUNT_PROJECTION, SQL_WHERE_ID,
                        new String[] { values.getAsString(Events.CALENDAR_ID) }, null, null, null);
                try {
                    if (c.moveToFirst()) {
                        accountName = c.getString(ACCOUNT_NAME_INDEX);
                        accountType = c.getString(ACCOUNT_TYPE_INDEX);
                    }
                } finally {
                    if (c != null) {
                        c.close();
                    }
                }
                verifyColorExists(accountName, accountType, color_id, Colors.TYPE_EVENT);
            }

            // Scrub and/or validate the combined event.
            if (callerIsSyncAdapter) {
                scrubEventData(values, modValues);
            }
            if (doValidate) {
                validateEventData(values);
            }

            // Look for any updates that could affect LAST_DATE.  It's defined as the end of
            // the last meeting, so we need to pay attention to DURATION.
            if (modValues.containsKey(Events.DTSTART) ||
                    modValues.containsKey(Events.DTEND) ||
                    modValues.containsKey(Events.DURATION) ||
                    modValues.containsKey(Events.EVENT_TIMEZONE) ||
                    modValues.containsKey(Events.RRULE) ||
                    modValues.containsKey(Events.RDATE) ||
                    modValues.containsKey(Events.EXRULE) ||
                    modValues.containsKey(Events.EXDATE)) {
                long newLastDate;
                try {
                    newLastDate = calculateLastDate(values);
                } catch (DateException de) {
                    throw new IllegalArgumentException("Unable to compute LAST_DATE", de);
                }
                Long oldLastDateObj = values.getAsLong(Events.LAST_DATE);
                long oldLastDate = (oldLastDateObj == null) ? -1 : oldLastDateObj;
                if (oldLastDate != newLastDate) {
                    // This overwrites any caller-supplied LAST_DATE.  This is okay, because the
                    // caller isn't supposed to be messing with the LAST_DATE field.
                    if (newLastDate < 0) {
                        modValues.putNull(Events.LAST_DATE);
                    } else {
                        modValues.put(Events.LAST_DATE, newLastDate);
                    }
                }
            }

            if (!callerIsSyncAdapter) {
                modValues.put(Events.DIRTY, 1);
                addMutator(modValues, Events.MUTATORS);
            }

            // Disallow updating the attendee status in the Events
            // table.  In the future, we could support this but we
            // would have to query and update the attendees table
            // to keep the values consistent.
            if (modValues.containsKey(Events.SELF_ATTENDEE_STATUS)) {
                throw new IllegalArgumentException("Updating "
                        + Events.SELF_ATTENDEE_STATUS
                        + " in Events table is not allowed.");
            }

            if (fixAllDayTime(values, modValues)) {
                if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "handleUpdateEvents: " +
                            "allDay is true but sec, min, hour were not 0.");
                }
            }

            // For taking care about recurrences exceptions cancelations, check if this needs
            //  to be an UPDATE or a DELETE
            boolean isUpdate = doesStatusCancelUpdateMeanUpdate(values, modValues);

            long id = values.getAsLong(Events._ID);

            if (isUpdate) {
                // If a user made a change, possibly duplicate the event so we can do a partial
                // update. If a sync adapter made a change and that change marks an event as
                // un-dirty, remove any duplicates that may have been created earlier.
                if (!callerIsSyncAdapter) {
                    mDbHelper.duplicateEvent(id);
                } else {
                    if (modValues.containsKey(Events.DIRTY)
                            && modValues.getAsInteger(Events.DIRTY) == 0) {
                        modValues.put(Events.MUTATORS, (String) null);
                        mDbHelper.removeDuplicateEvent(id);
                    }
                }
                int result = mDb.update(Tables.EVENTS, modValues, SQL_WHERE_ID,
                        new String[] { String.valueOf(id) });
                if (result > 0) {
                    updateEventRawTimesLocked(id, modValues);
                    mInstancesHelper.updateInstancesLocked(modValues, id,
                            false /* not a new event */, mDb);

                    // XXX: should we also be doing this when RRULE changes (e.g. instances
                    //      are introduced or removed?)
                    if (modValues.containsKey(Events.DTSTART) ||
                            modValues.containsKey(Events.STATUS)) {
                        // If this is a cancellation knock it out
                        // of the instances table
                        if (modValues.containsKey(Events.STATUS) &&
                                modValues.getAsInteger(Events.STATUS) == Events.STATUS_CANCELED) {
                            String[] args = new String[] {String.valueOf(id)};
                            mDb.delete(Tables.INSTANCES, SQL_WHERE_EVENT_ID, args);
                        }

                        // The start time or status of the event changed, so run the
                        // event alarm scheduler.
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "updateInternal() changing event");
                        }
                        mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
                    }

                    sendUpdateNotification(id, callerIsSyncAdapter);
                }
            } else {
                deleteEventInternal(id, callerIsSyncAdapter, true /* isBatch */);
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
                sendUpdateNotification(callerIsSyncAdapter);
            }
        }

        return cursor.getCount();
    }

    @Override
    protected int updateInTransaction(Uri uri, ContentValues values, String selection,
            String[] selectionArgs, boolean callerIsSyncAdapter) {
        final int callingUid = mCallingUid.get();
        mStats.incrementUpdateStats(callingUid, applyingBatch());
        try {
            return updateInTransactionInner(uri, values, selection, selectionArgs,
                    callerIsSyncAdapter);
        } finally {
            mStats.finishOperation(callingUid);
        }
    }

    private int updateInTransactionInner(Uri uri, ContentValues values, String selection,
            String[] selectionArgs, boolean callerIsSyncAdapter) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "updateInTransaction: " + uri);
        }
        CalendarSanityChecker.getInstance(mContext).checkLastCheckTime();

        validateUriParameters(uri.getQueryParameterNames());
        final int match = sUriMatcher.match(uri);
        verifyTransactionAllowed(TRANSACTION_UPDATE, uri, values, callerIsSyncAdapter, match,
                selection, selectionArgs);
        mDb = mDbHelper.getWritableDatabase();

        switch (match) {
            case SYNCSTATE:
                return mDbHelper.getSyncState().update(mDb, values,
                        appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                                Calendars.ACCOUNT_TYPE), selectionArgs);

            case SYNCSTATE_ID: {
                selection = appendAccountToSelection(uri, selection, Calendars.ACCOUNT_NAME,
                        Calendars.ACCOUNT_TYPE);
                String selectionWithId = (SyncState._ID + "=?")
                        + (selection == null ? "" : " AND (" + selection + ")");
                // Prepend id to selectionArgs
                selectionArgs = insertSelectionArg(selectionArgs,
                        String.valueOf(ContentUris.parseId(uri)));
                return mDbHelper.getSyncState().update(mDb, values, selectionWithId, selectionArgs);
            }

            case COLORS:
                int validValues = 0;
                if (values.getAsInteger(Colors.COLOR) != null) {
                    validValues++;
                }
                if (values.getAsString(Colors.DATA) != null) {
                    validValues++;
                }

                if (values.size() != validValues) {
                    throw new UnsupportedOperationException("You may only change the COLOR and"
                            + " DATA columns for an existing Colors entry.");
                }
                return handleUpdateColors(values, appendAccountToSelection(uri, selection,
                        Calendars.ACCOUNT_NAME, Calendars.ACCOUNT_TYPE),
                        selectionArgs);

            case CALENDARS:
            case CALENDARS_ID:
            {
                long id;
                if (match == CALENDARS_ID) {
                    id = ContentUris.parseId(uri);
                } else {
                    // TODO: for supporting other sync adapters, we will need to
                    // be able to deal with the following cases:
                    // 1) selection to "_id=?" and pass in a selectionArgs
                    // 2) selection to "_id IN (1, 2, 3)"
                    // 3) selection to "delete=0 AND _id=1"
                    if (selection != null && TextUtils.equals(selection,"_id=?")) {
                        id = Long.parseLong(selectionArgs[0]);
                    } else if (selection != null && selection.startsWith("_id=")) {
                        // The ContentProviderOperation generates an _id=n string instead of
                        // adding the id to the URL, so parse that out here.
                        id = Long.parseLong(selection.substring(4));
                    } else {
                        return mDb.update(Tables.CALENDARS, values, selection, selectionArgs);
                    }
                }
                if (!callerIsSyncAdapter) {
                    values.put(Calendars.DIRTY, 1);
                    addMutator(values, Calendars.MUTATORS);
                } else {
                    if (values.containsKey(Calendars.DIRTY)
                            && values.getAsInteger(Calendars.DIRTY) == 0) {
                        values.put(Calendars.MUTATORS, (String) null);
                    }
                }
                Integer syncEvents = values.getAsInteger(Calendars.SYNC_EVENTS);
                if (syncEvents != null) {
                    modifyCalendarSubscription(id, syncEvents == 1);
                }
                String color_id = values.getAsString(Calendars.CALENDAR_COLOR_KEY);
                if (!TextUtils.isEmpty(color_id)) {
                    String accountName = values.getAsString(Calendars.ACCOUNT_NAME);
                    String accountType = values.getAsString(Calendars.ACCOUNT_TYPE);
                    if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
                        Account account = getAccount(id);
                        if (account != null) {
                            accountName = account.name;
                            accountType = account.type;
                        }
                    }
                    verifyColorExists(accountName, accountType, color_id, Colors.TYPE_CALENDAR);
                }

                int result = mDb.update(Tables.CALENDARS, values, SQL_WHERE_ID,
                        new String[] {String.valueOf(id)});

                if (result > 0) {
                    // if visibility was toggled, we need to update alarms
                    if (values.containsKey(Calendars.VISIBLE)) {
                        // pass false for removeAlarms since the call to
                        // scheduleNextAlarmLocked will remove any alarms for
                        // non-visible events anyways. removeScheduledAlarmsLocked
                        // does not actually have the effect we want
                        mCalendarAlarm.checkNextAlarm(false);
                    }
                    // update the widget
                    sendUpdateNotification(callerIsSyncAdapter);
                }

                return result;
            }
            case EVENTS:
            case EVENTS_ID:
            {
                Cursor events = null;

                // Grab the full set of columns for each selected event.
                // TODO: define a projection with just the data we need (e.g. we don't need to
                //       validate the SYNC_* columns)

                try {
                    if (match == EVENTS_ID) {
                        // Single event, identified by ID.
                        long id = ContentUris.parseId(uri);
                        events = mDb.query(Tables.EVENTS, null /* columns */,
                                SQL_WHERE_ID, new String[] { String.valueOf(id) },
                                null /* groupBy */, null /* having */, null /* sortOrder */);
                    } else {
                        // One or more events, identified by the selection / selectionArgs.
                        events = mDb.query(Tables.EVENTS, null /* columns */,
                                selection, selectionArgs,
                                null /* groupBy */, null /* having */, null /* sortOrder */);
                    }

                    if (events.getCount() == 0) {
                        return 0;
                    }

                    return handleUpdateEvents(events, values, callerIsSyncAdapter);
                } finally {
                    if (events != null) {
                        events.close();
                    }
                }
            }
            case ATTENDEES:
                return updateEventRelatedTable(uri, Tables.ATTENDEES, false, values, selection,
                        selectionArgs, callerIsSyncAdapter);
            case ATTENDEES_ID:
                return updateEventRelatedTable(uri, Tables.ATTENDEES, true, values, null, null,
                        callerIsSyncAdapter);

            case CALENDAR_ALERTS_ID: {
                // Note: dirty bit is not set for Alerts because it is not synced.
                // It is generated from Reminders, which is synced.
                long id = ContentUris.parseId(uri);
                return mDb.update(Tables.CALENDAR_ALERTS, values, SQL_WHERE_ID,
                        new String[] {String.valueOf(id)});
            }
            case CALENDAR_ALERTS: {
                // Note: dirty bit is not set for Alerts because it is not synced.
                // It is generated from Reminders, which is synced.
                return mDb.update(Tables.CALENDAR_ALERTS, values, selection, selectionArgs);
            }

            case REMINDERS:
                return updateEventRelatedTable(uri, Tables.REMINDERS, false, values, selection,
                        selectionArgs, callerIsSyncAdapter);
            case REMINDERS_ID: {
                int count = updateEventRelatedTable(uri, Tables.REMINDERS, true, values, null, null,
                        callerIsSyncAdapter);

                // Reschedule the event alarms because the
                // "minutes" field may have changed.
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "updateInternal() changing reminder");
                }
                mCalendarAlarm.checkNextAlarm(false /* do not remove alarms */);
                return count;
            }

            case EXTENDED_PROPERTIES_ID:
                return updateEventRelatedTable(uri, Tables.EXTENDED_PROPERTIES, true, values,
                        null, null, callerIsSyncAdapter);
            case SCHEDULE_ALARM_REMOVE: {
                mCalendarAlarm.checkNextAlarm(true);
                return 0;
            }

            case PROVIDER_PROPERTIES: {
                if (!selection.equals("key=?")) {
                    throw new UnsupportedOperationException("Selection should be key=? for " + uri);
                }

                List<String> list = Arrays.asList(selectionArgs);

                if (list.contains(CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS)) {
                    throw new UnsupportedOperationException("Invalid selection key: " +
                            CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS + " for " + uri);
                }

                // Before it may be changed, save current Instances timezone for later use
                String timezoneInstancesBeforeUpdate = mCalendarCache.readTimezoneInstances();

                // Update the database with the provided values (this call may change the value
                // of timezone Instances)
                int result = mDb.update(Tables.CALENDAR_CACHE, values, selection, selectionArgs);

                // if successful, do some house cleaning:
                // if the timezone type is set to "home", set the Instances
                // timezone to the previous
                // if the timezone type is set to "auto", set the Instances
                // timezone to the current
                // device one
                // if the timezone Instances is set AND if we are in "home"
                // timezone type, then save the timezone Instance into
                // "previous" too
                if (result > 0) {
                    // If we are changing timezone type...
                    if (list.contains(CalendarCache.KEY_TIMEZONE_TYPE)) {
                        String value = values.getAsString(CalendarCache.COLUMN_NAME_VALUE);
                        if (value != null) {
                            // if we are setting timezone type to "home"
                            if (value.equals(CalendarCache.TIMEZONE_TYPE_HOME)) {
                                String previousTimezone =
                                        mCalendarCache.readTimezoneInstancesPrevious();
                                if (previousTimezone != null) {
                                    mCalendarCache.writeTimezoneInstances(previousTimezone);
                                }
                                // Regenerate Instances if the "home" timezone has changed
                                // and notify widgets
                                if (!timezoneInstancesBeforeUpdate.equals(previousTimezone) ) {
                                    regenerateInstancesTable();
                                    sendUpdateNotification(callerIsSyncAdapter);
                                }
                            }
                            // if we are setting timezone type to "auto"
                            else if (value.equals(CalendarCache.TIMEZONE_TYPE_AUTO)) {
                                String localTimezone = TimeZone.getDefault().getID();
                                mCalendarCache.writeTimezoneInstances(localTimezone);
                                if (!timezoneInstancesBeforeUpdate.equals(localTimezone)) {
                                    regenerateInstancesTable();
                                    sendUpdateNotification(callerIsSyncAdapter);
                                }
                            }
                        }
                    }
                    // If we are changing timezone Instances...
                    else if (list.contains(CalendarCache.KEY_TIMEZONE_INSTANCES)) {
                        // if we are in "home" timezone type...
                        if (isHomeTimezone()) {
                            String timezoneInstances = mCalendarCache.readTimezoneInstances();
                            // Update the previous value
                            mCalendarCache.writeTimezoneInstancesPrevious(timezoneInstances);
                            // Recompute Instances if the "home" timezone has changed
                            // and send notifications to any widgets
                            if (timezoneInstancesBeforeUpdate != null &&
                                    !timezoneInstancesBeforeUpdate.equals(timezoneInstances)) {
                                regenerateInstancesTable();
                                sendUpdateNotification(callerIsSyncAdapter);
                            }
                        }
                    }
                }
                return result;
            }

            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
    }

    /**
     * Verifies that a color with the given index exists for the given Calendar
     * entry.
     *
     * @param accountName The email of the account the color is for
     * @param accountType The type of account the color is for
     * @param colorIndex The color_index being set for the calendar
     * @param colorType The type of color expected (Calendar/Event)
     * @return The color specified by the index
     */
    private int verifyColorExists(String accountName, String accountType, String colorIndex,
            int colorType) {
        if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
            throw new IllegalArgumentException("Cannot set color. A valid account does"
                    + " not exist for this calendar.");
        }
        int color;
        Cursor c = null;
        try {
            c = getColorByTypeIndex(accountName, accountType, colorType, colorIndex);
            if (!c.moveToFirst()) {
                throw new IllegalArgumentException("Color type: " + colorType + " and index "
                        + colorIndex + " does not exist for account.");
            }
            color = c.getInt(COLORS_COLOR_INDEX);
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return color;
    }

    private String appendLastSyncedColumnToSelection(String selection, Uri uri) {
        if (getIsCallerSyncAdapter(uri)) {
            return selection;
        }
        final StringBuilder sb = new StringBuilder();
        sb.append(CalendarContract.Events.LAST_SYNCED).append(" = 0");
        return appendSelection(sb, selection);
    }

    private String appendAccountToSelection(
            Uri uri,
            String selection,
            String accountNameColumn,
            String accountTypeColumn) {
        final String accountName = QueryParameterUtils.getQueryParameter(uri,
                CalendarContract.EventsEntity.ACCOUNT_NAME);
        final String accountType = QueryParameterUtils.getQueryParameter(uri,
                CalendarContract.EventsEntity.ACCOUNT_TYPE);
        if (!TextUtils.isEmpty(accountName)) {
            final StringBuilder sb = new StringBuilder()
                    .append(accountNameColumn)
                    .append("=")
                    .append(DatabaseUtils.sqlEscapeString(accountName))
                    .append(" AND ")
                    .append(accountTypeColumn)
                    .append("=")
                    .append(DatabaseUtils.sqlEscapeString(accountType));
            return appendSelection(sb, selection);
        } else {
            return selection;
        }
    }

    private String appendSelection(StringBuilder sb, String selection) {
        if (!TextUtils.isEmpty(selection)) {
            sb.append(" AND (");
            sb.append(selection);
            sb.append(')');
        }
        return sb.toString();
    }

    /**
     * Verifies that the operation is allowed and throws an exception if it
     * isn't. This defines the limits of a sync adapter call vs an app call.
     * <p>
     * Also rejects calls that have a selection but shouldn't, or that don't have a selection
     * but should.
     *
     * @param type The type of call, {@link #TRANSACTION_QUERY},
     *            {@link #TRANSACTION_INSERT}, {@link #TRANSACTION_UPDATE}, or
     *            {@link #TRANSACTION_DELETE}
     * @param uri
     * @param values
     * @param isSyncAdapter
     */
    private void verifyTransactionAllowed(int type, Uri uri, ContentValues values,
            boolean isSyncAdapter, int uriMatch, String selection, String[] selectionArgs) {
        // Queries are never restricted to app- or sync-adapter-only, and we don't
        // restrict the set of columns that may be accessed.
        if (type == TRANSACTION_QUERY) {
            return;
        }

        if (type == TRANSACTION_UPDATE || type == TRANSACTION_DELETE) {
            // TODO review this list, document in contract.
            if (!TextUtils.isEmpty(selection)) {
                // Only allow selections for the URIs that can reasonably use them.
                // Whitelist of URIs allowed selections
                switch (uriMatch) {
                    case SYNCSTATE:
                    case CALENDARS:
                    case EVENTS:
                    case ATTENDEES:
                    case CALENDAR_ALERTS:
                    case REMINDERS:
                    case EXTENDED_PROPERTIES:
                    case PROVIDER_PROPERTIES:
                    case COLORS:
                        break;
                    default:
                        throw new IllegalArgumentException("Selection not permitted for " + uri);
                }
            } else {
                // Disallow empty selections for some URIs.
                // Blacklist of URIs _not_ allowed empty selections
                switch (uriMatch) {
                    case EVENTS:
                    case ATTENDEES:
                    case REMINDERS:
                    case PROVIDER_PROPERTIES:
                        throw new IllegalArgumentException("Selection must be specified for "
                                + uri);
                    default:
                        break;
                }
            }
        }

        // Only the sync adapter can use these to make changes.
        if (!isSyncAdapter) {
            switch (uriMatch) {
                case SYNCSTATE:
                case SYNCSTATE_ID:
                case EXTENDED_PROPERTIES:
                case EXTENDED_PROPERTIES_ID:
                case COLORS:
                    throw new IllegalArgumentException("Only sync adapters may write using " + uri);
                default:
                    break;
            }
        }

        switch (type) {
            case TRANSACTION_INSERT:
                if (uriMatch == INSTANCES) {
                    throw new UnsupportedOperationException(
                            "Inserting into instances not supported");
                }
                // Check there are no columns restricted to the provider
                verifyColumns(values, uriMatch);
                if (isSyncAdapter) {
                    // check that account and account type are specified
                    verifyHasAccount(uri, selection, selectionArgs);
                } else {
                    // check that sync only columns aren't included
                    verifyNoSyncColumns(values, uriMatch);
                }
                return;
            case TRANSACTION_UPDATE:
                if (uriMatch == INSTANCES) {
                    throw new UnsupportedOperationException("Updating instances not supported");
                }
                // Check there are no columns restricted to the provider
                verifyColumns(values, uriMatch);
                if (isSyncAdapter) {
                    // check that account and account type are specified
                    verifyHasAccount(uri, selection, selectionArgs);
                } else {
                    // check that sync only columns aren't included
                    verifyNoSyncColumns(values, uriMatch);
                }
                return;
            case TRANSACTION_DELETE:
                if (uriMatch == INSTANCES) {
                    throw new UnsupportedOperationException("Deleting instances not supported");
                }
                if (isSyncAdapter) {
                    // check that account and account type are specified
                    verifyHasAccount(uri, selection, selectionArgs);
                }
                return;
        }
    }

    private void verifyHasAccount(Uri uri, String selection, String[] selectionArgs) {
        String accountName = QueryParameterUtils.getQueryParameter(uri, Calendars.ACCOUNT_NAME);
        String accountType = QueryParameterUtils.getQueryParameter(uri,
                Calendars.ACCOUNT_TYPE);
        if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
            if (selection != null && selection.startsWith(ACCOUNT_SELECTION_PREFIX)) {
                accountName = selectionArgs[0];
                accountType = selectionArgs[1];
            }
        }
        if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
            throw new IllegalArgumentException(
                    "Sync adapters must specify an account and account type: " + uri);
        }
    }

    private void verifyColumns(ContentValues values, int uriMatch) {
        if (values == null || values.size() == 0) {
            return;
        }
        String[] columns;
        switch (uriMatch) {
            case EVENTS:
            case EVENTS_ID:
            case EVENT_ENTITIES:
            case EVENT_ENTITIES_ID:
                columns = Events.PROVIDER_WRITABLE_COLUMNS;
                break;
            default:
                columns = PROVIDER_WRITABLE_DEFAULT_COLUMNS;
                break;
        }

        for (int i = 0; i < columns.length; i++) {
            if (values.containsKey(columns[i])) {
                throw new IllegalArgumentException("Only the provider may write to " + columns[i]);
            }
        }
    }

    private void verifyNoSyncColumns(ContentValues values, int uriMatch) {
        if (values == null || values.size() == 0) {
            return;
        }
        String[] syncColumns;
        switch (uriMatch) {
            case CALENDARS:
            case CALENDARS_ID:
            case CALENDAR_ENTITIES:
            case CALENDAR_ENTITIES_ID:
                syncColumns = Calendars.SYNC_WRITABLE_COLUMNS;
                break;
            case EVENTS:
            case EVENTS_ID:
            case EVENT_ENTITIES:
            case EVENT_ENTITIES_ID:
                syncColumns = Events.SYNC_WRITABLE_COLUMNS;
                break;
            default:
                syncColumns = SYNC_WRITABLE_DEFAULT_COLUMNS;
                break;

        }
        for (int i = 0; i < syncColumns.length; i++) {
            if (values.containsKey(syncColumns[i])) {
                throw new IllegalArgumentException("Only sync adapters may write to "
                        + syncColumns[i]);
            }
        }
    }

    private void modifyCalendarSubscription(long id, boolean syncEvents) {
        // get the account, url, and current selected state
        // for this calendar.
        Cursor cursor = query(ContentUris.withAppendedId(Calendars.CONTENT_URI, id),
                new String[] {Calendars.ACCOUNT_NAME, Calendars.ACCOUNT_TYPE,
                        Calendars.CAL_SYNC1, Calendars.SYNC_EVENTS},
                null /* selection */,
                null /* selectionArgs */,
                null /* sort */);

        Account account = null;
        String calendarUrl = null;
        boolean oldSyncEvents = false;
        if (cursor != null) {
            try {
                if (cursor.moveToFirst()) {
                    final String accountName = cursor.getString(0);
                    final String accountType = cursor.getString(1);
                    account = new Account(accountName, accountType);
                    calendarUrl = cursor.getString(2);
                    oldSyncEvents = (cursor.getInt(3) != 0);
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }

        if (account == null) {
            // should not happen?
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Cannot update subscription because account "
                        + "is empty -- should not happen.");
            }
            return;
        }

        if (TextUtils.isEmpty(calendarUrl)) {
            // Passing in a null Url will cause it to not add any extras
            // Should only happen for non-google calendars.
            calendarUrl = null;
        }

        if (oldSyncEvents == syncEvents) {
            // nothing to do
            return;
        }

        // If the calendar is not selected for syncing, then don't download
        // events.
        mDbHelper.scheduleSync(account, !syncEvents, calendarUrl);
    }

    /**
     * Call this to trigger a broadcast of the ACTION_PROVIDER_CHANGED intent.
     * This also provides a timeout, so any calls to this method will be batched
     * over a period of BROADCAST_TIMEOUT_MILLIS defined in this class.
     *
     * @param callerIsSyncAdapter whether or not the update is being triggered by a sync
     */
    private void sendUpdateNotification(boolean callerIsSyncAdapter) {
        // We use -1 to represent an update to all events
        sendUpdateNotification(-1, callerIsSyncAdapter);
    }

    /**
     * Call this to trigger a broadcast of the ACTION_PROVIDER_CHANGED intent with a delay.
     * This also provides a timeout, so any calls to this method will be batched
     * over a period of BROADCAST_TIMEOUT_MILLIS defined in this class.
     *
     * TODO add support for eventId
     *
     * @param eventId the ID of the event that changed, or -1 for no specific event
     * @param callerIsSyncAdapter whether or not the update is being triggered by a sync
     */
    private void sendUpdateNotification(long eventId,
            boolean callerIsSyncAdapter) {
        // We use a much longer delay for sync-related updates, to prevent any
        // receivers from slowing down the sync
        final long delay = callerIsSyncAdapter ?
                SYNC_UPDATE_BROADCAST_TIMEOUT_MILLIS :
                UPDATE_BROADCAST_TIMEOUT_MILLIS;

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "sendUpdateNotification: delay=" + delay);
        }

        mCalendarAlarm.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() + delay,
                PendingIntent.getBroadcast(mContext, 0, createProviderChangedBroadcast(),
                        PendingIntent.FLAG_UPDATE_CURRENT));
    }

    private Intent createProviderChangedBroadcast() {
        return new Intent(Intent.ACTION_PROVIDER_CHANGED, CalendarContract.CONTENT_URI)
                .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING)
                .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
    }

    private static final int TRANSACTION_QUERY = 0;
    private static final int TRANSACTION_INSERT = 1;
    private static final int TRANSACTION_UPDATE = 2;
    private static final int TRANSACTION_DELETE = 3;

    // @formatter:off
    private static final String[] SYNC_WRITABLE_DEFAULT_COLUMNS = new String[] {
        CalendarContract.Calendars.DIRTY,
        CalendarContract.Calendars._SYNC_ID
    };
    private static final String[] PROVIDER_WRITABLE_DEFAULT_COLUMNS = new String[] {
    };
    // @formatter:on

    private static final int EVENTS = 1;
    private static final int EVENTS_ID = 2;
    private static final int INSTANCES = 3;
    private static final int CALENDARS = 4;
    private static final int CALENDARS_ID = 5;
    private static final int ATTENDEES = 6;
    private static final int ATTENDEES_ID = 7;
    private static final int REMINDERS = 8;
    private static final int REMINDERS_ID = 9;
    private static final int EXTENDED_PROPERTIES = 10;
    private static final int EXTENDED_PROPERTIES_ID = 11;
    private static final int CALENDAR_ALERTS = 12;
    private static final int CALENDAR_ALERTS_ID = 13;
    private static final int CALENDAR_ALERTS_BY_INSTANCE = 14;
    private static final int INSTANCES_BY_DAY = 15;
    private static final int SYNCSTATE = 16;
    private static final int SYNCSTATE_ID = 17;
    private static final int EVENT_ENTITIES = 18;
    private static final int EVENT_ENTITIES_ID = 19;
    private static final int EVENT_DAYS = 20;
    private static final int SCHEDULE_ALARM_REMOVE = 22;
    private static final int TIME = 23;
    private static final int CALENDAR_ENTITIES = 24;
    private static final int CALENDAR_ENTITIES_ID = 25;
    private static final int INSTANCES_SEARCH = 26;
    private static final int INSTANCES_SEARCH_BY_DAY = 27;
    private static final int PROVIDER_PROPERTIES = 28;
    private static final int EXCEPTION_ID = 29;
    private static final int EXCEPTION_ID2 = 30;
    private static final int EMMA = 31;
    private static final int COLORS = 32;
    private static final int ENTERPRISE_EVENTS = 33;
    private static final int ENTERPRISE_EVENTS_ID = 34;
    private static final int ENTERPRISE_CALENDARS = 35;
    private static final int ENTERPRISE_CALENDARS_ID = 36;
    private static final int ENTERPRISE_INSTANCES = 37;
    private static final int ENTERPRISE_INSTANCES_BY_DAY = 38;
    private static final int ENTERPRISE_INSTANCES_SEARCH = 39;
    private static final int ENTERPRISE_INSTANCES_SEARCH_BY_DAY = 40;

    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private static final HashMap<String, String> sInstancesProjectionMap;
    private static final HashMap<String, String> sColorsProjectionMap;
    protected static final HashMap<String, String> sCalendarsProjectionMap;
    protected static final HashMap<String, String> sEventsProjectionMap;
    private static final HashMap<String, String> sEventEntitiesProjectionMap;
    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> sCalendarCacheProjectionMap;
    private static final HashMap<String, String> sCountProjectionMap;

    static {
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "instances/when/*/*", INSTANCES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "instances/whenbyday/*/*", INSTANCES_BY_DAY);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "instances/search/*/*/*", INSTANCES_SEARCH);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "instances/searchbyday/*/*/*",
                INSTANCES_SEARCH_BY_DAY);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "instances/groupbyday/*/*", EVENT_DAYS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "events", EVENTS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "events/#", EVENTS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "event_entities", EVENT_ENTITIES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "event_entities/#", EVENT_ENTITIES_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendars", CALENDARS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendars/#", CALENDARS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendar_entities", CALENDAR_ENTITIES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendar_entities/#", CALENDAR_ENTITIES_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "attendees", ATTENDEES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "attendees/#", ATTENDEES_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "reminders", REMINDERS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "reminders/#", REMINDERS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "extendedproperties", EXTENDED_PROPERTIES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "extendedproperties/#",
                EXTENDED_PROPERTIES_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendar_alerts", CALENDAR_ALERTS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendar_alerts/#", CALENDAR_ALERTS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "calendar_alerts/by_instance",
                           CALENDAR_ALERTS_BY_INSTANCE);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "syncstate", SYNCSTATE);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "syncstate/#", SYNCSTATE_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY,
                CalendarAlarmManager.SCHEDULE_ALARM_REMOVE_PATH, SCHEDULE_ALARM_REMOVE);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "time/#", TIME);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "time", TIME);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "properties", PROVIDER_PROPERTIES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "exception/#", EXCEPTION_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "exception/#/#", EXCEPTION_ID2);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "emma", EMMA);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "colors", COLORS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/events", ENTERPRISE_EVENTS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/events/#",
                ENTERPRISE_EVENTS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/calendars",
                ENTERPRISE_CALENDARS);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/calendars/#",
                ENTERPRISE_CALENDARS_ID);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/instances/when/*/*",
                ENTERPRISE_INSTANCES);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/instances/whenbyday/*/*",
                ENTERPRISE_INSTANCES_BY_DAY);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/instances/search/*/*/*",
                ENTERPRISE_INSTANCES_SEARCH);
        sUriMatcher.addURI(CalendarContract.AUTHORITY, "enterprise/instances/searchbyday/*/*/*",
                ENTERPRISE_INSTANCES_SEARCH_BY_DAY);

        /** Contains just BaseColumns._COUNT */
        sCountProjectionMap = new HashMap<String, String>();
        sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*) AS " + BaseColumns._COUNT);

        sColorsProjectionMap = new HashMap<String, String>();
        sColorsProjectionMap.put(Colors._ID, Colors._ID);
        sColorsProjectionMap.put(Colors.DATA, Colors.DATA);
        sColorsProjectionMap.put(Colors.ACCOUNT_NAME, Colors.ACCOUNT_NAME);
        sColorsProjectionMap.put(Colors.ACCOUNT_TYPE, Colors.ACCOUNT_TYPE);
        sColorsProjectionMap.put(Colors.COLOR_KEY, Colors.COLOR_KEY);
        sColorsProjectionMap.put(Colors.COLOR_TYPE, Colors.COLOR_TYPE);
        sColorsProjectionMap.put(Colors.COLOR, Colors.COLOR);

        sCalendarsProjectionMap = new HashMap<String, String>();
        sCalendarsProjectionMap.put(Calendars._ID, Calendars._ID);
        sCalendarsProjectionMap.put(Calendars.ACCOUNT_NAME, Calendars.ACCOUNT_NAME);
        sCalendarsProjectionMap.put(Calendars.ACCOUNT_TYPE, Calendars.ACCOUNT_TYPE);
        sCalendarsProjectionMap.put(Calendars._SYNC_ID, Calendars._SYNC_ID);
        sCalendarsProjectionMap.put(Calendars.DIRTY, Calendars.DIRTY);
        sCalendarsProjectionMap.put(Calendars.MUTATORS, Calendars.MUTATORS);
        sCalendarsProjectionMap.put(Calendars.NAME, Calendars.NAME);
        sCalendarsProjectionMap.put(
                Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_DISPLAY_NAME);
        sCalendarsProjectionMap.put(Calendars.CALENDAR_COLOR, Calendars.CALENDAR_COLOR);
        sCalendarsProjectionMap.put(Calendars.CALENDAR_COLOR_KEY, Calendars.CALENDAR_COLOR_KEY);
        sCalendarsProjectionMap.put(Calendars.CALENDAR_ACCESS_LEVEL,
                Calendars.CALENDAR_ACCESS_LEVEL);
        sCalendarsProjectionMap.put(Calendars.VISIBLE, Calendars.VISIBLE);
        sCalendarsProjectionMap.put(Calendars.SYNC_EVENTS, Calendars.SYNC_EVENTS);
        sCalendarsProjectionMap.put(Calendars.CALENDAR_LOCATION, Calendars.CALENDAR_LOCATION);
        sCalendarsProjectionMap.put(Calendars.CALENDAR_TIME_ZONE, Calendars.CALENDAR_TIME_ZONE);
        sCalendarsProjectionMap.put(Calendars.OWNER_ACCOUNT, Calendars.OWNER_ACCOUNT);
        sCalendarsProjectionMap.put(Calendars.IS_PRIMARY,
                "COALESCE(" + Calendars.IS_PRIMARY + ", "
                        + Calendars.OWNER_ACCOUNT + " = " + Calendars.ACCOUNT_NAME + ") AS "
                        + Calendars.IS_PRIMARY);
        sCalendarsProjectionMap.put(Calendars.CAN_ORGANIZER_RESPOND,
                Calendars.CAN_ORGANIZER_RESPOND);
        sCalendarsProjectionMap.put(Calendars.CAN_MODIFY_TIME_ZONE, Calendars.CAN_MODIFY_TIME_ZONE);
        sCalendarsProjectionMap.put(Calendars.CAN_PARTIALLY_UPDATE, Calendars.CAN_PARTIALLY_UPDATE);
        sCalendarsProjectionMap.put(Calendars.MAX_REMINDERS, Calendars.MAX_REMINDERS);
        sCalendarsProjectionMap.put(Calendars.ALLOWED_REMINDERS, Calendars.ALLOWED_REMINDERS);
        sCalendarsProjectionMap.put(Calendars.ALLOWED_AVAILABILITY, Calendars.ALLOWED_AVAILABILITY);
        sCalendarsProjectionMap.put(Calendars.ALLOWED_ATTENDEE_TYPES,
                Calendars.ALLOWED_ATTENDEE_TYPES);
        sCalendarsProjectionMap.put(Calendars.DELETED, Calendars.DELETED);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC1, Calendars.CAL_SYNC1);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC2, Calendars.CAL_SYNC2);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC3, Calendars.CAL_SYNC3);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC4, Calendars.CAL_SYNC4);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC5, Calendars.CAL_SYNC5);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC6, Calendars.CAL_SYNC6);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC7, Calendars.CAL_SYNC7);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC8, Calendars.CAL_SYNC8);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC9, Calendars.CAL_SYNC9);
        sCalendarsProjectionMap.put(Calendars.CAL_SYNC10, Calendars.CAL_SYNC10);

        sEventsProjectionMap = new HashMap<String, String>();
        // Events columns
        sEventsProjectionMap.put(Events.ACCOUNT_NAME, Events.ACCOUNT_NAME);
        sEventsProjectionMap.put(Events.ACCOUNT_TYPE, Events.ACCOUNT_TYPE);
        sEventsProjectionMap.put(Events.TITLE, Events.TITLE);
        sEventsProjectionMap.put(Events.EVENT_LOCATION, Events.EVENT_LOCATION);
        sEventsProjectionMap.put(Events.DESCRIPTION, Events.DESCRIPTION);
        sEventsProjectionMap.put(Events.STATUS, Events.STATUS);
        sEventsProjectionMap.put(Events.EVENT_COLOR, Events.EVENT_COLOR);
        sEventsProjectionMap.put(Events.EVENT_COLOR_KEY, Events.EVENT_COLOR_KEY);
        sEventsProjectionMap.put(Events.SELF_ATTENDEE_STATUS, Events.SELF_ATTENDEE_STATUS);
        sEventsProjectionMap.put(Events.DTSTART, Events.DTSTART);
        sEventsProjectionMap.put(Events.DTEND, Events.DTEND);
        sEventsProjectionMap.put(Events.EVENT_TIMEZONE, Events.EVENT_TIMEZONE);
        sEventsProjectionMap.put(Events.EVENT_END_TIMEZONE, Events.EVENT_END_TIMEZONE);
        sEventsProjectionMap.put(Events.DURATION, Events.DURATION);
        sEventsProjectionMap.put(Events.ALL_DAY, Events.ALL_DAY);
        sEventsProjectionMap.put(Events.ACCESS_LEVEL, Events.ACCESS_LEVEL);
        sEventsProjectionMap.put(Events.AVAILABILITY, Events.AVAILABILITY);
        sEventsProjectionMap.put(Events.HAS_ALARM, Events.HAS_ALARM);
        sEventsProjectionMap.put(Events.HAS_EXTENDED_PROPERTIES, Events.HAS_EXTENDED_PROPERTIES);
        sEventsProjectionMap.put(Events.RRULE, Events.RRULE);
        sEventsProjectionMap.put(Events.RDATE, Events.RDATE);
        sEventsProjectionMap.put(Events.EXRULE, Events.EXRULE);
        sEventsProjectionMap.put(Events.EXDATE, Events.EXDATE);
        sEventsProjectionMap.put(Events.ORIGINAL_SYNC_ID, Events.ORIGINAL_SYNC_ID);
        sEventsProjectionMap.put(Events.ORIGINAL_ID, Events.ORIGINAL_ID);
        sEventsProjectionMap.put(Events.ORIGINAL_INSTANCE_TIME, Events.ORIGINAL_INSTANCE_TIME);
        sEventsProjectionMap.put(Events.ORIGINAL_ALL_DAY, Events.ORIGINAL_ALL_DAY);
        sEventsProjectionMap.put(Events.LAST_DATE, Events.LAST_DATE);
        sEventsProjectionMap.put(Events.HAS_ATTENDEE_DATA, Events.HAS_ATTENDEE_DATA);
        sEventsProjectionMap.put(Events.CALENDAR_ID, Events.CALENDAR_ID);
        sEventsProjectionMap.put(Events.GUESTS_CAN_INVITE_OTHERS, Events.GUESTS_CAN_INVITE_OTHERS);
        sEventsProjectionMap.put(Events.GUESTS_CAN_MODIFY, Events.GUESTS_CAN_MODIFY);
        sEventsProjectionMap.put(Events.GUESTS_CAN_SEE_GUESTS, Events.GUESTS_CAN_SEE_GUESTS);
        sEventsProjectionMap.put(Events.ORGANIZER, Events.ORGANIZER);
        sEventsProjectionMap.put(Events.IS_ORGANIZER, Events.IS_ORGANIZER);
        sEventsProjectionMap.put(Events.CUSTOM_APP_PACKAGE, Events.CUSTOM_APP_PACKAGE);
        sEventsProjectionMap.put(Events.CUSTOM_APP_URI, Events.CUSTOM_APP_URI);
        sEventsProjectionMap.put(Events.UID_2445, Events.UID_2445);
        sEventsProjectionMap.put(Events.DELETED, Events.DELETED);
        sEventsProjectionMap.put(Events._SYNC_ID, Events._SYNC_ID);

        // Put the shared items into the Attendees, Reminders projection map
        sAttendeesProjectionMap = new HashMap<String, String>(sEventsProjectionMap);
        sRemindersProjectionMap = new HashMap<String, String>(sEventsProjectionMap);

        // Calendar columns
        sEventsProjectionMap.put(Calendars.CALENDAR_COLOR, Calendars.CALENDAR_COLOR);
        sEventsProjectionMap.put(Calendars.CALENDAR_COLOR_KEY, Calendars.CALENDAR_COLOR_KEY);
        sEventsProjectionMap.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CALENDAR_ACCESS_LEVEL);
        sEventsProjectionMap.put(Calendars.VISIBLE, Calendars.VISIBLE);
        sEventsProjectionMap.put(Calendars.CALENDAR_TIME_ZONE, Calendars.CALENDAR_TIME_ZONE);
        sEventsProjectionMap.put(Calendars.OWNER_ACCOUNT, Calendars.OWNER_ACCOUNT);
        sEventsProjectionMap.put(Calendars.CALENDAR_DISPLAY_NAME, Calendars.CALENDAR_DISPLAY_NAME);
        sEventsProjectionMap.put(Calendars.ALLOWED_REMINDERS, Calendars.ALLOWED_REMINDERS);
        sEventsProjectionMap
                .put(Calendars.ALLOWED_ATTENDEE_TYPES, Calendars.ALLOWED_ATTENDEE_TYPES);
        sEventsProjectionMap.put(Calendars.ALLOWED_AVAILABILITY, Calendars.ALLOWED_AVAILABILITY);
        sEventsProjectionMap.put(Calendars.MAX_REMINDERS, Calendars.MAX_REMINDERS);
        sEventsProjectionMap.put(Calendars.CAN_ORGANIZER_RESPOND, Calendars.CAN_ORGANIZER_RESPOND);
        sEventsProjectionMap.put(Calendars.CAN_MODIFY_TIME_ZONE, Calendars.CAN_MODIFY_TIME_ZONE);
        sEventsProjectionMap.put(Calendars.IS_PRIMARY,
                "COALESCE(" + Calendars.IS_PRIMARY + ", "
                        + Calendars.OWNER_ACCOUNT + " = " + Calendars.ACCOUNT_NAME + ") AS "
                        + Calendars.IS_PRIMARY);
        sEventsProjectionMap.put(Events.DISPLAY_COLOR, Events.DISPLAY_COLOR);

        // Put the shared items into the Instances projection map
        // The Instances and CalendarAlerts are joined with Calendars, so the projections include
        // the above Calendar columns.
        sInstancesProjectionMap = new HashMap<String, String>(sEventsProjectionMap);
        sCalendarAlertsProjectionMap = new HashMap<String, String>(sEventsProjectionMap);

        sEventsProjectionMap.put(Events._ID, Events._ID);
        sEventsProjectionMap.put(Events.SYNC_DATA1, Events.SYNC_DATA1);
        sEventsProjectionMap.put(Events.SYNC_DATA2, Events.SYNC_DATA2);
        sEventsProjectionMap.put(Events.SYNC_DATA3, Events.SYNC_DATA3);
        sEventsProjectionMap.put(Events.SYNC_DATA4, Events.SYNC_DATA4);
        sEventsProjectionMap.put(Events.SYNC_DATA5, Events.SYNC_DATA5);
        sEventsProjectionMap.put(Events.SYNC_DATA6, Events.SYNC_DATA6);
        sEventsProjectionMap.put(Events.SYNC_DATA7, Events.SYNC_DATA7);
        sEventsProjectionMap.put(Events.SYNC_DATA8, Events.SYNC_DATA8);
        sEventsProjectionMap.put(Events.SYNC_DATA9, Events.SYNC_DATA9);
        sEventsProjectionMap.put(Events.SYNC_DATA10, Events.SYNC_DATA10);
        sEventsProjectionMap.put(Calendars.CAL_SYNC1, Calendars.CAL_SYNC1);
        sEventsProjectionMap.put(Calendars.CAL_SYNC2, Calendars.CAL_SYNC2);
        sEventsProjectionMap.put(Calendars.CAL_SYNC3, Calendars.CAL_SYNC3);
        sEventsProjectionMap.put(Calendars.CAL_SYNC4, Calendars.CAL_SYNC4);
        sEventsProjectionMap.put(Calendars.CAL_SYNC5, Calendars.CAL_SYNC5);
        sEventsProjectionMap.put(Calendars.CAL_SYNC6, Calendars.CAL_SYNC6);
        sEventsProjectionMap.put(Calendars.CAL_SYNC7, Calendars.CAL_SYNC7);
        sEventsProjectionMap.put(Calendars.CAL_SYNC8, Calendars.CAL_SYNC8);
        sEventsProjectionMap.put(Calendars.CAL_SYNC9, Calendars.CAL_SYNC9);
        sEventsProjectionMap.put(Calendars.CAL_SYNC10, Calendars.CAL_SYNC10);
        sEventsProjectionMap.put(Events.DIRTY, Events.DIRTY);
        sEventsProjectionMap.put(Events.MUTATORS, Events.MUTATORS);
        sEventsProjectionMap.put(Events.LAST_SYNCED, Events.LAST_SYNCED);

        sEventEntitiesProjectionMap = new HashMap<String, String>();
        sEventEntitiesProjectionMap.put(Events.TITLE, Events.TITLE);
        sEventEntitiesProjectionMap.put(Events.EVENT_LOCATION, Events.EVENT_LOCATION);
        sEventEntitiesProjectionMap.put(Events.DESCRIPTION, Events.DESCRIPTION);
        sEventEntitiesProjectionMap.put(Events.STATUS, Events.STATUS);
        sEventEntitiesProjectionMap.put(Events.EVENT_COLOR, Events.EVENT_COLOR);
        sEventEntitiesProjectionMap.put(Events.EVENT_COLOR_KEY, Events.EVENT_COLOR_KEY);
        sEventEntitiesProjectionMap.put(Events.SELF_ATTENDEE_STATUS, Events.SELF_ATTENDEE_STATUS);
        sEventEntitiesProjectionMap.put(Events.DTSTART, Events.DTSTART);
        sEventEntitiesProjectionMap.put(Events.DTEND, Events.DTEND);
        sEventEntitiesProjectionMap.put(Events.EVENT_TIMEZONE, Events.EVENT_TIMEZONE);
        sEventEntitiesProjectionMap.put(Events.EVENT_END_TIMEZONE, Events.EVENT_END_TIMEZONE);
        sEventEntitiesProjectionMap.put(Events.DURATION, Events.DURATION);
        sEventEntitiesProjectionMap.put(Events.ALL_DAY, Events.ALL_DAY);
        sEventEntitiesProjectionMap.put(Events.ACCESS_LEVEL, Events.ACCESS_LEVEL);
        sEventEntitiesProjectionMap.put(Events.AVAILABILITY, Events.AVAILABILITY);
        sEventEntitiesProjectionMap.put(Events.HAS_ALARM, Events.HAS_ALARM);
        sEventEntitiesProjectionMap.put(Events.HAS_EXTENDED_PROPERTIES,
                Events.HAS_EXTENDED_PROPERTIES);
        sEventEntitiesProjectionMap.put(Events.RRULE, Events.RRULE);
        sEventEntitiesProjectionMap.put(Events.RDATE, Events.RDATE);
        sEventEntitiesProjectionMap.put(Events.EXRULE, Events.EXRULE);
        sEventEntitiesProjectionMap.put(Events.EXDATE, Events.EXDATE);
        sEventEntitiesProjectionMap.put(Events.ORIGINAL_SYNC_ID, Events.ORIGINAL_SYNC_ID);
        sEventEntitiesProjectionMap.put(Events.ORIGINAL_ID, Events.ORIGINAL_ID);
        sEventEntitiesProjectionMap.put(Events.ORIGINAL_INSTANCE_TIME,
                Events.ORIGINAL_INSTANCE_TIME);
        sEventEntitiesProjectionMap.put(Events.ORIGINAL_ALL_DAY, Events.ORIGINAL_ALL_DAY);
        sEventEntitiesProjectionMap.put(Events.LAST_DATE, Events.LAST_DATE);
        sEventEntitiesProjectionMap.put(Events.HAS_ATTENDEE_DATA, Events.HAS_ATTENDEE_DATA);
        sEventEntitiesProjectionMap.put(Events.CALENDAR_ID, Events.CALENDAR_ID);
        sEventEntitiesProjectionMap.put(Events.GUESTS_CAN_INVITE_OTHERS,
                Events.GUESTS_CAN_INVITE_OTHERS);
        sEventEntitiesProjectionMap.put(Events.GUESTS_CAN_MODIFY, Events.GUESTS_CAN_MODIFY);
        sEventEntitiesProjectionMap.put(Events.GUESTS_CAN_SEE_GUESTS, Events.GUESTS_CAN_SEE_GUESTS);
        sEventEntitiesProjectionMap.put(Events.ORGANIZER, Events.ORGANIZER);
        sEventEntitiesProjectionMap.put(Events.IS_ORGANIZER, Events.IS_ORGANIZER);
        sEventEntitiesProjectionMap.put(Events.CUSTOM_APP_PACKAGE, Events.CUSTOM_APP_PACKAGE);
        sEventEntitiesProjectionMap.put(Events.CUSTOM_APP_URI, Events.CUSTOM_APP_URI);
        sEventEntitiesProjectionMap.put(Events.UID_2445, Events.UID_2445);
        sEventEntitiesProjectionMap.put(Events.DELETED, Events.DELETED);
        sEventEntitiesProjectionMap.put(Events._ID, Events._ID);
        sEventEntitiesProjectionMap.put(Events._SYNC_ID, Events._SYNC_ID);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA1, Events.SYNC_DATA1);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA2, Events.SYNC_DATA2);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA3, Events.SYNC_DATA3);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA4, Events.SYNC_DATA4);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA5, Events.SYNC_DATA5);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA6, Events.SYNC_DATA6);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA7, Events.SYNC_DATA7);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA8, Events.SYNC_DATA8);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA9, Events.SYNC_DATA9);
        sEventEntitiesProjectionMap.put(Events.SYNC_DATA10, Events.SYNC_DATA10);
        sEventEntitiesProjectionMap.put(Events.DIRTY, Events.DIRTY);
        sEventEntitiesProjectionMap.put(Events.MUTATORS, Events.MUTATORS);
        sEventEntitiesProjectionMap.put(Events.LAST_SYNCED, Events.LAST_SYNCED);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC1, Calendars.CAL_SYNC1);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC2, Calendars.CAL_SYNC2);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC3, Calendars.CAL_SYNC3);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC4, Calendars.CAL_SYNC4);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC5, Calendars.CAL_SYNC5);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC6, Calendars.CAL_SYNC6);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC7, Calendars.CAL_SYNC7);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC8, Calendars.CAL_SYNC8);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC9, Calendars.CAL_SYNC9);
        sEventEntitiesProjectionMap.put(Calendars.CAL_SYNC10, Calendars.CAL_SYNC10);

        // Instances columns
        sInstancesProjectionMap.put(Events.DELETED, "Events.deleted as deleted");
        sInstancesProjectionMap.put(Instances.BEGIN, "begin");
        sInstancesProjectionMap.put(Instances.END, "end");
        sInstancesProjectionMap.put(Instances.EVENT_ID, "Instances.event_id AS event_id");
        sInstancesProjectionMap.put(Instances._ID, "Instances._id AS _id");
        sInstancesProjectionMap.put(Instances.START_DAY, "startDay");
        sInstancesProjectionMap.put(Instances.END_DAY, "endDay");
        sInstancesProjectionMap.put(Instances.START_MINUTE, "startMinute");
        sInstancesProjectionMap.put(Instances.END_MINUTE, "endMinute");

        // Attendees columns
        sAttendeesProjectionMap.put(Attendees.EVENT_ID, "event_id");
        sAttendeesProjectionMap.put(Attendees._ID, "Attendees._id AS _id");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_NAME, "attendeeName");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_EMAIL, "attendeeEmail");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_STATUS, "attendeeStatus");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_RELATIONSHIP, "attendeeRelationship");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_TYPE, "attendeeType");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_IDENTITY, "attendeeIdentity");
        sAttendeesProjectionMap.put(Attendees.ATTENDEE_ID_NAMESPACE, "attendeeIdNamespace");
        sAttendeesProjectionMap.put(Events.DELETED, "Events.deleted AS deleted");
        sAttendeesProjectionMap.put(Events._SYNC_ID, "Events._sync_id AS _sync_id");

        // Reminders columns
        sRemindersProjectionMap.put(Reminders.EVENT_ID, "event_id");
        sRemindersProjectionMap.put(Reminders._ID, "Reminders._id AS _id");
        sRemindersProjectionMap.put(Reminders.MINUTES, "minutes");
        sRemindersProjectionMap.put(Reminders.METHOD, "method");
        sRemindersProjectionMap.put(Events.DELETED, "Events.deleted AS deleted");
        sRemindersProjectionMap.put(Events._SYNC_ID, "Events._sync_id AS _sync_id");

        // CalendarAlerts columns
        sCalendarAlertsProjectionMap.put(CalendarAlerts.EVENT_ID, "event_id");
        sCalendarAlertsProjectionMap.put(CalendarAlerts._ID, "CalendarAlerts._id AS _id");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.BEGIN, "begin");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.END, "end");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.ALARM_TIME, "alarmTime");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.NOTIFY_TIME, "notifyTime");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.STATE, "state");
        sCalendarAlertsProjectionMap.put(CalendarAlerts.MINUTES, "minutes");

        // CalendarCache columns
        sCalendarCacheProjectionMap = new HashMap<String, String>();
        sCalendarCacheProjectionMap.put(CalendarCache.COLUMN_NAME_KEY, "key");
        sCalendarCacheProjectionMap.put(CalendarCache.COLUMN_NAME_VALUE, "value");
    }


    /**
     * This is called by AccountManager when the set of accounts is updated.
     * <p>
     * We are overriding this since we need to delete from the
     * Calendars table, which is not syncable, which has triggers that
     * will delete from the Events and  tables, which are
     * syncable.  TODO: update comment, make sure deletes don't get synced.
     *
     * @param accounts The list of currently active accounts.
     */
    @Override
    public void onAccountsUpdated(Account[] accounts) {
        Thread thread = new AccountsUpdatedThread(accounts);
        thread.start();
    }

    private class AccountsUpdatedThread extends Thread {
        private Account[] mAccounts;

        AccountsUpdatedThread(Account[] accounts) {
            mAccounts = accounts;
        }

        @Override
        public void run() {
            // The process could be killed while the thread runs.  Right now that isn't a problem,
            // because we'll just call removeStaleAccounts() again when the provider restarts, but
            // if we want to do additional actions we may need to use a service (e.g. start
            // EmptyService in onAccountsUpdated() and stop it when we finish here).

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            removeStaleAccounts(mAccounts);
        }
    }

    /**
     * Makes sure there are no entries for accounts that no longer exist.
     */
    private void removeStaleAccounts(Account[] accounts) {
        mDb = mDbHelper.getWritableDatabase();
        if (mDb == null) {
            return;
        }

        HashSet<Account> validAccounts = new HashSet<Account>();
        for (Account account : accounts) {
            validAccounts.add(new Account(account.name, account.type));
        }
        ArrayList<Account> accountsToDelete = new ArrayList<Account>();

        mDb.beginTransaction();
        Cursor c = null;
        try {

            for (String table : new String[]{Tables.CALENDARS, Tables.COLORS}) {
                // Find all the accounts the calendar DB knows about, mark the ones that aren't
                // in the valid set for deletion.
                c = mDb.rawQuery("SELECT DISTINCT " +
                                            Calendars.ACCOUNT_NAME +
                                            "," +
                                            Calendars.ACCOUNT_TYPE +
                                        " FROM " + table, null);
                while (c.moveToNext()) {
                    // ACCOUNT_TYPE_LOCAL is to store calendars not associated
                    // with a system account. Typically, a calendar must be
                    // associated with an account on the device or it will be
                    // deleted.
                    if (c.getString(0) != null
                            && c.getString(1) != null
                            && !TextUtils.equals(c.getString(1),
                                    CalendarContract.ACCOUNT_TYPE_LOCAL)) {
                        Account currAccount = new Account(c.getString(0), c.getString(1));
                        if (!validAccounts.contains(currAccount)) {
                            accountsToDelete.add(currAccount);
                        }
                    }
                }
                c.close();
                c = null;
            }

            for (Account account : accountsToDelete) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "removing data for removed account " + account);
                }
                String[] params = new String[]{account.name, account.type};
                mDb.execSQL(SQL_DELETE_FROM_CALENDARS, params);
                // This will be a no-op for accounts without a color palette.
                mDb.execSQL(SQL_DELETE_FROM_COLORS, params);
            }
            mDbHelper.getSyncState().onAccountsChanged(mDb, accounts);
            mDb.setTransactionSuccessful();
        } finally {
            if (c != null) {
                c.close();
            }
            mDb.endTransaction();
        }

        // make sure the widget reflects the account changes
        if (!accountsToDelete.isEmpty()) {
            sendUpdateNotification(false);
        }
    }

    /**
     * Inserts an argument at the beginning of the selection arg list.
     *
     * The {@link android.database.sqlite.SQLiteQueryBuilder}'s where clause is
     * prepended to the user's where clause (combined with 'AND') to generate
     * the final where close, so arguments associated with the QueryBuilder are
     * prepended before any user selection args to keep them in the right order.
     */
    private String[] insertSelectionArg(String[] selectionArgs, String arg) {
        if (selectionArgs == null) {
            return new String[] {arg};
        } else {
            int newLength = selectionArgs.length + 1;
            String[] newSelectionArgs = new String[newLength];
            newSelectionArgs[0] = arg;
            System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length);
            return newSelectionArgs;
        }
    }

    @VisibleForTesting
    protected String getCallingPackageName() {
        if (getCachedCallingPackage() != null) {
            // If the calling package is null, use the best available as a fallback.
            return getCachedCallingPackage();
        }
        if (!Boolean.TRUE.equals(mCallingPackageErrorLogged.get())) {
            Log.e(TAG, "Failed to get the cached calling package.", new Throwable());
            mCallingPackageErrorLogged.set(Boolean.TRUE);
        }
        final PackageManager pm = getContext().getPackageManager();
        final int uid = Binder.getCallingUid();
        final String[] packages = pm.getPackagesForUid(uid);
        if (packages != null && packages.length == 1) {
            return packages[0];
        }
        final String name = pm.getNameForUid(uid);
        if (name != null) {
            return name;
        }
        return String.valueOf(uid);
    }

    private void addMutator(ContentValues values, String columnName) {
        final String packageName = getCallingPackageName();
        final String mutators = values.getAsString(columnName);
        if (TextUtils.isEmpty(mutators)) {
            values.put(columnName, packageName);
        } else {
            values.put(columnName, mutators + "," + packageName);
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        mStats.dump(writer, "  ");
    }
}
