/*
* *
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* /
*/
package org.anhonesteffort.flock.sync;
import android.accounts.Account;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SyncInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import org.anhonesteffort.flock.util.guava.Optional;
import org.anhonesteffort.flock.DavAccountHelper;
import org.anhonesteffort.flock.PreferencesActivity;
import org.anhonesteffort.flock.auth.DavAccount;
import org.anhonesteffort.flock.sync.key.KeySyncScheduler;
/**
* Programmer: rhodey
*/
public abstract class AbstractSyncScheduler extends ContentObserver {
public static final String EXTRA_FORCE_SYNC = "AbstractSyncScheduler.EXTRA_FORCE_SYNC";
private static final String PREFERENCES_NAME = "AbstractSyncScheduler.PREFERENCES_NAME";
private static final String KEY_SYNC_OVERRIDDEN = "AbstractSyncScheduler.KEY_SYNC_OVERRIDDEN";
private static final String KEY_TIME_LAST_SYNC = "AbstractSyncScheduler.KEY_TIME_LAST_SYNC";
protected Context context;
public AbstractSyncScheduler(Context context) {
super(null);
this.context = context;
}
protected abstract String getTAG();
protected abstract String getAuthority();
protected abstract Uri getUri();
public void registerSelfForBroadcasts() {
context.getContentResolver().unregisterContentObserver(this);
context.getContentResolver().registerContentObserver(getUri(), false, this);
}
public boolean syncInProgress(Account account) {
for (SyncInfo syncInfo : ContentResolver.getCurrentSyncs()) {
if (syncInfo.account.type.equals(account.type) && syncInfo.authority.equals(getAuthority()))
return true;
}
return ContentResolver.isSyncActive(account, getAuthority());
}
public boolean getIsSyncEnabled(Account account) {
return ContentResolver.getIsSyncable(account, getAuthority()) > 0;
}
public void setSyncEnabled(Account account, boolean enabled) {
if (!enabled && getAuthority().equals(KeySyncScheduler.CONTENT_AUTHORITY)) {
Log.w(getTAG(), "cannot disable key sync service, not changing sync setting.");
return;
}
ContentResolver.setIsSyncable(account, getAuthority(), enabled ? 1 : 0);
}
public void cancelPendingSyncs(Account account) {
ContentResolver.cancelSync(account, getAuthority());
}
private void requestSync(boolean force) {
Bundle extras = new Bundle();
Optional<DavAccount> account = DavAccountHelper.getAccount(context);
if (!account.isPresent()) {
Log.e(getTAG(), "account not present, cannot request sync.");
return;
}
handleInitSyncAdapter();
extras.putBoolean(EXTRA_FORCE_SYNC, force);
ContentResolver.requestSync(account.get().getOsAccount(), getAuthority(), extras);
}
public void requestSync() {
requestSync(true);
}
public void setSyncInterval(int minutes) {
long SECONDS_PER_MINUTE = 60L;
long SYNC_INTERVAL = minutes * SECONDS_PER_MINUTE;
Log.d(getTAG(), "setSyncInterval() " + minutes);
Optional<DavAccount> account = DavAccountHelper.getAccount(context);
if (!account.isPresent()) {
Log.e(getTAG(), "account not present, interval cannot be set");
return;
}
if (minutes > 0) {
ContentResolver.addPeriodicSync(account.get().getOsAccount(),
getAuthority(),
new Bundle(),
SYNC_INTERVAL);
}
}
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
}
public int getSyncIntervalMinutes() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return Integer.valueOf(
preferences.getString(PreferencesActivity.KEY_PREF_SYNC_INTERVAL_MINUTES, "60")
);
}
public void restoreSyncIntervalFromUserSetting() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
setSyncInterval(Integer.valueOf(
preferences.getString(PreferencesActivity.KEY_PREF_SYNC_INTERVAL_MINUTES, "60")
));
}
public void setTimeLastSync(Long timeMilliseconds) {
getSharedPreferences(context).edit().putLong(
KEY_TIME_LAST_SYNC + getAuthority(), timeMilliseconds
).apply();
}
public Optional<Long> getTimeLastSync() {
Long timeMilliseconds = getSharedPreferences(context).getLong(KEY_TIME_LAST_SYNC + getAuthority(), -1);
if (timeMilliseconds == -1)
return Optional.absent();
return Optional.of(timeMilliseconds);
}
public void onAccountRemoved() {
Log.d(getTAG(), "onAccountRemoved()");
getSharedPreferences(context).edit().putBoolean(
KEY_SYNC_OVERRIDDEN + getAuthority(), false
).apply();
}
private void handleInitSyncAdapter() {
SharedPreferences settings = getSharedPreferences(context);
if (settings.getBoolean(KEY_SYNC_OVERRIDDEN + getAuthority(), false))
return;
Optional<DavAccount> account = DavAccountHelper.getAccount(context);
if (!account.isPresent()) {
Log.e(getTAG(), "account not present, cannot init sync adapter");
return;
}
ContentResolver.setSyncAutomatically(account.get().getOsAccount(), getAuthority(), true);
settings.edit().putBoolean(KEY_SYNC_OVERRIDDEN + getAuthority(), true).apply();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
setSyncInterval(Integer.valueOf(
preferences.getString(PreferencesActivity.KEY_PREF_SYNC_INTERVAL_MINUTES, "60")
));
}
@Override
public void onChange(boolean selfChange, Uri changeUri) {
SharedPreferences settings = getSharedPreferences(context);
Optional<DavAccount> account = DavAccountHelper.getAccount(context);
if (account.isPresent())
handleInitSyncAdapter();
if (settings.getBoolean(PreferencesActivity.KEY_PREF_SYNC_ON_CONTENT_CHANGE, true) &&
account.isPresent())
{
requestSync(false);
}
}
@Override
public void onChange(boolean selfChange) {
onChange(selfChange, null);
}
}