/*
* Copyright (C) 2015 Actor LLC. <https://actor.im>
*/
package im.actor.runtime.android;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import im.actor.runtime.util.ExponentialBackoff;
import im.actor.runtime.Runtime;
import im.actor.runtime.actors.ThreadPriority;
import im.actor.runtime.android.threading.AndroidDispatcher;
import im.actor.runtime.android.threading.AndroidImmediateDispatcher;
import im.actor.runtime.android.time.SntpClient;
import im.actor.runtime.generic.GenericThreadingProvider;
import im.actor.runtime.Log;
import im.actor.runtime.threading.Dispatcher;
import im.actor.runtime.threading.ImmediateDispatcher;
public class AndroidThreadingProvider extends GenericThreadingProvider {
private static final String PROPS = "time_sync.ini";
private SharedPreferences preference;
private long syncDelta;
private String serverHost;
public AndroidThreadingProvider() {
this.serverHost = "europe.pool.ntp.org";
Runtime.dispatch(() -> {
this.preference = AndroidContext.getContext().getSharedPreferences(PROPS, Context.MODE_PRIVATE);
this.syncDelta = preference.getLong("delta", syncDelta);
invalidateSync();
IntentFilter timeChangedFilter = new IntentFilter();
timeChangedFilter.addAction(Intent.ACTION_TIME_CHANGED);
timeChangedFilter.addAction(Intent.ACTION_DATE_CHANGED);
AndroidContext.getContext().registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("AndroidClockSync", "Time changed: invalidating sync");
invalidateSync();
}
}, timeChangedFilter);
});
}
// TODO: Better invalidation
private void invalidateSync() {
Log.d("AndroidClockSync", "Starting sync...");
new Thread() {
@Override
public void run() {
SntpClient client = new SntpClient();
ExponentialBackoff exponentialBackoff = new ExponentialBackoff();
while (!client.requestTime(serverHost, 10000)) {
exponentialBackoff.onFailure();
try {
Thread.sleep(exponentialBackoff.exponentialWait());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
syncDelta = client.getClockOffset();
preference.edit().putLong("delta", syncDelta).commit();
Log.d("AndroidClockSync", "Synced. Time delta: " + syncDelta + " ms");
}
}.start();
}
@Override
public long getSyncedCurrentTime() {
return System.currentTimeMillis() + syncDelta;
}
@Override
public Dispatcher createDispatcher(String name) {
return new AndroidDispatcher(name);
}
@Override
public ImmediateDispatcher createImmediateDispatcher(String name, ThreadPriority priority) {
return new AndroidImmediateDispatcher(name, priority);
}
}