12f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock/* 22f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * Copyright (C) 2015 The Android Open Source Project 32f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * 42f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 52f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * you may not use this file except in compliance with the License. 62f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * You may obtain a copy of the License at 72f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * 82f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 92f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * 102f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * Unless required by applicable law or agreed to in writing, software 112f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 122f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * See the License for the specific language governing permissions and 142f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock * limitations under the License. 152f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock */ 162f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 172f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockpackage com.android.server.notification; 182f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 192f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.content.ContentResolver; 202f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.content.ContentUris; 212f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.content.Context; 222f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.database.ContentObserver; 232f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.database.Cursor; 242f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.net.Uri; 252f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.provider.BaseColumns; 262f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.provider.CalendarContract.Attendees; 271b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlockimport android.provider.CalendarContract.Calendars; 281b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlockimport android.provider.CalendarContract.Events; 292f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.provider.CalendarContract.Instances; 302f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.service.notification.ZenModeConfig.EventInfo; 311b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlockimport android.util.ArraySet; 322f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport android.util.Log; 332f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 342f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport java.io.PrintWriter; 352f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport java.util.Date; 362f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockimport java.util.Objects; 372f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 382f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlockpublic class CalendarTracker { 392f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final String TAG = "ConditionProviders.CT"; 402f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final boolean DEBUG = Log.isLoggable("ConditionProviders", Log.DEBUG); 412f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final boolean DEBUG_ATTENDEES = false; 422f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 432f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final int EVENT_CHECK_LOOKAHEAD = 24 * 60 * 60 * 1000; 442f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 452f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final String[] INSTANCE_PROJECTION = { 46a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.BEGIN, 47a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.END, 48a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.TITLE, 49a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.VISIBLE, 50a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.EVENT_ID, 51a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.CALENDAR_DISPLAY_NAME, 52a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.OWNER_ACCOUNT, 53a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.CALENDAR_ID, 54a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds Instances.AVAILABILITY, 552f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock }; 562f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 572f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final String INSTANCE_ORDER_BY = Instances.BEGIN + " ASC"; 582f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 592f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final String[] ATTENDEE_PROJECTION = { 602f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock Attendees.EVENT_ID, 612f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock Attendees.ATTENDEE_EMAIL, 622f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock Attendees.ATTENDEE_STATUS, 632f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock }; 642f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 652f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static final String ATTENDEE_SELECTION = Attendees.EVENT_ID + " = ? AND " 662f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock + Attendees.ATTENDEE_EMAIL + " = ?"; 672f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 681b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock private final Context mSystemContext; 691b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock private final Context mUserContext; 702f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 712f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private Callback mCallback; 722f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private boolean mRegistered; 732f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 741b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock public CalendarTracker(Context systemContext, Context userContext) { 751b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock mSystemContext = systemContext; 761b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock mUserContext = userContext; 772f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 782f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 792f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public void setCallback(Callback callback) { 802f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (mCallback == callback) return; 812f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock mCallback = callback; 822f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock setRegistered(mCallback != null); 832f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 842f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 852f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public void dump(String prefix, PrintWriter pw) { 862f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock pw.print(prefix); pw.print("mCallback="); pw.println(mCallback); 872f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock pw.print(prefix); pw.print("mRegistered="); pw.println(mRegistered); 881b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock pw.print(prefix); pw.print("u="); pw.println(mUserContext.getUserId()); 892f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 902f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 911b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock private ArraySet<Long> getPrimaryCalendars() { 921b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final long start = System.currentTimeMillis(); 931b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final ArraySet<Long> rt = new ArraySet<>(); 941b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final String primary = "\"primary\""; 951b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final String[] projection = { Calendars._ID, 961b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + primary }; 971b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final String selection = primary + " = 1"; 981b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock Cursor cursor = null; 991b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock try { 1001b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cursor = mUserContext.getContentResolver().query(Calendars.CONTENT_URI, projection, 1011b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock selection, null, null); 1021b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock while (cursor != null && cursor.moveToNext()) { 1031b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock rt.add(cursor.getLong(0)); 1041b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } 1051b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } finally { 1061b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (cursor != null) { 1071b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cursor.close(); 1081b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } 1091b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } 1101b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "getPrimaryCalendars took " + (System.currentTimeMillis() - start)); 1111b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock return rt; 1121b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } 1132f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 1142f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public CheckEventResult checkEvent(EventInfo filter, long time) { 1152f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final Uri.Builder uriBuilder = Instances.CONTENT_URI.buildUpon(); 1162f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock ContentUris.appendId(uriBuilder, time); 1172f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock ContentUris.appendId(uriBuilder, time + EVENT_CHECK_LOOKAHEAD); 1182f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final Uri uri = uriBuilder.build(); 1191b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final Cursor cursor = mUserContext.getContentResolver().query(uri, INSTANCE_PROJECTION, 1201b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock null, null, INSTANCE_ORDER_BY); 1212f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final CheckEventResult result = new CheckEventResult(); 1222f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock result.recheckAt = time + EVENT_CHECK_LOOKAHEAD; 1232f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock try { 1241b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final ArraySet<Long> primaryCalendars = getPrimaryCalendars(); 1251b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock while (cursor != null && cursor.moveToNext()) { 1262f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final long begin = cursor.getLong(0); 1272f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final long end = cursor.getLong(1); 1282f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final String title = cursor.getString(2); 1291b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final boolean calendarVisible = cursor.getInt(3) == 1; 1302f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final int eventId = cursor.getInt(4); 131a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds final String name = cursor.getString(5); 132a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds final String owner = cursor.getString(6); 133a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds final long calendarId = cursor.getLong(7); 134a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds final int availability = cursor.getInt(8); 1351b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final boolean calendarPrimary = primaryCalendars.contains(calendarId); 136a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds if (DEBUG) Log.d(TAG, String.format( 137a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds "%s %s-%s v=%s a=%s eid=%s n=%s o=%s cid=%s p=%s", 1381b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock title, 1391b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock new Date(begin), new Date(end), calendarVisible, 140a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds availabilityToString(availability), eventId, name, owner, calendarId, 1411b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock calendarPrimary)); 1422f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final boolean meetsTime = time >= begin && time < end; 1431b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final boolean meetsCalendar = calendarVisible && calendarPrimary 144a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds && (filter.calendar == null || Objects.equals(filter.calendar, owner) 145a9864d234757ef43b227f32b02f825fb0a33b61bJulia Reynolds || Objects.equals(filter.calendar, name)); 1461b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final boolean meetsAvailability = availability != Instances.AVAILABILITY_FREE; 1471b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (meetsCalendar && meetsAvailability) { 1481b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, " MEETS CALENDAR & AVAILABILITY"); 1492f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final boolean meetsAttendee = meetsAttendee(filter, eventId, owner); 1502f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (meetsAttendee) { 1512f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG) Log.d(TAG, " MEETS ATTENDEE"); 1522f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (meetsTime) { 1532f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG) Log.d(TAG, " MEETS TIME"); 1542f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock result.inEvent = true; 1552f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1562f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (begin > time && begin < result.recheckAt) { 1572f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock result.recheckAt = begin; 1582f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } else if (end > time && end < result.recheckAt) { 1592f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock result.recheckAt = end; 1602f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1612f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1622f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1632f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1642f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } finally { 1651b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (cursor != null) { 1661b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cursor.close(); 1671b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock } 1682f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1692f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock return result; 1702f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1712f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 1722f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private boolean meetsAttendee(EventInfo filter, int eventId, String email) { 1731b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final long start = System.currentTimeMillis(); 1742f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock String selection = ATTENDEE_SELECTION; 1752f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock String[] selectionArgs = { Integer.toString(eventId), email }; 1762f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG_ATTENDEES) { 1772f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock selection = null; 1782f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock selectionArgs = null; 1792f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1801b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final Cursor cursor = mUserContext.getContentResolver().query(Attendees.CONTENT_URI, 1812f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock ATTENDEE_PROJECTION, selection, selectionArgs, null); 1822f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock try { 1839bbe0bb413033b252d6ce5858989ca3cd7cbbdb3Julia Reynolds if (cursor == null || cursor.getCount() == 0) { 1842f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG) Log.d(TAG, "No attendees found"); 1852f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock return true; 1862f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 1872f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock boolean rt = false; 1889bbe0bb413033b252d6ce5858989ca3cd7cbbdb3Julia Reynolds while (cursor != null && cursor.moveToNext()) { 1892f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final long rowEventId = cursor.getLong(0); 1902f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final String rowEmail = cursor.getString(1); 1912f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final int status = cursor.getInt(2); 1922f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final boolean meetsReply = meetsReply(filter.reply, status); 1932f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG) Log.d(TAG, (DEBUG_ATTENDEES ? String.format( 1942f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock "rowEventId=%s, rowEmail=%s, ", rowEventId, rowEmail) : "") + 195d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock String.format("status=%s, meetsReply=%s", 196d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock attendeeStatusToString(status), meetsReply)); 1972f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock final boolean eventMeets = rowEventId == eventId && Objects.equals(rowEmail, email) 198d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock && meetsReply; 1992f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock rt |= eventMeets; 2002f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2012f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock return rt; 2022f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } finally { 2039bbe0bb413033b252d6ce5858989ca3cd7cbbdb3Julia Reynolds if (cursor != null) { 2049bbe0bb413033b252d6ce5858989ca3cd7cbbdb3Julia Reynolds cursor.close(); 2059bbe0bb413033b252d6ce5858989ca3cd7cbbdb3Julia Reynolds } 2061b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "meetsAttendee took " + (System.currentTimeMillis() - start)); 2072f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2082f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2092f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2102f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private void setRegistered(boolean registered) { 2112f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (mRegistered == registered) return; 2121b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final ContentResolver cr = mSystemContext.getContentResolver(); 2131b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock final int userId = mUserContext.getUserId(); 2142f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (mRegistered) { 2151b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "unregister content observer u=" + userId); 2162f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock cr.unregisterContentObserver(mObserver); 2172f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2182f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock mRegistered = registered; 2191b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "mRegistered = " + registered + " u=" + userId); 2202f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (mRegistered) { 2211b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "register content observer u=" + userId); 2221b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cr.registerContentObserver(Instances.CONTENT_URI, true, mObserver, userId); 2231b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cr.registerContentObserver(Events.CONTENT_URI, true, mObserver, userId); 2241b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock cr.registerContentObserver(Calendars.CONTENT_URI, true, mObserver, userId); 2252f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2262f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2272f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2282f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static String attendeeStatusToString(int status) { 2292f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock switch (status) { 2302f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case Attendees.ATTENDEE_STATUS_NONE: return "ATTENDEE_STATUS_NONE"; 2312f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case Attendees.ATTENDEE_STATUS_ACCEPTED: return "ATTENDEE_STATUS_ACCEPTED"; 2322f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case Attendees.ATTENDEE_STATUS_DECLINED: return "ATTENDEE_STATUS_DECLINED"; 2332f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case Attendees.ATTENDEE_STATUS_INVITED: return "ATTENDEE_STATUS_INVITED"; 2342f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case Attendees.ATTENDEE_STATUS_TENTATIVE: return "ATTENDEE_STATUS_TENTATIVE"; 2352f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock default: return "ATTENDEE_STATUS_UNKNOWN_" + status; 2362f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2372f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2382f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 239028a53977cd0e3c1393ca17ad680473764905a56John Spurlock private static String availabilityToString(int availability) { 240028a53977cd0e3c1393ca17ad680473764905a56John Spurlock switch (availability) { 241028a53977cd0e3c1393ca17ad680473764905a56John Spurlock case Instances.AVAILABILITY_BUSY: return "AVAILABILITY_BUSY"; 242028a53977cd0e3c1393ca17ad680473764905a56John Spurlock case Instances.AVAILABILITY_FREE: return "AVAILABILITY_FREE"; 243028a53977cd0e3c1393ca17ad680473764905a56John Spurlock case Instances.AVAILABILITY_TENTATIVE: return "AVAILABILITY_TENTATIVE"; 244028a53977cd0e3c1393ca17ad680473764905a56John Spurlock default: return "AVAILABILITY_UNKNOWN_" + availability; 245028a53977cd0e3c1393ca17ad680473764905a56John Spurlock } 246028a53977cd0e3c1393ca17ad680473764905a56John Spurlock } 247028a53977cd0e3c1393ca17ad680473764905a56John Spurlock 2482f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private static boolean meetsReply(int reply, int attendeeStatus) { 2492f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock switch (reply) { 2502f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case EventInfo.REPLY_YES: 2512f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED; 252d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock case EventInfo.REPLY_YES_OR_MAYBE: 253d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock return attendeeStatus == Attendees.ATTENDEE_STATUS_ACCEPTED 254d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock || attendeeStatus == Attendees.ATTENDEE_STATUS_TENTATIVE; 2552f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock case EventInfo.REPLY_ANY_EXCEPT_NO: 2562f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock return attendeeStatus != Attendees.ATTENDEE_STATUS_DECLINED; 257d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock default: 258d39af2d3f8c5d87e102aeb79d4148218ff616245John Spurlock return false; 2592f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2602f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2612f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2622f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock private final ContentObserver mObserver = new ContentObserver(null) { 2632f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock @Override 2642f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public void onChange(boolean selfChange, Uri u) { 2651b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock if (DEBUG) Log.d(TAG, "onChange selfChange=" + selfChange + " uri=" + u 2661b8b22b1a412539020f78a132cff7c8fa7fae258John Spurlock + " u=" + mUserContext.getUserId()); 2672f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock mCallback.onChanged(); 2682f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2692f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2702f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock @Override 2712f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public void onChange(boolean selfChange) { 2722f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock if (DEBUG) Log.d(TAG, "onChange selfChange=" + selfChange); 2732f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2742f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock }; 2752f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2762f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public static class CheckEventResult { 2772f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public boolean inEvent; 2782f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public long recheckAt; 2792f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2802f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2812f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock public interface Callback { 2822f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock void onChanged(); 2832f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock } 2842f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock 2852f096ed7662f9d20876ae2944ffc4ecf4fd51faaJohn Spurlock} 286