Эх сурвалжийг харах

show on special vendors "disable power check" in auto upload menu
- tint button
- change logic when to show battery warning

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

tobiasKaminsky 6 жил өмнө
parent
commit
e72a789e69

+ 13 - 14
src/main/java/com/nextcloud/client/device/DeviceModule.kt → src/main/java/com/nextcloud/client/device/DeviceModule.java

@@ -19,23 +19,22 @@
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  */
  */
 
 
-package com.nextcloud.client.device
+package com.nextcloud.client.device;
 
 
-import android.content.Context
-import android.os.PowerManager
-import dagger.Module
-import dagger.Provides
+import android.content.Context;
+import android.os.PowerManager;
 
 
-@Module
-class DeviceModule {
+import com.nextcloud.client.preferences.AppPreferences;
+
+import dagger.Module;
+import dagger.Provides;
 
 
+@Module
+public class DeviceModule {
     @Provides
     @Provides
-    fun powerManagementService(context: Context): PowerManagementService {
-        val platformPowerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
-        return PowerManagementServiceImpl(
-            context = context,
-            powerManager = platformPowerManager,
-            deviceInfo = DeviceInfo()
-        )
+    PowerManagementService powerManagementService(Context context, AppPreferences preferences) {
+        PowerManager platformPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+        return new PowerManagementServiceImpl(context, platformPowerManager, preferences, new DeviceInfo());
     }
     }
 }
 }

+ 15 - 0
src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt

@@ -28,10 +28,13 @@ import android.content.IntentFilter
 import android.os.BatteryManager
 import android.os.BatteryManager
 import android.os.Build
 import android.os.Build
 import android.os.PowerManager
 import android.os.PowerManager
+import com.nextcloud.client.preferences.AppPreferences
+import com.nextcloud.client.preferences.AppPreferencesImpl
 
 
 internal class PowerManagementServiceImpl(
 internal class PowerManagementServiceImpl(
     private val context: Context,
     private val context: Context,
     private val powerManager: PowerManager,
     private val powerManager: PowerManager,
+    private val preferences: AppPreferences,
     private val deviceInfo: DeviceInfo = DeviceInfo()
     private val deviceInfo: DeviceInfo = DeviceInfo()
 ) : PowerManagementService {
 ) : PowerManagementService {
 
 
@@ -41,10 +44,22 @@ internal class PowerManagementServiceImpl(
          * break application experience.
          * break application experience.
          */
          */
         val OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS = setOf("samsung", "huawei", "xiaomi")
         val OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS = setOf("samsung", "huawei", "xiaomi")
+
+        @JvmStatic
+        fun fromContext(context: Context): PowerManagementServiceImpl {
+            val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+            val preferences = AppPreferencesImpl.fromContext(context)
+
+            return PowerManagementServiceImpl(context, powerManager, preferences, DeviceInfo())
+        }
     }
     }
 
 
     override val isPowerSavingEnabled: Boolean
     override val isPowerSavingEnabled: Boolean
         get() {
         get() {
+            if (preferences.isPowerCheckDisabled) {
+                return false
+            }
+
             @TargetApi(Build.VERSION_CODES.LOLLIPOP)
             @TargetApi(Build.VERSION_CODES.LOLLIPOP)
             if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) {
             if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) {
                 return powerManager.isPowerSaveMode
                 return powerManager.isPowerSaveMode

+ 3 - 0
src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -29,6 +29,7 @@ import com.owncloud.android.authentication.DeepLinkLoginActivity;
 import com.owncloud.android.files.BootupBroadcastReceiver;
 import com.owncloud.android.files.BootupBroadcastReceiver;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.jobs.NContentObserverJob;
 import com.owncloud.android.jobs.NotificationJob;
 import com.owncloud.android.jobs.NotificationJob;
 import com.owncloud.android.providers.DiskLruImageCacheFileProvider;
 import com.owncloud.android.providers.DiskLruImageCacheFileProvider;
 import com.owncloud.android.providers.UsersAndGroupsSearchProvider;
 import com.owncloud.android.providers.UsersAndGroupsSearchProvider;
@@ -154,4 +155,6 @@ abstract class ComponentsModule {
 
 
     @ContributesAndroidInjector abstract AccountManagerService accountManagerService();
     @ContributesAndroidInjector abstract AccountManagerService accountManagerService();
     @ContributesAndroidInjector abstract OperationsService operationsService();
     @ContributesAndroidInjector abstract OperationsService operationsService();
+
+    @ContributesAndroidInjector abstract NContentObserverJob nContentObserverJob();
 }
 }

+ 4 - 0
src/main/java/com/nextcloud/client/preferences/AppPreferences.java

@@ -296,4 +296,8 @@ public interface AppPreferences {
     void setPhotoSearchTimestamp(long timestamp);
     void setPhotoSearchTimestamp(long timestamp);
 
 
     long getPhotoSearchTimestamp();
     long getPhotoSearchTimestamp();
+
+    boolean isPowerCheckDisabled();
+
+    void setPowerCheckDisabled(boolean value);
 }
 }

+ 11 - 0
src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

@@ -73,6 +73,7 @@ public final class AppPreferencesImpl implements AppPreferences {
     private static final String PREF__SELECTED_ACCOUNT_NAME = "select_oc_account";
     private static final String PREF__SELECTED_ACCOUNT_NAME = "select_oc_account";
     private static final String PREF__MIGRATED_USER_ID = "migrated_user_id";
     private static final String PREF__MIGRATED_USER_ID = "migrated_user_id";
     private static final String PREF__PHOTO_SEARCH_TIMESTAMP = "photo_search_timestamp";
     private static final String PREF__PHOTO_SEARCH_TIMESTAMP = "photo_search_timestamp";
+    private static final String PREF__POWER_CHECK_DISABLED = "power_check_disabled";
 
 
     private final Context context;
     private final Context context;
     private final SharedPreferences preferences;
     private final SharedPreferences preferences;
@@ -534,4 +535,14 @@ public final class AppPreferencesImpl implements AppPreferences {
 
 
         return preferenceName + "_" + folderIdString;
         return preferenceName + "_" + folderIdString;
     }
     }
+
+    @Override
+    public boolean isPowerCheckDisabled() {
+        return preferences.getBoolean(PREF__POWER_CHECK_DISABLED, false);
+    }
+
+    @Override
+    public void setPowerCheckDisabled(boolean value) {
+        preferences.edit().putBoolean(PREF__POWER_CHECK_DISABLED, value).apply();
+    }
 }
 }

