/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2009 Funambol, Inc. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * "Powered by Funambol" logo. If the display of the logo is not reasonably * feasible for technical reasons, the Appropriate Legal Notices must display * the words "Powered by Funambol". */ package de.chbosync.android.syncmlclient.controller; import java.util.Enumeration; import java.util.Vector; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.os.Handler; import com.funambol.client.source.AppSyncSource; import com.funambol.sync.client.ChangesTracker; import com.funambol.sync.client.TrackableSyncSource; import com.funambol.util.Log; import de.chbosync.android.syncmlclient.AndroidAccountManager; import de.chbosync.android.syncmlclient.AndroidAppSyncSource; import de.chbosync.android.syncmlclient.AndroidAppSyncSourceManager; import de.chbosync.android.syncmlclient.App; import de.chbosync.android.syncmlclient.AppInitializer; import de.chbosync.android.syncmlclient.source.AndroidChangesTracker; /** * <code>AutoSyncSwitcher</code> allows to change the auto sync mode: * <li><code>AUTO_SYNC_MODE_NATIVE</code>: leave the auto sync handling to the * native sync manager</li> * <li><code>AUTO_SYNC_MODE_CUSTOM</code>: start a custom auto sync handling * based on <code>ContentObserver</code>s</li> * <br/><br/> * Switching from <code>AUTO_SYNC_MODE_CUSTOM</code> to * <code>AUTO_SYNC_MODE_NATIVE</code> will immadiately * start a synchronization of the sources which has meen modified during the * custom auto sync period. */ public class AutoSyncSwitcher { private final String TAG_LOG = "AutoSyncSwitcher"; public static final int AUTO_SYNC_MODE_NATIVE = 0; public static final int AUTO_SYNC_MODE_CUSTOM = 1; private Context mContext; private Handler mHandler; private AndroidAppSyncSourceManager appSyncSourceManager; private ContentResolver contentResolver; private Vector<AppSyncSource> pendingSources; private Vector<String> authoritiesWithAutoSync; private Vector<ContentObserver> observers; private AndroidHomeScreenController homeScreenController; private int status = AUTO_SYNC_MODE_NATIVE; public AutoSyncSwitcher(Context context, Handler handler, AndroidHomeScreenController homeScreenController) { this.mContext = context; this.mHandler = handler; this.contentResolver = mContext.getContentResolver(); this.homeScreenController = homeScreenController; AppInitializer initializer = App.i().getAppInitializer(); this.appSyncSourceManager = initializer.getAppSyncSourceManager(); } /** * Switch to the given auto sync mode. * * @param mode * @throws IllegalArgumentException */ public void setAutoSyncMode(int mode) throws IllegalArgumentException { switch(mode) { case AUTO_SYNC_MODE_CUSTOM: if(status == AUTO_SYNC_MODE_CUSTOM) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Auto sync is already in custom mode"); } } else { switchToCustomAutoSync(); status = AUTO_SYNC_MODE_CUSTOM; } break; case AUTO_SYNC_MODE_NATIVE: if(status == AUTO_SYNC_MODE_NATIVE) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Auto sync is already in native mode"); } } else { switchToNativeAutoSync(); status = AUTO_SYNC_MODE_NATIVE; } break; default: Log.error(TAG_LOG, "Invalid auto sync mode: " + mode); throw new IllegalArgumentException("Invalid auto sync mode: " + mode); } } /** * @return the current auto sync mode */ public int getAutoSyncMode() { return status; } private void switchToCustomAutoSync() { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Switching to custom auto sync"); } Account account = AndroidAccountManager.getNativeAccount(mContext); Enumeration sources = appSyncSourceManager.getEnabledAndWorkingSources(); observers = new Vector<ContentObserver>(); authoritiesWithAutoSync = new Vector<String>(); pendingSources = new Vector<AppSyncSource>(); AndroidAppSyncSource currentSource = (AndroidAppSyncSource) homeScreenController.getCurrentSource(); } private void switchToNativeAutoSync() { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Switching to native auto sync"); } // Remove content observers if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Unregistering content observers"); } for(int i=0; i<observers.size(); i++) { contentResolver.unregisterContentObserver(observers.get(i)); } } /** * Filters the given sources Vector, keep only the ones which really need to * be synchronized. * * @param sources * @return */ private Vector<AppSyncSource> getSourcesToSync(Vector<AppSyncSource> sources) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Retrieving sources to synchronize"); } for(int i=0; i<sources.size(); i++) { AndroidAppSyncSource appSource = (AndroidAppSyncSource)sources.get(i); TrackableSyncSource tss = (TrackableSyncSource)appSource.getSyncSource(); ChangesTracker tracker = tss.getTracker(); if(tracker instanceof AndroidChangesTracker) { AndroidChangesTracker aTracker = (AndroidChangesTracker)tracker; if(aTracker.hasChanges()) { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Changes found in source: " + appSource.getName()); } } else { if (Log.isLoggable(Log.DEBUG)) { Log.debug(TAG_LOG, "Changes not found in source: " + appSource.getName()); } sources.remove(appSource); } } } return sources; } }