mirror of
https://github.com/M66B/FairEmail.git
synced 2025-01-01 12:44:42 +00:00
Refactoring
This commit is contained in:
parent
682c92b56b
commit
1a072cde2a
1 changed files with 274 additions and 280 deletions
|
@ -86,8 +86,12 @@ import androidx.lifecycle.Observer;
|
|||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||
|
||||
public class ServiceSynchronize extends LifecycleService {
|
||||
private Core.State state;
|
||||
private boolean started = false;
|
||||
private int queued = 0;
|
||||
private long lastLost = 0;
|
||||
private TupleAccountStats lastStats = new TupleAccountStats();
|
||||
private ServiceManager serviceManager = new ServiceManager();
|
||||
private ExecutorService queue = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
|
||||
private static boolean booted = false;
|
||||
|
||||
|
@ -114,7 +118,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
// Removed because of Android VPN service
|
||||
// builder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
|
||||
cm.registerNetworkCallback(builder.build(), serviceManager);
|
||||
cm.registerNetworkCallback(builder.build(), networkCallback);
|
||||
|
||||
DB db = DB.getInstance(this);
|
||||
|
||||
|
@ -142,9 +146,13 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
Log.i("Service destroy");
|
||||
|
||||
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
cm.unregisterNetworkCallback(serviceManager);
|
||||
cm.unregisterNetworkCallback(networkCallback);
|
||||
|
||||
serviceManager.service_destroy();
|
||||
synchronized (this) {
|
||||
EntityLog.log(this, "Service destroy");
|
||||
if (started)
|
||||
queue_reload(false, "service destroy");
|
||||
}
|
||||
|
||||
Widget.update(this, -1);
|
||||
|
||||
|
@ -172,23 +180,23 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
try {
|
||||
switch (action) {
|
||||
case "init":
|
||||
serviceManager.service_init();
|
||||
onInit();
|
||||
break;
|
||||
|
||||
case "alarm":
|
||||
serviceManager.service_alarm();
|
||||
onAlarm();
|
||||
break;
|
||||
|
||||
case "reload":
|
||||
serviceManager.service_reload(intent.getStringExtra("reason"));
|
||||
onReload(intent.getStringExtra("reason"));
|
||||
break;
|
||||
|
||||
case "oneshot_start":
|
||||
serviceManager.service_oneshot(true);
|
||||
onOneshot(true);
|
||||
break;
|
||||
|
||||
case "oneshot_end":
|
||||
serviceManager.service_oneshot(false);
|
||||
onOneshot(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -231,6 +239,230 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
return builder;
|
||||
}
|
||||
|
||||
private void onInit() {
|
||||
EntityLog.log(this, "Service init");
|
||||
// Network events will manage the service
|
||||
}
|
||||
|
||||
private void onAlarm() {
|
||||
schedule(this);
|
||||
onReload("alarm");
|
||||
}
|
||||
|
||||
private void onReload(String reason) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
queue_reload(true, reason);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onOneshot(boolean start) {
|
||||
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent alarm = new Intent(this, ServiceSynchronize.class);
|
||||
alarm.setAction("oneshot_end");
|
||||
PendingIntent piOneshot;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
piOneshot = PendingIntent.getService(this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
else
|
||||
piOneshot = PendingIntent.getForegroundService(this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
am.cancel(piOneshot);
|
||||
|
||||
if (start) {
|
||||
// Network events will manage the service
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
||||
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
else
|
||||
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
} else {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
prefs.edit().putBoolean("oneshot", false).apply();
|
||||
queue_reload(true, "oneshot");
|
||||
}
|
||||
}
|
||||
|
||||
private void queue_reload(final boolean start, final String reason) {
|
||||
final boolean doStop = started;
|
||||
final boolean doStart = (start && isEnabled() && Helper.suitableNetwork(this, true));
|
||||
|
||||
EntityLog.log(this, "Queue reload" +
|
||||
" doStop=" + doStop + " doStart=" + doStart + " queued=" + queued + " " + reason);
|
||||
|
||||
started = doStart;
|
||||
|
||||
queued++;
|
||||
queue.submit(new Runnable() {
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":manage");
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
|
||||
try {
|
||||
wl.acquire();
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Reload" +
|
||||
" stop=" + doStop + " start=" + doStart + " queued=" + queued + " " + reason);
|
||||
|
||||
if (doStop)
|
||||
stop();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
for (EntityAccount account : db.account().getAccountsTbd())
|
||||
nm.deleteNotificationChannel(EntityAccount.getNotificationChannelName(account.id));
|
||||
}
|
||||
|
||||
int accounts = db.account().deleteAccountsTbd();
|
||||
int identities = db.identity().deleteIdentitiesTbd();
|
||||
if (accounts > 0 || identities > 0)
|
||||
Log.i("Deleted accounts=" + accounts + " identities=" + identities);
|
||||
|
||||
if (doStart)
|
||||
start();
|
||||
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
} finally {
|
||||
queued--;
|
||||
EntityLog.log(ServiceSynchronize.this, "Reload done queued=" + queued);
|
||||
|
||||
if (queued == 0 && !isEnabled()) {
|
||||
try {
|
||||
Thread.sleep(STOP_DELAY);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
if (queued == 0 && !isEnabled())
|
||||
stopService();
|
||||
}
|
||||
|
||||
wl.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isEnabled() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
boolean oneshot = prefs.getBoolean("oneshot", false);
|
||||
return (enabled || oneshot);
|
||||
}
|
||||
|
||||
private void start() {
|
||||
EntityLog.log(this, "Main start");
|
||||
|
||||
state = new Core.State();
|
||||
state.runnable(new Runnable() {
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":main");
|
||||
private List<Core.State> threadState = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wl.acquire();
|
||||
|
||||
final DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
|
||||
long ago = new Date().getTime() - lastLost;
|
||||
if (ago < RECONNECT_BACKOFF)
|
||||
try {
|
||||
long backoff = RECONNECT_BACKOFF - ago;
|
||||
EntityLog.log(ServiceSynchronize.this, "Main backoff=" + (backoff / 1000));
|
||||
if (state.acquire(backoff))
|
||||
return;
|
||||
} catch (InterruptedException ex) {
|
||||
Log.w("main backoff " + ex.toString());
|
||||
}
|
||||
|
||||
// Start monitoring accounts
|
||||
List<EntityAccount> accounts = db.account().getSynchronizingAccounts();
|
||||
for (final EntityAccount account : accounts) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
|
||||
if (account.notify)
|
||||
account.createNotificationChannel(ServiceSynchronize.this);
|
||||
else
|
||||
account.deleteNotificationChannel(ServiceSynchronize.this);
|
||||
|
||||
Log.i(account.host + "/" + account.user + " run");
|
||||
final Core.State astate = new Core.State();
|
||||
astate.runnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
monitorAccount(account, astate);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
EntityLog.log(ServiceSynchronize.this, account.name + " " + Helper.formatThrowable(ex));
|
||||
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
||||
}
|
||||
}
|
||||
}, "sync.account." + account.id);
|
||||
astate.start();
|
||||
threadState.add(astate);
|
||||
}
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Main started");
|
||||
|
||||
try {
|
||||
wl.release();
|
||||
state.acquire();
|
||||
} catch (InterruptedException ex) {
|
||||
Log.w("main wait " + ex.toString());
|
||||
} finally {
|
||||
wl.acquire();
|
||||
}
|
||||
|
||||
// Stop monitoring accounts
|
||||
for (Core.State astate : threadState)
|
||||
astate.stop();
|
||||
for (Core.State astate : threadState)
|
||||
astate.join();
|
||||
threadState.clear();
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Main exited");
|
||||
} catch (Throwable ex) {
|
||||
// Fail-safe
|
||||
Log.e(ex);
|
||||
} finally {
|
||||
wl.release();
|
||||
EntityLog.log(ServiceSynchronize.this, "Start wake lock=" + wl.isHeld());
|
||||
}
|
||||
}
|
||||
}, "sync.main");
|
||||
state.start();
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
EntityLog.log(this, "Main stop");
|
||||
|
||||
state.stop();
|
||||
state.join();
|
||||
|
||||
EntityLog.log(this, "Main stopped");
|
||||
|
||||
state = null;
|
||||
}
|
||||
|
||||
private void stopService() {
|
||||
EntityLog.log(this, "Service stop");
|
||||
|
||||
DB db = DB.getInstance(this);
|
||||
List<EntityOperation> ops = db.operation().getOperations(EntityOperation.SYNC);
|
||||
for (EntityOperation op : ops)
|
||||
db.folder().setFolderSyncState(op.folder, null);
|
||||
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
private void monitorAccount(final EntityAccount account, final Core.State state) throws NoSuchProviderException {
|
||||
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
final PowerManager.WakeLock wlAccount = pm.newWakeLock(
|
||||
|
@ -245,7 +477,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
Log.i(account.name + " run");
|
||||
|
||||
// Debug
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
boolean debug = (prefs.getBoolean("debug", false) || BuildConfig.BETA_RELEASE);
|
||||
//System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
||||
|
||||
|
@ -776,7 +1008,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
Log.i(account.name + " done state=" + state);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(account.name, ex);
|
||||
Core.reportError(ServiceSynchronize.this, account, null, ex);
|
||||
Core.reportError(this, account, null, ex);
|
||||
|
||||
EntityLog.log(this, account.name + " " + Helper.formatThrowable(ex));
|
||||
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
||||
|
@ -873,16 +1105,10 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
}
|
||||
}
|
||||
|
||||
private class ServiceManager extends ConnectivityManager.NetworkCallback {
|
||||
private Core.State state;
|
||||
private boolean started = false;
|
||||
private int queued = 0;
|
||||
private long lastLost = 0;
|
||||
private ExecutorService queue = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
|
||||
|
||||
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
synchronized (this) {
|
||||
synchronized (ServiceSynchronize.this) {
|
||||
try {
|
||||
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
EntityLog.log(ServiceSynchronize.this, "Available " + network + " " + cm.getNetworkInfo(network));
|
||||
|
@ -897,7 +1123,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
|
||||
@Override
|
||||
public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
|
||||
synchronized (this) {
|
||||
synchronized (ServiceSynchronize.this) {
|
||||
try {
|
||||
if (!started) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Network " + network + " capabilities " + capabilities);
|
||||
|
@ -912,7 +1138,7 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
synchronized (this) {
|
||||
synchronized (ServiceSynchronize.this) {
|
||||
try {
|
||||
EntityLog.log(ServiceSynchronize.this, "Lost " + network);
|
||||
|
||||
|
@ -925,237 +1151,50 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
boolean oneshot = prefs.getBoolean("oneshot", false);
|
||||
return (enabled || oneshot);
|
||||
}
|
||||
|
||||
private void service_init() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service init");
|
||||
// Network events will manage the service
|
||||
}
|
||||
|
||||
private void service_alarm() {
|
||||
schedule(ServiceSynchronize.this);
|
||||
service_reload("alarm");
|
||||
}
|
||||
|
||||
private void service_reload(String reason) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
serviceManager.queue_reload(true, reason);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void service_oneshot(boolean start) {
|
||||
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent alarm = new Intent(ServiceSynchronize.this, ServiceSynchronize.class);
|
||||
alarm.setAction("oneshot_end");
|
||||
PendingIntent piOneshot;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
|
||||
piOneshot = PendingIntent.getService(ServiceSynchronize.this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
else
|
||||
piOneshot = PendingIntent.getForegroundService(ServiceSynchronize.this, PI_ONESHOT, alarm, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
am.cancel(piOneshot);
|
||||
|
||||
if (start) {
|
||||
// Network events will manage the service
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
||||
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
else
|
||||
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ONESHOT_DURATION, piOneshot);
|
||||
} else {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSynchronize.this);
|
||||
prefs.edit().putBoolean("oneshot", false).apply();
|
||||
queue_reload(true, "oneshot");
|
||||
}
|
||||
}
|
||||
|
||||
private void service_destroy() {
|
||||
synchronized (this) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service destroy");
|
||||
if (started)
|
||||
queue_reload(false, "service destroy");
|
||||
}
|
||||
}
|
||||
|
||||
private void start() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Main start");
|
||||
|
||||
state = new Core.State();
|
||||
state.runnable(new Runnable() {
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":main");
|
||||
private List<Core.State> threadState = new ArrayList<>();
|
||||
static void boot(final Context context) {
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
wl.acquire();
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
final DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
// Reset state
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().remove("oneshot").apply();
|
||||
|
||||
long ago = new Date().getTime() - lastLost;
|
||||
if (ago < RECONNECT_BACKOFF)
|
||||
try {
|
||||
long backoff = RECONNECT_BACKOFF - ago;
|
||||
EntityLog.log(ServiceSynchronize.this, "Main backoff=" + (backoff / 1000));
|
||||
if (state.acquire(backoff))
|
||||
return;
|
||||
} catch (InterruptedException ex) {
|
||||
Log.w("main backoff " + ex.toString());
|
||||
}
|
||||
for (EntityAccount account : db.account().getAccounts())
|
||||
db.account().setAccountState(account.id, null);
|
||||
|
||||
// Start monitoring accounts
|
||||
List<EntityAccount> accounts = db.account().getSynchronizingAccounts();
|
||||
for (final EntityAccount account : accounts) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
|
||||
if (account.notify)
|
||||
account.createNotificationChannel(ServiceSynchronize.this);
|
||||
else
|
||||
account.deleteNotificationChannel(ServiceSynchronize.this);
|
||||
|
||||
Log.i(account.host + "/" + account.user + " run");
|
||||
final Core.State astate = new Core.State();
|
||||
astate.runnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
monitorAccount(account, astate);
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
EntityLog.log(ServiceSynchronize.this, account.name + " " + Helper.formatThrowable(ex));
|
||||
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
||||
}
|
||||
}
|
||||
}, "sync.account." + account.id);
|
||||
astate.start();
|
||||
threadState.add(astate);
|
||||
for (EntityFolder folder : db.folder().getFolders()) {
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
db.folder().setFolderSyncState(folder.id, null);
|
||||
}
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Main started");
|
||||
// Restore snooze timers
|
||||
for (EntityMessage message : db.message().getSnoozed())
|
||||
EntityMessage.snooze(context, message.id, message.ui_snoozed);
|
||||
|
||||
try {
|
||||
wl.release();
|
||||
state.acquire();
|
||||
} catch (InterruptedException ex) {
|
||||
Log.w("main wait " + ex.toString());
|
||||
} finally {
|
||||
wl.acquire();
|
||||
}
|
||||
|
||||
// Stop monitoring accounts
|
||||
for (Core.State astate : threadState)
|
||||
astate.stop();
|
||||
for (Core.State astate : threadState)
|
||||
astate.join();
|
||||
threadState.clear();
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Main exited");
|
||||
} catch (Throwable ex) {
|
||||
// Fail-safe
|
||||
Log.e(ex);
|
||||
} finally {
|
||||
wl.release();
|
||||
EntityLog.log(ServiceSynchronize.this, "Start wake lock=" + wl.isHeld());
|
||||
}
|
||||
}
|
||||
}, "sync.main");
|
||||
state.start();
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Main stop");
|
||||
|
||||
state.stop();
|
||||
state.join();
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Main stopped");
|
||||
|
||||
state = null;
|
||||
}
|
||||
|
||||
private void queue_reload(final boolean start, final String reason) {
|
||||
final boolean doStop = started;
|
||||
final boolean doStart = (start && isEnabled() && Helper.suitableNetwork(ServiceSynchronize.this, true));
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Queue reload" +
|
||||
" doStop=" + doStop + " doStart=" + doStart + " queued=" + queued + " " + reason);
|
||||
|
||||
started = doStart;
|
||||
|
||||
queued++;
|
||||
queue.submit(new Runnable() {
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
PowerManager.WakeLock wl = pm.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":manage");
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
|
||||
try {
|
||||
wl.acquire();
|
||||
|
||||
EntityLog.log(ServiceSynchronize.this, "Reload" +
|
||||
" stop=" + doStop + " start=" + doStart + " queued=" + queued + " " + reason);
|
||||
|
||||
if (doStop)
|
||||
stop();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
for (EntityAccount account : db.account().getAccountsTbd())
|
||||
nm.deleteNotificationChannel(EntityAccount.getNotificationChannelName(account.id));
|
||||
}
|
||||
|
||||
int accounts = db.account().deleteAccountsTbd();
|
||||
int identities = db.identity().deleteIdentitiesTbd();
|
||||
if (accounts > 0 || identities > 0)
|
||||
Log.i("Deleted accounts=" + accounts + " identities=" + identities);
|
||||
|
||||
if (doStart)
|
||||
start();
|
||||
// Restore schedule
|
||||
schedule(context);
|
||||
|
||||
// Conditionally init service
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
int accounts = db.account().getSynchronizingAccounts().size();
|
||||
if (enabled && accounts > 0)
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("init"));
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
} finally {
|
||||
queued--;
|
||||
EntityLog.log(ServiceSynchronize.this, "Reload done queued=" + queued);
|
||||
|
||||
if (queued == 0 && !isEnabled()) {
|
||||
try {
|
||||
Thread.sleep(STOP_DELAY);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
if (queued == 0 && !isEnabled())
|
||||
stopService();
|
||||
}
|
||||
|
||||
wl.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void stopService() {
|
||||
EntityLog.log(ServiceSynchronize.this, "Service stop");
|
||||
|
||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||
List<EntityOperation> ops = db.operation().getOperations(EntityOperation.SYNC);
|
||||
for (EntityOperation op : ops)
|
||||
db.folder().setFolderSyncState(op.folder, null);
|
||||
|
||||
stopSelf();
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1217,51 +1256,6 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
am.set(AlarmManager.RTC_WAKEUP, next, piAlarm);
|
||||
}
|
||||
|
||||
static void boot(final Context context) {
|
||||
if (!booted) {
|
||||
booted = true;
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
// Reset state
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefs.edit().remove("oneshot").apply();
|
||||
|
||||
for (EntityAccount account : db.account().getAccounts())
|
||||
db.account().setAccountState(account.id, null);
|
||||
|
||||
for (EntityFolder folder : db.folder().getFolders()) {
|
||||
db.folder().setFolderState(folder.id, null);
|
||||
db.folder().setFolderSyncState(folder.id, null);
|
||||
}
|
||||
|
||||
// Restore snooze timers
|
||||
for (EntityMessage message : db.message().getSnoozed())
|
||||
EntityMessage.snooze(context, message.id, message.ui_snoozed);
|
||||
|
||||
// Restore schedule
|
||||
schedule(context);
|
||||
|
||||
// Conditionally init service
|
||||
boolean enabled = prefs.getBoolean("enabled", true);
|
||||
int accounts = db.account().getSynchronizingAccounts().size();
|
||||
if (enabled && accounts > 0)
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
.setAction("init"));
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
static void reschedule(Context context) {
|
||||
ContextCompat.startForegroundService(context,
|
||||
new Intent(context, ServiceSynchronize.class)
|
||||
|
|
Loading…
Reference in a new issue