From e72a789e6913bc2666f266b7fe438109b1d083de Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 14 May 2019 10:36:59 +0200 Subject: [PATCH 1/3] show on special vendors "disable power check" in auto upload menu - tint button - change logic when to show battery warning Signed-off-by: tobiasKaminsky --- .../{DeviceModule.kt => DeviceModule.java} | 27 ++++++------ .../device/PowerManagementServiceImpl.kt | 15 +++++++ .../nextcloud/client/di/ComponentsModule.java | 3 ++ .../client/preferences/AppPreferences.java | 4 ++ .../preferences/AppPreferencesImpl.java | 11 +++++ .../files/BootupBroadcastReceiver.java | 2 +- .../ui/activity/SyncedFoldersActivity.java | 41 ++++++++++++++++--- src/main/res/menu/synced_folders_menu.xml | 6 +++ src/main/res/values/strings.xml | 3 +- .../device/TestPowerManagementService.kt | 26 ++++++++++-- 10 files changed, 114 insertions(+), 24 deletions(-) rename src/main/java/com/nextcloud/client/device/{DeviceModule.kt => DeviceModule.java} (60%) diff --git a/src/main/java/com/nextcloud/client/device/DeviceModule.kt b/src/main/java/com/nextcloud/client/device/DeviceModule.java similarity index 60% rename from src/main/java/com/nextcloud/client/device/DeviceModule.kt rename to src/main/java/com/nextcloud/client/device/DeviceModule.java index 8549d41be322..052fb119d635 100644 --- a/src/main/java/com/nextcloud/client/device/DeviceModule.kt +++ b/src/main/java/com/nextcloud/client/device/DeviceModule.java @@ -19,23 +19,22 @@ * along with this program. If not, see . */ -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 - 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()); } } diff --git a/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt b/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt index c1c41894514b..0f9e642ac3e6 100644 --- a/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt +++ b/src/main/java/com/nextcloud/client/device/PowerManagementServiceImpl.kt @@ -28,10 +28,13 @@ import android.content.IntentFilter import android.os.BatteryManager import android.os.Build import android.os.PowerManager +import com.nextcloud.client.preferences.AppPreferences +import com.nextcloud.client.preferences.AppPreferencesImpl internal class PowerManagementServiceImpl( private val context: Context, private val powerManager: PowerManager, + private val preferences: AppPreferences, private val deviceInfo: DeviceInfo = DeviceInfo() ) : PowerManagementService { @@ -41,10 +44,22 @@ internal class PowerManagementServiceImpl( * break application experience. */ 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 get() { + if (preferences.isPowerCheckDisabled) { + return false + } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) { return powerManager.isPowerSaveMode diff --git a/src/main/java/com/nextcloud/client/di/ComponentsModule.java b/src/main/java/com/nextcloud/client/di/ComponentsModule.java index 2d49f3354098..57a9f39fbde6 100644 --- a/src/main/java/com/nextcloud/client/di/ComponentsModule.java +++ b/src/main/java/com/nextcloud/client/di/ComponentsModule.java @@ -29,6 +29,7 @@ import com.owncloud.android.files.BootupBroadcastReceiver; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.jobs.NContentObserverJob; import com.owncloud.android.jobs.NotificationJob; import com.owncloud.android.providers.DiskLruImageCacheFileProvider; import com.owncloud.android.providers.UsersAndGroupsSearchProvider; @@ -154,4 +155,6 @@ abstract class ComponentsModule { @ContributesAndroidInjector abstract AccountManagerService accountManagerService(); @ContributesAndroidInjector abstract OperationsService operationsService(); + + @ContributesAndroidInjector abstract NContentObserverJob nContentObserverJob(); } diff --git a/src/main/java/com/nextcloud/client/preferences/AppPreferences.java b/src/main/java/com/nextcloud/client/preferences/AppPreferences.java index f963aed37c83..d1b46c12bf8a 100644 --- a/src/main/java/com/nextcloud/client/preferences/AppPreferences.java +++ b/src/main/java/com/nextcloud/client/preferences/AppPreferences.java @@ -296,4 +296,8 @@ public interface AppPreferences { void setPhotoSearchTimestamp(long timestamp); long getPhotoSearchTimestamp(); + + boolean isPowerCheckDisabled(); + + void setPowerCheckDisabled(boolean value); } diff --git a/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index ef832689c166..9e292adfa1a5 100644 --- a/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/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__MIGRATED_USER_ID = "migrated_user_id"; 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 SharedPreferences preferences; @@ -534,4 +535,14 @@ private static String getKeyFromFolder(String preferenceName, OCFile folder) { 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(); + } } diff --git a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java index 42998ed9865f..15a46803090b 100644 --- a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java +++ b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java @@ -40,7 +40,7 @@ /** - * 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. */ public class BootupBroadcastReceiver extends BroadcastReceiver { diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 5a7895acbf62..121897539f15 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -41,6 +41,7 @@ import android.widget.LinearLayout; import android.widget.TextView; +import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.di.Injectable; import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.BuildConfig; @@ -96,7 +97,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener, Injectable { private static final String[] PRIORITIZED_FOLDERS = new String[]{"Camera", "Screenshots"}; - private static final List SPECIAL_MANUFACTURER = Arrays.asList("Samsung", "Huawei", "Xiaomi"); 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 TAG = SyncedFoldersActivity.class.getSimpleName(); @@ -112,6 +112,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA private String path; private int type; @Inject AppPreferences preferences; + @Inject PowerManagementService powerManagementService; @Override protected void onCreate(Bundle savedInstanceState) { @@ -175,9 +176,42 @@ protected void onCreate(Bundle savedInstanceState) { public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); 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; } + 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. */ @@ -691,10 +725,7 @@ protected void onResume() { } 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) .setTitle(getString(R.string.battery_optimization_title)) .setMessage(getString(R.string.battery_optimization_message)) diff --git a/src/main/res/menu/synced_folders_menu.xml b/src/main/res/menu/synced_folders_menu.xml index 745f7a9ceb73..b4f2acb1d51c 100644 --- a/src/main/res/menu/synced_folders_menu.xml +++ b/src/main/res/menu/synced_folders_menu.xml @@ -25,5 +25,11 @@ + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 1154ff12b9a6..dc20f454e982 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -884,7 +884,8 @@ Copy internal link Only works for users with access to this folder Failed to pass file to download manager - + Disable power save check + Disabling power save check might result in uploading files when in low battery state! Engineering Test Mode Preferences diff --git a/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt b/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt index 1e767550ea5b..5bdd0fb9a7a3 100644 --- a/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt +++ b/src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt @@ -26,6 +26,7 @@ import android.content.Intent import android.os.BatteryManager import android.os.Build import android.os.PowerManager +import com.nextcloud.client.preferences.AppPreferences import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.eq @@ -61,13 +62,17 @@ class TestPowerManagementService { internal lateinit var powerManagementService: PowerManagementServiceImpl + @Mock + lateinit var preferences: AppPreferences + @Before fun setUpBase() { MockitoAnnotations.initMocks(this) 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") 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() { From 969ce78e035b957e695184298d2093bcbbc44f1f Mon Sep 17 00:00:00 2001 From: nextcloud-android-bot Date: Tue, 20 Aug 2019 06:45:21 +0000 Subject: [PATCH 2/3] Drone: update FindBugs results to reflect reduced error/warning count [skip ci] Signed-off-by: nextcloud-android-bot --- scripts/analysis/findbugs-results.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt index 36352541cc85..8d4011ad25d8 100644 --- a/scripts/analysis/findbugs-results.txt +++ b/scripts/analysis/findbugs-results.txt @@ -1 +1 @@ -413 +412 \ No newline at end of file From 68cebf83dec20d018dfe3ae937b303962d795658 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 20 Aug 2019 09:45:10 +0200 Subject: [PATCH 3/3] revert DeviceModule back to Kotlin Signed-off-by: tobiasKaminsky --- .../{DeviceModule.java => DeviceModule.kt} | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) rename src/main/java/com/nextcloud/client/device/{DeviceModule.java => DeviceModule.kt} (52%) diff --git a/src/main/java/com/nextcloud/client/device/DeviceModule.java b/src/main/java/com/nextcloud/client/device/DeviceModule.kt similarity index 52% rename from src/main/java/com/nextcloud/client/device/DeviceModule.java rename to src/main/java/com/nextcloud/client/device/DeviceModule.kt index 052fb119d635..e2370501af02 100644 --- a/src/main/java/com/nextcloud/client/device/DeviceModule.java +++ b/src/main/java/com/nextcloud/client/device/DeviceModule.kt @@ -2,8 +2,11 @@ * Nextcloud Android client application * * @author Chris Narkiewicz + * @author Tobias Kaminsky * * Copyright (C) 2019 Chris Narkiewicz + * Copyright (C) 2019 Tobias Kaminsky + * Copyright (C) 2019 Nextcloud GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,22 +22,25 @@ * along with this program. If not, see . */ -package com.nextcloud.client.device; +package com.nextcloud.client.device -import android.content.Context; -import android.os.PowerManager; - -import com.nextcloud.client.preferences.AppPreferences; - -import dagger.Module; -import dagger.Provides; +import android.content.Context +import android.os.PowerManager +import com.nextcloud.client.preferences.AppPreferences +import dagger.Module +import dagger.Provides @Module -public class DeviceModule { - @Provides - PowerManagementService powerManagementService(Context context, AppPreferences preferences) { - PowerManager platformPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); +class DeviceModule { - return new PowerManagementServiceImpl(context, platformPowerManager, preferences, new DeviceInfo()); + @Provides + fun powerManagementService(context: Context, preferences: AppPreferences): PowerManagementService { + val platformPowerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager + return PowerManagementServiceImpl( + context = context, + powerManager = platformPowerManager, + deviceInfo = DeviceInfo(), + preferences = preferences + ) } }