1b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook/* 2b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Copyright (C) 2008-2009 Marc Blank 3b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Licensed to The Android Open Source Project. 4b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 5b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License"); 6b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * you may not use this file except in compliance with the License. 7b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * You may obtain a copy of the License at 8b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 9b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * http://www.apache.org/licenses/LICENSE-2.0 10b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 11b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Unless required by applicable law or agreed to in writing, software 12b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS, 13b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * See the License for the specific language governing permissions and 15b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * limitations under the License. 16b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook */ 17b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 18b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookpackage com.android.exchange; 19b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 20b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.BroadcastReceiver; 21b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.ContentResolver; 22b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.Context; 23b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.content.Intent; 24b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.database.Cursor; 25b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport android.util.Log; 26b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 27b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.emailcommon.provider.EmailContent.Message; 28b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.emailcommon.provider.EmailContent.MessageColumns; 29b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport com.android.emailcommon.provider.ProviderUnavailableException; 30b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 31b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookimport java.util.ArrayList; 32b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 33b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook/** 34b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * EmailSyncAlarmReceiver (USAR) is used by the SyncManager to start up-syncs of user-modified data 35b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * back to the Exchange server. 36b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 37b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * Here's how this works for Email, for example: 38b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 39b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 1) User modifies or deletes an email from the UI. 40b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 2) SyncManager, which has a ContentObserver watching the Message class, is alerted to a change 41b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 3) SyncManager sets an alarm (to be received by USAR) for a few seconds in the 42b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * future (currently 15), the delay preventing excess syncing (think of it as a debounce mechanism). 43b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 4) ESAR Receiver's onReceive method is called 44b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 5) ESAR goes through all change and deletion records and compiles a list of mailboxes which have 45b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * changes to be uploaded. 46b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 6) ESAR calls SyncManager to start syncs of those mailboxes 47b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 48b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * If EmailProvider isn't available, the upsyncs will happen the next time ExchangeService starts 49b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook * 50b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook */ 51b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrookpublic class EmailSyncAlarmReceiver extends BroadcastReceiver { 52b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook final String[] MAILBOX_DATA_PROJECTION = {MessageColumns.MAILBOX_KEY}; 53b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 54b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook @Override 55b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void onReceive(final Context context, Intent intent) { 56b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook new Thread(new Runnable() { 57b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook public void run() { 58b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook handleReceive(context); 59b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 60b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook }).start(); 61b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 62b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 63b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook private void handleReceive(Context context) { 64b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ArrayList<Long> mailboxesToNotify = new ArrayList<Long>(); 65b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ContentResolver cr = context.getContentResolver(); 66b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook int messageCount = 0; 67b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 68b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Get a selector for EAS accounts (we don't want to sync on changes to POP/IMAP messages) 69b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook String selector = ExchangeService.getEasAccountSelector(); 70b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 71b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook try { 72b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Find all of the deletions 73b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Cursor c = cr.query(Message.DELETED_CONTENT_URI, MAILBOX_DATA_PROJECTION, selector, 74b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook null, null); 75b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (c == null) throw new ProviderUnavailableException(); 76b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook try { 77b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Keep track of which mailboxes to notify; we'll only notify each one once 78b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook while (c.moveToNext()) { 79b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook messageCount++; 80b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook long mailboxId = c.getLong(0); 81b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (!mailboxesToNotify.contains(mailboxId)) { 82b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mailboxesToNotify.add(mailboxId); 83b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 84b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 85b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } finally { 86b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook c.close(); 87b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 88b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 89b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Now, find changed messages 90b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook c = cr.query(Message.UPDATED_CONTENT_URI, MAILBOX_DATA_PROJECTION, selector, 91b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook null, null); 92b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (c == null) throw new ProviderUnavailableException(); 93b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook try { 94b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Keep track of which mailboxes to notify; we'll only notify each one once 95b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook while (c.moveToNext()) { 96b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook messageCount++; 97b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook long mailboxId = c.getLong(0); 98b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook if (!mailboxesToNotify.contains(mailboxId)) { 99b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook mailboxesToNotify.add(mailboxId); 100b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 101b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 102b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } finally { 103b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook c.close(); 104b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 105b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook 106b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook // Request service from the mailbox 107b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook for (Long mailboxId: mailboxesToNotify) { 108b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook ExchangeService.serviceRequest(mailboxId, ExchangeService.SYNC_UPSYNC); 109b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 110b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } catch (ProviderUnavailableException e) { 111b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook Log.e("EmailSyncAlarmReceiver", "EmailProvider unavailable; aborting alarm receiver"); 112b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 113b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook } 114b931f82fa44c2e26e2645c0d5fde9eef3e666efdPaul Westbrook} 115