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