+ 1 - 1
src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java

@@ -40,7 +40,7 @@ import dagger.android.AndroidInjection;
 
 
 
 
 /**
 /**
- * App-registered receiver catching the broadcast intent reporting that the system was 
+ * App-registered receiver catching the broadcast intent reporting that the system was
  * just boot up.
  * just boot up.
  */
  */
 public class BootupBroadcastReceiver extends BroadcastReceiver {
 public class BootupBroadcastReceiver extends BroadcastReceiver {

+ 36 - 5
src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

@@ -41,6 +41,7 @@ import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.TextView;
 
 
+import com.nextcloud.client.device.PowerManagementService;
 import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.owncloud.android.BuildConfig;
 import com.owncloud.android.BuildConfig;
@@ -96,7 +97,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener, Injectable {
         SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener, Injectable {
 
 
     private static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"};
     private static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"};
-    private static final List<String> SPECIAL_MANUFACTURER = Arrays.asList("Samsung", "Huawei", "Xiaomi");
     public static final String EXTRA_SHOW_SIDEBAR = "SHOW_SIDEBAR";
     public static final String EXTRA_SHOW_SIDEBAR = "SHOW_SIDEBAR";
     private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG";
     private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG";
     private static final String TAG = SyncedFoldersActivity.class.getSimpleName();
     private static final String TAG = SyncedFoldersActivity.class.getSimpleName();
@@ -112,6 +112,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
     private String path;
     private String path;
     private int type;
     private int type;
     @Inject AppPreferences preferences;
     @Inject AppPreferences preferences;
+    @Inject PowerManagementService powerManagementService;
 
 
     @Override
     @Override
     protected void onCreate(Bundle savedInstanceState) {
     protected void onCreate(Bundle savedInstanceState) {
@@ -175,9 +176,42 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
     public boolean onCreateOptionsMenu(Menu menu) {
     public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.synced_folders_menu, menu);
         inflater.inflate(R.menu.synced_folders_menu, menu);
+
+        if (powerManagementService.isPowerSavingExclusionAvailable()) {
+            MenuItem item = menu.findItem(R.id.action_disable_power_save_check);
+            item.setVisible(true);
+
+            item.setChecked(preferences.isPowerCheckDisabled());
+
+            item.setOnMenuItemClickListener(this::onDisablePowerSaveCheckClicked);
+        }
+
+        return true;
+    }
+
+    private boolean onDisablePowerSaveCheckClicked(MenuItem powerCheck) {
+        if (!powerCheck.isChecked()) {
+            showPowerCheckDialog();
+        }
+
+        preferences.setPowerCheckDisabled(!powerCheck.isChecked());
+        powerCheck.setChecked(!powerCheck.isChecked());
+
         return true;
         return true;
     }
     }
 
 
+    private void showPowerCheckDialog() {
+        AlertDialog alertDialog = new AlertDialog.Builder(this)
+            .setView(findViewById(R.id.root_layout))
+            .setPositiveButton(R.string.common_ok, (dialog, which) -> dialog.dismiss())
+            .setTitle(ThemeUtils.getColoredTitle(getResources().getString(R.string.autoupload_disable_power_save_check),
+                                                 ThemeUtils.primaryAccentColor(this)))
+            .setMessage(getString(R.string.power_save_check_dialog_message))
+            .show();
+
+        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ThemeUtils.primaryAccentColor(this));
+    }
+
     /**
     /**
      * sets up the UI elements and loads all media/synced folders.
      * sets up the UI elements and loads all media/synced folders.
      */
      */
@@ -691,10 +725,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
     }
     }
 
 
     private void showBatteryOptimizationInfo() {
     private void showBatteryOptimizationInfo() {
-
-        boolean isSpecialManufacturer = SPECIAL_MANUFACTURER.contains(Build.MANUFACTURER.toLowerCase(Locale.ROOT));
-
-        if (isSpecialManufacturer && checkIfBatteryOptimizationEnabled() || checkIfBatteryOptimizationEnabled()) {
+        if (powerManagementService.isPowerSavingExclusionAvailable() || checkIfBatteryOptimizationEnabled()) {
             AlertDialog alertDialog = new AlertDialog.Builder(this, R.style.Theme_ownCloud_Dialog)
             AlertDialog alertDialog = new AlertDialog.Builder(this, R.style.Theme_ownCloud_Dialog)
                 .setTitle(getString(R.string.battery_optimization_title))
                 .setTitle(getString(R.string.battery_optimization_title))
                 .setMessage(getString(R.string.battery_optimization_message))
                 .setMessage(getString(R.string.battery_optimization_message))

+ 6 - 0
src/main/res/menu/synced_folders_menu.xml

@@ -25,5 +25,11 @@
         <item
         <item
             android:id="@+id/action_create_custom_folder"
             android:id="@+id/action_create_custom_folder"
             android:title="@string/autoupload_custom_folder"/>
             android:title="@string/autoupload_custom_folder"/>
+
+        <item
+            android:id="@+id/action_disable_power_save_check"
+            android:title="@string/autoupload_disable_power_save_check"
+            android:visible="false"
+            android:checkable="true" />
     </group>
     </group>
 </menu>
 </menu>

+ 2 - 1
src/main/res/values/strings.xml

@@ -884,7 +884,8 @@
     <string name="copy_internal_link">Copy internal link</string>
     <string name="copy_internal_link">Copy internal link</string>
     <string name="copy_internal_link_subline">Only works for users with access to this folder</string>
     <string name="copy_internal_link_subline">Only works for users with access to this folder</string>
     <string name="failed_to_download">Failed to pass file to download manager</string>
     <string name="failed_to_download">Failed to pass file to download manager</string>
-
+    <string name="autoupload_disable_power_save_check">Disable power save check</string>
+    <string name="power_save_check_dialog_message">Disabling power save check might result in uploading files when in low battery state!</string>
     <string name="etm_title">Engineering Test Mode</string>
     <string name="etm_title">Engineering Test Mode</string>
     <string name="etm_preferences">Preferences</string>
     <string name="etm_preferences">Preferences</string>
 
 

+ 23 - 3
src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt

@@ -26,6 +26,7 @@ import android.content.Intent
 import android.os.BatteryManager
 import android.os.BatteryManager
 import android.os.Build
 import android.os.Build
 import android.os.PowerManager
 import android.os.PowerManager
+import com.nextcloud.client.preferences.AppPreferences
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.any
 import com.nhaarman.mockitokotlin2.anyOrNull
 import com.nhaarman.mockitokotlin2.anyOrNull
 import com.nhaarman.mockitokotlin2.eq
 import com.nhaarman.mockitokotlin2.eq
@@ -61,13 +62,17 @@ class TestPowerManagementService {
 
 
         internal lateinit var powerManagementService: PowerManagementServiceImpl
         internal lateinit var powerManagementService: PowerManagementServiceImpl
 
 
+        @Mock
+        lateinit var preferences: AppPreferences
+
         @Before
         @Before
         fun setUpBase() {
         fun setUpBase() {
             MockitoAnnotations.initMocks(this)
             MockitoAnnotations.initMocks(this)
             powerManagementService = PowerManagementServiceImpl(
             powerManagementService = PowerManagementServiceImpl(
-                context = context,
-                powerManager = platformPowerManager,
-                deviceInfo = deviceInfo
+                context,
+                platformPowerManager,
+                preferences,
+                deviceInfo
             )
             )
         }
         }
     }
     }
@@ -120,6 +125,21 @@ class TestPowerManagementService {
             whenever(deviceInfo.vendor).thenReturn("some_other_nice_vendor")
             whenever(deviceInfo.vendor).thenReturn("some_other_nice_vendor")
             assertFalse(powerManagementService.isPowerSavingExclusionAvailable)
             assertFalse(powerManagementService.isPowerSavingExclusionAvailable)
         }
         }
+
+        @Test
+        fun `power saving check is disabled`() {
+            // GIVEN
+            //      a device which falsely returns power save mode enabled
+            //      power check is overridden by user
+            whenever(preferences.isPowerCheckDisabled).thenReturn(true)
+            whenever(platformPowerManager.isPowerSaveMode).thenReturn(true)
+
+            // WHEN
+            //      power save mode is checked
+            // THEN
+            //      power saving is disabled
+            assertFalse(powerManagementService.isPowerSavingEnabled)
+        }
     }
     }
 
 
     class BatteryCharging : Base() {
     class BatteryCharging : Base() {