Home | History | Annotate | Download | only in emailsync
      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