Home | History | Annotate | Download | only in service
      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.service;
     18 
     19 import android.content.AbstractThreadedSyncAdapter;
     20 import android.content.ContentProviderClient;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.ServiceConnection;
     24 import android.content.SyncResult;
     25 import android.database.Cursor;
     26 import android.os.Bundle;
     27 import android.os.RemoteException;
     28 import android.provider.CalendarContract.Events;
     29 import android.util.Log;
     30 
     31 import com.android.emailcommon.provider.Account;
     32 import com.android.emailcommon.provider.EmailContent.MailboxColumns;
     33 import com.android.emailcommon.provider.Mailbox;
     34 import com.android.emailcommon.service.EmailServiceStatus;
     35 import com.android.exchange.Eas;
     36 import com.android.mail.utils.LogUtils;
     37 
     38 public class CalendarSyncAdapterService extends AbstractSyncAdapterService {
     39     private static final String TAG = LogUtils.TAG;
     40     private static final String ACCOUNT_AND_TYPE_CALENDAR =
     41         MailboxColumns.ACCOUNT_KEY + "=? AND " + MailboxColumns.TYPE + '=' + Mailbox.TYPE_CALENDAR;
     42     private static final String DIRTY_IN_ACCOUNT =
     43         Events.DIRTY + "=1 AND " + Events.ACCOUNT_NAME + "=?";
     44 
     45     private static final Object sSyncAdapterLock = new Object();
     46     private static AbstractThreadedSyncAdapter sSyncAdapter = null;
     47 
     48     public CalendarSyncAdapterService() {
     49         super();
     50     }
     51 
     52     @Override
     53     protected AbstractThreadedSyncAdapter getSyncAdapter() {
     54         synchronized (sSyncAdapterLock) {
     55             if (sSyncAdapter == null) {
     56                 sSyncAdapter = new SyncAdapterImpl(this);
     57             }
     58             return sSyncAdapter;
     59         }
     60     }
     61 
     62     private class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
     63         public SyncAdapterImpl(Context context) {
     64             super(context, true /* autoInitialize */);
     65         }
     66 
     67         @Override
     68         public void onPerformSync(android.accounts.Account acct, Bundle extras,
     69                 String authority, ContentProviderClient provider, SyncResult syncResult) {
     70             if (LogUtils.isLoggable(TAG, Log.DEBUG)) {
     71                 LogUtils.d(TAG, "onPerformSync calendar: %s, %s",
     72                         acct.toString(), extras.toString());
     73             } else {
     74                 LogUtils.i(TAG, "onPerformSync calendar: %s", extras.toString());
     75             }
     76 
     77             if (!waitForService()) {
     78                 // The service didn't connect, nothing we can do.
     79                 return;
     80             }
     81             final Account emailAccount = Account.restoreAccountWithAddress(
     82                     CalendarSyncAdapterService.this, acct.name);
     83             if (emailAccount == null) {
     84                 // There could be a timing issue with onPerformSync() being called and
     85                 // the account being removed from our database.
     86                 LogUtils.w(TAG,
     87                         "onPerformSync() - Could not find an Account, skipping calendar sync.");
     88                 return;
     89             }
     90 
     91             // TODO: is this still needed?
     92             if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
     93                 final Cursor c = getContentResolver().query(Events.CONTENT_URI,
     94                         new String[] {Events._ID}, DIRTY_IN_ACCOUNT,
     95                         new String[] {acct.name}, null);
     96                 if (c == null) {
     97                     LogUtils.e(TAG, "Null changes cursor in CalendarSyncAdapterService");
     98                     return;
     99                 }
    100                 try {
    101                     if (!c.moveToFirst()) {
    102                         if (Eas.USER_LOG) {
    103                             LogUtils.d(TAG, "No changes for " + acct.name);
    104                         }
    105                         return;
    106                     }
    107                 } finally {
    108                     c.close();
    109                 }
    110             }
    111 
    112             // TODO: move this logic to some common place.
    113             // Push only means this sync request should only refresh the ping (either because
    114             // settings changed, or we need to restart it for some reason).
    115             final boolean pushOnly = Mailbox.isPushOnlyExtras(extras);
    116 
    117             if (pushOnly) {
    118                 LogUtils.d(TAG, "onPerformSync calendar: mailbox push only");
    119                 if (mEasService != null) {
    120                     try {
    121                         mEasService.pushModify(emailAccount.mId);
    122                         return;
    123                     } catch (final RemoteException re) {
    124                         LogUtils.e(TAG, re, "While trying to pushModify within onPerformSync");
    125                         // TODO: how to handle this?
    126                     }
    127                 }
    128                 return;
    129             } else {
    130                 try {
    131                     final int result = mEasService.sync(emailAccount.mId, extras);
    132                     writeResultToSyncResult(result, syncResult);
    133                     if (syncResult.stats.numAuthExceptions > 0 &&
    134                             result != EmailServiceStatus.PROVISIONING_ERROR) {
    135                         showAuthNotification(emailAccount.mId, emailAccount.mEmailAddress);
    136                     }
    137                 } catch (RemoteException e) {
    138                     LogUtils.e(TAG, e, "While trying to pushModify within onPerformSync");
    139                 }
    140             }
    141 
    142             LogUtils.d(TAG, "onPerformSync calendar: finished");
    143         }
    144     }
    145 }
    146