Home | History | Annotate | Download | only in exchange
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.exchange;
     18 
     19 import android.accounts.Account;
     20 import android.accounts.OperationCanceledException;
     21 import android.app.Service;
     22 import android.content.AbstractThreadedSyncAdapter;
     23 import android.content.ContentProviderClient;
     24 import android.content.ContentResolver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.SyncResult;
     28 import android.database.Cursor;
     29 import android.os.Bundle;
     30 import android.os.IBinder;
     31 import android.provider.CalendarContract.Events;
     32 import android.util.Log;
     33 
     34 import com.android.emailcommon.provider.EmailContent;
     35 import com.android.emailcommon.provider.EmailContent.AccountColumns;
     36 import com.android.emailcommon.provider.EmailContent.MailboxColumns;
     37 import com.android.emailcommon.provider.Mailbox;
     38 
     39 public class CalendarSyncAdapterService extends Service {
     40     private static final String TAG = "EAS CalendarSyncAdapterService";
     41     private static SyncAdapterImpl sSyncAdapter = null;
     42     private static final Object sSyncAdapterLock = new Object();
     43 
     44     private static final String ACCOUNT_AND_TYPE_CALENDAR =
     45         MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.TYPE + '=' + Mailbox.TYPE_CALENDAR;
     46     private static final String DIRTY_IN_ACCOUNT =
     47         Events.DIRTY + "=1 AND " + Events.ACCOUNT_NAME + "=?";
     48     private static final String[] ID_SYNC_KEY_PROJECTION =
     49         new String[] {MailboxColumns.ID, MailboxColumns.SYNC_KEY};
     50     private static final int ID_SYNC_KEY_MAILBOX_ID = 0;
     51     private static final int ID_SYNC_KEY_SYNC_KEY = 1;
     52 
     53     public CalendarSyncAdapterService() {
     54         super();
     55     }
     56 
     57     private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
     58         private Context mContext;
     59 
     60         public SyncAdapterImpl(Context context) {
     61             super(context, true /* autoInitialize */);
     62             mContext = context;
     63         }
     64 
     65         @Override
     66         public void onPerformSync(Account account, Bundle extras,
     67                 String authority, ContentProviderClient provider, SyncResult syncResult) {
     68             try {
     69                 CalendarSyncAdapterService.performSync(mContext, account, extras,
     70                         authority, provider, syncResult);
     71             } catch (OperationCanceledException e) {
     72             }
     73         }
     74     }
     75 
     76     @Override
     77     public void onCreate() {
     78         super.onCreate();
     79         synchronized (sSyncAdapterLock) {
     80             if (sSyncAdapter == null) {
     81                 sSyncAdapter = new SyncAdapterImpl(getApplicationContext());
     82             }
     83         }
     84     }
     85 
     86     @Override
     87     public IBinder onBind(Intent intent) {
     88         return sSyncAdapter.getSyncAdapterBinder();
     89     }
     90 
     91     /**
     92      * Partial integration with system SyncManager; we tell our EAS ExchangeService to start a
     93      * calendar sync when we get the signal from SyncManager.
     94      * The missing piece at this point is integration with the push/ping mechanism in EAS; this will
     95      * be put in place at a later time.
     96      */
     97     private static void performSync(Context context, Account account, Bundle extras,
     98             String authority, ContentProviderClient provider, SyncResult syncResult)
     99             throws OperationCanceledException {
    100         ContentResolver cr = context.getContentResolver();
    101         boolean logging = Eas.USER_LOG;
    102         if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
    103             Cursor c = cr.query(Events.CONTENT_URI,
    104                     new String[] {Events._ID}, DIRTY_IN_ACCOUNT, new String[] {account.name}, null);
    105             try {
    106                 if (!c.moveToFirst()) {
    107                     if (logging) {
    108                         Log.d(TAG, "No changes for " + account.name);
    109                     }
    110                     return;
    111                 }
    112             } finally {
    113                 c.close();
    114             }
    115         }
    116 
    117         // Find the (EmailProvider) account associated with this email address
    118         Cursor accountCursor =
    119             cr.query(com.android.emailcommon.provider.Account.CONTENT_URI,
    120                     EmailContent.ID_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?",
    121                     new String[] {account.name}, null);
    122         try {
    123             if (accountCursor.moveToFirst()) {
    124                 long accountId = accountCursor.getLong(0);
    125                 // Now, find the calendar mailbox associated with the account
    126                 Cursor mailboxCursor = cr.query(Mailbox.CONTENT_URI, ID_SYNC_KEY_PROJECTION,
    127                         ACCOUNT_AND_TYPE_CALENDAR, new String[] {Long.toString(accountId)}, null);
    128                 try {
    129                      if (mailboxCursor.moveToFirst()) {
    130                         if (logging) {
    131                             Log.d(TAG, "Upload sync requested for " + account.name);
    132                         }
    133                         String syncKey = mailboxCursor.getString(ID_SYNC_KEY_SYNC_KEY);
    134                         if ((syncKey == null) || (syncKey.equals("0"))) {
    135                             if (logging) {
    136                                 Log.d(TAG, "Can't sync; mailbox in initial state");
    137                             }
    138                             return;
    139                         }
    140                         // Ask for a sync from our sync manager
    141                         ExchangeService.serviceRequest(mailboxCursor.getLong(
    142                                 ID_SYNC_KEY_MAILBOX_ID), ExchangeService.SYNC_UPSYNC);
    143                     }
    144                 } finally {
    145                     mailboxCursor.close();
    146                 }
    147             }
    148         } finally {
    149             accountCursor.close();
    150         }
    151     }
    152 }