Home | History | Annotate | Download | only in exchange
      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.exchange;
     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 import android.util.Log;
     26 
     27 import com.android.emailcommon.provider.EmailContent.Message;
     28 import com.android.emailcommon.provider.EmailContent.MessageColumns;
     29 import com.android.emailcommon.provider.ProviderUnavailableException;
     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             public void run() {
     58                 handleReceive(context);
     59             }
     60         }).start();
     61     }
     62 
     63     private void handleReceive(Context context) {
     64         ArrayList<Long> mailboxesToNotify = new ArrayList<Long>();
     65         ContentResolver cr = context.getContentResolver();
     66         int messageCount = 0;
     67 
     68         // Get a selector for EAS accounts (we don't want to sync on changes to POP/IMAP messages)
     69         String selector = ExchangeService.getEasAccountSelector();
     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                     messageCount++;
     80                     long mailboxId = c.getLong(0);
     81                     if (!mailboxesToNotify.contains(mailboxId)) {
     82                         mailboxesToNotify.add(mailboxId);
     83                     }
     84                 }
     85             } finally {
     86                 c.close();
     87             }
     88 
     89             // Now, find changed messages
     90             c = cr.query(Message.UPDATED_CONTENT_URI, MAILBOX_DATA_PROJECTION, selector,
     91                     null, null);
     92             if (c == null) throw new ProviderUnavailableException();
     93             try {
     94                 // Keep track of which mailboxes to notify; we'll only notify each one once
     95                 while (c.moveToNext()) {
     96                     messageCount++;
     97                     long mailboxId = c.getLong(0);
     98                     if (!mailboxesToNotify.contains(mailboxId)) {
     99                         mailboxesToNotify.add(mailboxId);
    100                     }
    101                 }
    102             } finally {
    103                 c.close();
    104             }
    105 
    106             // Request service from the mailbox
    107             for (Long mailboxId: mailboxesToNotify) {
    108                 ExchangeService.serviceRequest(mailboxId, ExchangeService.SYNC_UPSYNC);
    109             }
    110         } catch (ProviderUnavailableException e) {
    111             Log.e("EmailSyncAlarmReceiver", "EmailProvider unavailable; aborting alarm receiver");
    112         }
    113     }
    114 }
    115