From 8cb91051974e28ea4f061f7e82584a738fc6db8d Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 2 Aug 2016 19:12:50 +0200 Subject: [PATCH 1/3] Moved shouldRun check into DeviceStateHolder. --- .../syncthing/DeviceStateHolder.java | 55 ++++++++++++++++++- .../syncthing/SyncthingService.java | 49 +---------------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java index d31c842d..133675cc 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java @@ -4,10 +4,16 @@ import android.annotation.TargetApi; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.BatteryManager; +import android.preference.PreferenceManager; +import android.util.Log; + +import java.util.HashSet; +import java.util.Set; /** * Holds information about the current wifi and charging state of the device. @@ -17,6 +23,8 @@ import android.os.BatteryManager; */ public class DeviceStateHolder extends BroadcastReceiver { + private static final String TAG = "DeviceStateHolder"; + /** * Intent extra containing a boolean saying whether wifi is connected or not. */ @@ -91,7 +99,52 @@ public class DeviceStateHolder extends BroadcastReceiver { } } - public String getWifiSsid() { + private String getWifiSsid() { return mWifiSsid; } + + public boolean shouldRun() { + if (SyncthingService.alwaysRunInBackground(mContext)) { + // Always run, ignoring wifi/charging state. + return true; + } + else { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); + // Check wifi/charging state against preferences and start if ok. + boolean prefStopMobileData = prefs.getBoolean(SyncthingService.PREF_SYNC_ONLY_WIFI, false); + boolean prefStopNotCharging = prefs.getBoolean(SyncthingService.PREF_SYNC_ONLY_CHARGING, false); + + return (isCharging() || !prefStopNotCharging) && + (!prefStopMobileData || isAllowedWifiConnected()); + } + } + + private boolean isAllowedWifiConnected() { + boolean wifiConnected = isWifiConnected(); + if (wifiConnected) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + Set ssids = sp.getStringSet(SyncthingService.PREF_SYNC_ONLY_WIFI_SSIDS, new HashSet()); + if (ssids.isEmpty()) { + Log.d(TAG, "All SSIDs allowed for syncing"); + return true; + } else { + String ssid = getWifiSsid(); + if (ssid != null) { + if (ssids.contains(ssid)) { + Log.d(TAG, "SSID [" + ssid + "] found in whitelist: " + ssids); + return true; + } + Log.i(TAG, "SSID [" + ssid + "] not whitelisted: " + ssids); + return false; + } else { + // Don't know the SSID (yet) (should not happen?!), so not allowing + Log.w(TAG, "SSID unknown (yet), cannot check SSID whitelist. Disallowing sync."); + return false; + } + } + } + Log.d(TAG, "Wifi not connected"); + return false; + } + } diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java index 1b0a4439..d4185e81 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java @@ -1,12 +1,9 @@ package com.nutomic.syncthingandroid.syncthing; -import android.app.Activity; -import android.app.AlertDialog; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -22,7 +19,6 @@ import android.widget.Toast; import com.nutomic.syncthingandroid.R; import com.nutomic.syncthingandroid.activities.MainActivity; -import com.nutomic.syncthingandroid.activities.SettingsActivity; import com.nutomic.syncthingandroid.util.ConfigXml; import com.nutomic.syncthingandroid.util.FolderObserver; import com.nutomic.syncthingandroid.util.PRNGFixes; @@ -194,23 +190,8 @@ public class SyncthingService extends Service implements * called. */ public void updateState() { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean shouldRun; - if (!alwaysRunInBackground(this)) { - // Always run, ignoring wifi/charging state. - shouldRun = true; - } - else { - // Check wifi/charging state against preferences and start if ok. - boolean prefStopMobileData = prefs.getBoolean(PREF_SYNC_ONLY_WIFI, false); - boolean prefStopNotCharging = prefs.getBoolean(PREF_SYNC_ONLY_CHARGING, false); - - shouldRun = (mDeviceStateHolder.isCharging() || !prefStopNotCharging) && - (!prefStopMobileData || isAllowedWifiConnected()); - } - // Start syncthing. - if (shouldRun) { + if (mDeviceStateHolder.shouldRun()) { if (mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) { mStopScheduled = false; return; @@ -257,34 +238,6 @@ public class SyncthingService extends Service implements onApiChange(); } - private boolean isAllowedWifiConnected() { - boolean wifiConnected = mDeviceStateHolder.isWifiConnected(); - if (wifiConnected) { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); - Set ssids = sp.getStringSet(PREF_SYNC_ONLY_WIFI_SSIDS, new HashSet()); - if (ssids.isEmpty()) { - Log.d(TAG, "All SSIDs allowed for syncing"); - return true; - } else { - String ssid = mDeviceStateHolder.getWifiSsid(); - if (ssid != null) { - if (ssids.contains(ssid)) { - Log.d(TAG, "SSID [" + ssid + "] found in whitelist: " + ssids); - return true; - } - Log.i(TAG, "SSID [" + ssid + "] not whitelisted: " + ssids); - return false; - } else { - // Don't know the SSID (yet) (should not happen?!), so not allowing - Log.w(TAG, "SSID unknown (yet), cannot check SSID whitelist. Disallowing sync."); - return false; - } - } - } - Log.d(TAG, "Wifi not connected"); - return false; - } - /** * Shows or hides the persistent notification based on running state and * {@link #PREF_NOTIFICATION_TYPE}. From 2daa601e363efad61e96229c10c19f1ed3c298fb Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 2 Aug 2016 19:17:22 +0200 Subject: [PATCH 2/3] Disable sync if Android sync setting is disabled (fixes #588). --- src/main/AndroidManifest.xml | 1 + .../syncthing/DeviceStateHolder.java | 10 ++++++++-- .../syncthingandroid/syncthing/SyncthingService.java | 12 ++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index c20520c9..e2ea9e1d 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + mOnApiChangeListeners = new HashSet<>(); + private final SyncStatusObserver mSyncStatusObserver = new SyncStatusObserver() { + @Override + public void onStatusChanged(int i) { + updateState(); + } + }; + /** * INIT: Service is starting up and initializing. * STARTING: Syncthing binary is starting (but the API is not yet ready). @@ -314,6 +323,8 @@ public class SyncthingService extends Service implements registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); new StartupTask(sp.getString("gui_user",""), sp.getString("gui_password","")).execute(); sp.registerOnSharedPreferenceChangeListener(this); + ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, + mSyncStatusObserver); } /** @@ -420,6 +431,7 @@ public class SyncthingService extends Service implements SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); sp.unregisterOnSharedPreferenceChangeListener(this); + ContentResolver.removeStatusChangeListener(mSyncStatusObserver); } private void shutdown() { From c1d5bcc4cdb02eb40ab60030f304515682ba4ba3 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 2 Aug 2016 21:44:51 +0200 Subject: [PATCH 3/3] Disable Syncthing if battery saving mode is active (fixes #603). --- .../syncthing/DeviceStateHolder.java | 15 +++++++++++---- .../syncthing/SyncthingService.java | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java index 924b4793..b8cbea77 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/DeviceStateHolder.java @@ -10,6 +10,8 @@ import android.net.ConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.BatteryManager; +import android.os.Build; +import android.os.PowerManager; import android.preference.PreferenceManager; import android.util.Log; @@ -107,14 +109,16 @@ public class DeviceStateHolder extends BroadcastReceiver { /** * Determines if Syncthing should currently run. */ + @TargetApi(21) public boolean shouldRun() { - if (!ContentResolver.getMasterSyncAutomatically()) { + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB && pm.isPowerSaveMode()) { + return false; + } + else if (!ContentResolver.getMasterSyncAutomatically()) { return false; } else if (SyncthingService.alwaysRunInBackground(mContext)) { - return true; - } - else { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); // Check wifi/charging state against preferences and start if ok. boolean prefStopMobileData = prefs.getBoolean(SyncthingService.PREF_SYNC_ONLY_WIFI, false); @@ -123,6 +127,9 @@ public class DeviceStateHolder extends BroadcastReceiver { return (isCharging() || !prefStopNotCharging) && (!prefStopMobileData || isAllowedWifiConnected()); } + else { + return true; + } } private boolean isAllowedWifiConnected() { diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java index b90d4ec8..e5960a4b 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java @@ -1,8 +1,10 @@ package com.nutomic.syncthingandroid.syncthing; +import android.annotation.TargetApi; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -13,6 +15,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Environment; import android.os.IBinder; +import android.os.PowerManager; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; @@ -133,6 +136,13 @@ public class SyncthingService extends Service implements } }; + private final BroadcastReceiver mPowerSaveModeChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateState(); + } + }; + /** * INIT: Service is starting up and initializing. * STARTING: Syncthing binary is starting (but the API is not yet ready). @@ -301,6 +311,7 @@ public class SyncthingService extends Service implements * Starts the native binary. */ @Override + @TargetApi(21) public void onCreate() { PRNGFixes.apply(); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); @@ -321,6 +332,11 @@ public class SyncthingService extends Service implements mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this); registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { + registerReceiver(mPowerSaveModeChangedReceiver, + new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); + } + new StartupTask(sp.getString("gui_user",""), sp.getString("gui_password","")).execute(); sp.registerOnSharedPreferenceChangeListener(this); ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, @@ -432,6 +448,8 @@ public class SyncthingService extends Service implements SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); sp.unregisterOnSharedPreferenceChangeListener(this); ContentResolver.removeStatusChangeListener(mSyncStatusObserver); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) + unregisterReceiver(mPowerSaveModeChangedReceiver); } private void shutdown() {