prepare new-idle

This commit is contained in:
B. Petersen
2018-06-09 00:53:19 +02:00
parent f0d6aa6a87
commit d709ace71c
8 changed files with 74 additions and 153 deletions
+8 -33
View File
@@ -90,31 +90,6 @@ static void s_init_globals(JNIEnv *env, jclass MrMailbox_class)
}
/* setup threads, only called directly by the backed */
int mrosnative_setup_thread(mrmailbox_t* mailbox)
{
if( s_jvm == NULL ) {
mrmailbox_log_error(mailbox, 0, "Not ready, cannot setup thread.");
return 0;
}
mrmailbox_log_info(mailbox, 0, "Attaching C-thread to Java VM...");
JNIEnv* env = NULL;
(*s_jvm)->AttachCurrentThread(s_jvm, &env, NULL);
mrmailbox_log_info(mailbox, 0, "Attaching ok.");
return 1;
}
void mrosnative_unsetup_thread(mrmailbox_t* mailbox)
{
mrmailbox_log_info(mailbox, 0, "Detaching C-thread from Java VM...");
(*s_jvm)->DetachCurrentThread(s_jvm);
mrmailbox_log_info(mailbox, 0, "DeltaChat", "Detaching done.");
}
/* tools */
static jintArray mrarray2jintArray_n_mrarray_unref(JNIEnv *env, mrarray_t* ca)
@@ -278,27 +253,27 @@ JNIEXPORT jint Java_com_b44t_messenger_MrMailbox_isConfigured(JNIEnv *env, jclas
}
JNIEXPORT jboolean Java_com_b44t_messenger_MrMailbox_idle(JNIEnv *env, jclass cls)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_performJobs(JNIEnv *env, jclass cls)
{
return (jboolean)mrmailbox_idle(get_mrmailbox_t(env, cls));
mrmailbox_perform_jobs(get_mrmailbox_t(env, cls));
}
JNIEXPORT jboolean Java_com_b44t_messenger_MrMailbox_isIdle(JNIEnv *env, jclass cls)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_performIdle(JNIEnv *env, jclass cls)
{
return (jboolean)mrmailbox_is_idle(get_mrmailbox_t(env, cls));
mrmailbox_perform_idle(get_mrmailbox_t(env, cls));
}
JNIEXPORT jboolean Java_com_b44t_messenger_MrMailbox_interruptIdle(JNIEnv *env, jclass cls)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_interruptIdle(JNIEnv *env, jclass cls)
{
return (jboolean)mrmailbox_interrupt_idle(get_mrmailbox_t(env, cls));
mrmailbox_interrupt_idle(get_mrmailbox_t(env, cls));
}
JNIEXPORT jboolean Java_com_b44t_messenger_MrMailbox_poll(JNIEnv *env, jclass cls)
JNIEXPORT void Java_com_b44t_messenger_MrMailbox_performPoll(JNIEnv *env, jclass cls)
{
return (jboolean)mrmailbox_poll(get_mrmailbox_t(env, cls));
mrmailbox_perform_poll(get_mrmailbox_t(env, cls));
}
@@ -147,8 +147,8 @@ public class ApplicationLoader extends Application {
try {
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
s_idleWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "idleWakeLock");
s_idleWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
imapWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "idleWakeLock");
imapWakeLock.setReferenceCounted(false); // if the idle-thread is killed for any reasons, it is better not to rely on reference counting
wakeupWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wakeupWakeLock" /*any name*/);
wakeupWakeLock.setReferenceCounted(false);
@@ -217,7 +217,8 @@ public class ApplicationLoader extends Application {
File dbfile = new File(getFilesDirFixed(), "messenger.db");
MrMailbox.open(dbfile.getAbsolutePath());
if( MrMailbox.isConfigured()!=0 && ApplicationLoader.getPermanentPush() ) {
ApplicationLoader.startIdleThread();
ApplicationLoader.imapForeground = true;
ApplicationLoader.startImapThread();
}
// create other default objects
@@ -288,103 +289,64 @@ public class ApplicationLoader extends Application {
if( permanentPush ) {
applicationContext.startService(new Intent(applicationContext, KeepAliveService.class));
stopIdleThreadPhysically();
startIdleThread(); // restart the idleThread to ensure we set a wake lock
}
else {
applicationContext.stopService(new Intent(applicationContext, KeepAliveService.class));
}
}
private static final Object s_idleThreadCritical = new Object();
private static Thread s_idleThread = null;
private static PowerManager.WakeLock s_idleWakeLock = null;
private static boolean s_switchFromIdleToPoll = false;
private static final Object imapThreadCritical = new Object();
public static Thread imapThread = null;
private static PowerManager.WakeLock imapWakeLock = null;
public static boolean imapForeground = false;
public static boolean imapSwitchToBackground = false;
public static void startIdleThread()
public static void startImapThread()
{
synchronized (s_idleThreadCritical) {
s_switchFromIdleToPoll = false;
imapSwitchToBackground = false;
if (s_idleThread != null && s_idleThread.isAlive() && MrMailbox.isIdle()) {
Log.i("DeltaChat", "Idle thread already started.");
synchronized(imapThreadCritical) {
if( imapThread != null && imapThread.isAlive() ) {
Log.i("DeltaChat", "*** IMAP-Thread is already active, doing nothing.");
return;
}
if( s_idleThread != null ) {
try {
MrMailbox.interruptIdle();
s_idleThread.join(1000);
s_idleThread.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
s_idleThread = null;
}
s_idleThread = new Thread(new Runnable() {
imapThread = new Thread(new Runnable() {
@Override
public void run() {
boolean permanentPush = getPermanentPush();
if( permanentPush ) {
s_idleWakeLock.acquire();
Log.i("DeltaChat", "*** IMAP-Thread started.");
while( true ) {
imapWakeLock.acquire();
MrMailbox.performJobs();
imapWakeLock.release();
if( imapForeground ) {
MrMailbox.performIdle();
}
else {
imapWakeLock.acquire();
MrMailbox.performPoll();
imapWakeLock.release();
break;
}
}
try {
MrMailbox.idle(); // this may run hours ...
} catch (Exception e) {
e.printStackTrace();
}
if( permanentPush ) {
s_idleWakeLock.release();
}
Log.i("DeltaChat", "*** IMAP-Thread stopped.");
}
}, "idleThread");
s_idleThread.start();
}, "imapThread");
imapThread.start();
}
}
public static void scheduleStopIdleThread()
public static void scheduleStopImapThread()
{
synchronized (s_idleThreadCritical) {
if (MrMailbox.isIdle()) {
s_switchFromIdleToPoll = true;
Log.i("DeltaChat", "Will switch from idle to poll on next timer event.");
}
}
}
Log.i("DeltaChat", "*** IMAP-thread scheduled to stop.");
public static void stopIdleThreadPhysically()
{
synchronized (s_idleThreadCritical) {
s_switchFromIdleToPoll = false;
if( s_idleThread==null) {
Log.i("DeltaChat", "No idle thread to stop.");
return;
}
try {
MrMailbox.interruptIdle();
s_idleThread.join(1000);
s_idleThread.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
s_idleThread = null;
}
}
public static boolean getAndResetSwitchFromIdleToPoll()
{
boolean doSwitch = false;
synchronized (s_idleThreadCritical) {
if (s_switchFromIdleToPoll && MrMailbox.isIdle()) {
doSwitch = true;
}
s_switchFromIdleToPoll = false;
}
return doSwitch;
imapSwitchToBackground = true;
}
}
@@ -69,7 +69,9 @@ public class ForegroundDetector implements Application.ActivityLifecycleCallback
}
}
ApplicationLoader.startIdleThread(); // we call this without checking getPermanentPush() to have a simple guarantee that push is always active when the app is in foregroud (startIdleThread makes sure the thread is not started twice)
ApplicationLoader.imapSwitchToBackground = false;
ApplicationLoader.imapForeground = true;
ApplicationLoader.startImapThread(); // we call this without checking getPermanentPush() to have a simple guarantee that push is always active when the app is in foregroud (startIdleThread makes sure the thread is not started twice)
}
public boolean isWasInBackground(boolean reset) {
@@ -98,7 +100,7 @@ public class ForegroundDetector implements Application.ActivityLifecycleCallback
wasInBackground = true;
if( !ApplicationLoader.getPermanentPush() ) {
ApplicationLoader.scheduleStopIdleThread();;
ApplicationLoader.scheduleStopImapThread();;
}
}
else {
@@ -56,10 +56,10 @@ public class MrMailbox {
public native static int isConfigured();
public native static boolean idle();
public native static boolean isIdle();
public native static boolean interruptIdle();
public native static boolean poll();
public native static void performJobs();
public native static void performIdle();
public native static void interruptIdle();
public native static void performPoll();
public native static void setConfig(String key, String value);
public native static void setConfigInt(String key, int value);
@@ -38,7 +38,7 @@ public class ScreenReceiver extends BroadcastReceiver {
// also stop the idle-thread when the screen goes off, this is not always in sync with the ForegroundDetector
if( !ApplicationLoader.getPermanentPush() ) {
ApplicationLoader.scheduleStopIdleThread();
ApplicationLoader.scheduleStopImapThread();
}
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
MrMailbox.log_i("DeltaChat", "*** Screen on");
@@ -360,7 +360,7 @@ public class SettingsAccountFragment extends BaseFragment implements Notificatio
public void run() {
final int res = MrMailbox.configure();
if( res != 0 ) {
ApplicationLoader.startIdleThread();
ApplicationLoader.startImapThread();
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
@@ -31,46 +31,27 @@ import android.content.Intent;
import android.os.Build;
import android.util.Log;
import com.coremedia.iso.boxes.apple.AppleItemListBox;
public class TimerReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// for a discussion about the different approaches to save batter, see https://github.com/deltachat/deltachat-android/issues/104#issuecomment-331670326
if( ApplicationLoader.imapSwitchToBackground ) {
try {
ApplicationLoader.wakeupWakeLock.acquire(); // do this first!
MrMailbox.log_i("DeltaChat", "*** TimerReceiver.onReceive()");
Log.i("DeltaChat", "IMAP-Thread set to background mode.");
// we assume, the IMAP thread is alive. I cannot imagine, the thread was killed with the App being running.
// (if the whole App was killed, the IMAP thread is already started by MrMailbox.connect() if we're here)
// (the thread itself will reconnect to the IMAP server as needed)
// however, it seems as if the threads sleep longer than ususal, check this by calling heartbeat() manually
//
// CAVE: MrMailbox.heartbeat() must not be called from the mainthread - otherwise eg. when the network hangs,
// this function returns only after the network timeout and the ui thread may hang for minutes ...
new Thread(new Runnable() {
@Override
public void run() {
if( ApplicationLoader.getPermanentPush() ) {
MrMailbox.heartbeat();
}
else {
if( ApplicationLoader.getAndResetSwitchFromIdleToPoll() ) {
ApplicationLoader.stopIdleThreadPhysically();
}
else {
MrMailbox.poll();
}
}
}
}).start();
// create the next alarm in about a minute
scheduleNextAlarm();
} finally {
// Always release the wakelock, _if_ there is more to do, the backend acquires an additional wakelock using MR_EVENT_WAKE_LOCK
ApplicationLoader.wakeupWakeLock.release();
ApplicationLoader.imapForeground = false;
MrMailbox.interruptIdle();
}
else {
Log.i("DeltaChat", "IMAP-Thread starting from timer.");
ApplicationLoader.startImapThread(); // do not change imapForeground before; may or may not be in foreground
}
scheduleNextAlarm();
}
public static void scheduleNextAlarm()
@@ -382,7 +382,8 @@ public class WelcomeActivity extends Activity implements NotificationCenter.Noti
}
if( (int)args[0]==1 ) {
ApplicationLoader.startIdleThread(); // import does not automatically connect
ApplicationLoader.imapForeground = true;
ApplicationLoader.startImapThread(); // import does not automatically connect
KeepAliveService kas = KeepAliveService.getInstance();
if( kas != null ) {
kas.updateForegroundNotification();