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
18package com.android.exchange;
19
20import com.android.email.provider.EmailContent.Message;
21import com.android.email.provider.EmailContent.MessageColumns;
22
23import android.content.BroadcastReceiver;
24import android.content.ContentResolver;
25import android.content.Context;
26import android.content.Intent;
27import android.database.Cursor;
28import android.util.Log;
29
30import java.util.ArrayList;
31
32/**
33 * EmailSyncAlarmReceiver (USAR) is used by the SyncManager to start up-syncs of user-modified data
34 * back to the Exchange server.
35 *
36 * Here's how this works for Email, for example:
37 *
38 * 1) User modifies or deletes an email from the UI.
39 * 2) SyncManager, which has a ContentObserver watching the Message class, is alerted to a change
40 * 3) SyncManager sets an alarm (to be received by USAR) for a few seconds in the
41 * future (currently 15), the delay preventing excess syncing (think of it as a debounce mechanism).
42 * 4) ESAR Receiver's onReceive method is called
43 * 5) ESAR goes through all change and deletion records and compiles a list of mailboxes which have
44 * changes to be uploaded.
45 * 6) ESAR calls SyncManager to start syncs of those mailboxes
46 *
47 */
48public class EmailSyncAlarmReceiver extends BroadcastReceiver {
49    final String[] MAILBOX_DATA_PROJECTION = {MessageColumns.MAILBOX_KEY};
50    private static String TAG = "EmailSyncAlarm";
51
52    @Override
53    public void onReceive(final Context context, Intent intent) {
54        Log.v(TAG, "onReceive");
55        new Thread(new Runnable() {
56            public void run() {
57                handleReceive(context);
58            }
59        }).start();
60    }
61
62    private void handleReceive(Context context) {
63        ArrayList<Long> mailboxesToNotify = new ArrayList<Long>();
64        ContentResolver cr = context.getContentResolver();
65        int messageCount = 0;
66
67        // Get a selector for EAS accounts (we don't want to sync on changes to POP/IMAP messages)
68        String selector = SyncManager.getEasAccountSelector();
69
70        // Find all of the deletions
71        Cursor c = cr.query(Message.DELETED_CONTENT_URI, MAILBOX_DATA_PROJECTION, selector,
72               null, null);
73        try {
74            // Keep track of which mailboxes to notify; we'll only notify each one once
75            while (c.moveToNext()) {
76                messageCount++;
77                long mailboxId = c.getLong(0);
78                if (!mailboxesToNotify.contains(mailboxId)) {
79                    mailboxesToNotify.add(mailboxId);
80                }
81            }
82        } finally {
83            c.close();
84        }
85
86        // Now, find changed messages
87        c = cr.query(Message.UPDATED_CONTENT_URI, MAILBOX_DATA_PROJECTION, selector,
88                null, null);
89        try {
90            // Keep track of which mailboxes to notify; we'll only notify each one once
91            while (c.moveToNext()) {
92                messageCount++;
93                long mailboxId = c.getLong(0);
94                if (!mailboxesToNotify.contains(mailboxId)) {
95                    mailboxesToNotify.add(mailboxId);
96                }
97            }
98        } finally {
99            c.close();
100        }
101
102        // Request service from the mailbox
103        for (Long mailboxId: mailboxesToNotify) {
104            SyncManager.serviceRequest(mailboxId, SyncManager.SYNC_UPSYNC);
105        }
106        Log.v(TAG, "Changed/Deleted messages: " + messageCount + ", mailboxes: " +
107                mailboxesToNotify.size());
108    }
109}
110