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

Move PowerUtils to dedicated power management service

Signed-off-by: Chris Narkiewicz <hello@ezaquarii.com>
Chris Narkiewicz 6 жил өмнө
parent
commit
d34d3f5f27

+ 8 - 0
src/main/java/com/nextcloud/client/device/DeviceInfo.kt

@@ -0,0 +1,8 @@
+package com.nextcloud.client.device
+
+import android.os.Build
+
+class DeviceInfo {
+    val vendor: String = Build.MANUFACTURER.toLowerCase()
+    val apiLevel: Int = Build.VERSION.SDK_INT
+}

+ 19 - 0
src/main/java/com/nextcloud/client/device/DeviceModule.kt

@@ -0,0 +1,19 @@
+package com.nextcloud.client.device
+
+import android.content.Context
+import android.os.PowerManager
+import dagger.Module
+import dagger.Provides
+
+@Module
+class DeviceModule {
+
+    @Provides
+    fun powerManagementService(context: Context): PowerManagementService {
+        val platformPowerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+        return PowerManagementServiceImpl(
+            powerManager = platformPowerManager,
+            deviceInfo = DeviceInfo()
+        )
+    }
+}

+ 4 - 0
src/main/java/com/nextcloud/client/device/Package.md

@@ -0,0 +1,4 @@
+# Package com.nextcloud.client.device
+
+This package provides utitilies to access underlying Android 
+hardware API and relevant abstractions.

+ 26 - 0
src/main/java/com/nextcloud/client/device/PowerManagementService.kt

@@ -0,0 +1,26 @@
+package com.nextcloud.client.device
+
+/**
+ * This service provides all device power management
+ * functions.
+ */
+interface PowerManagementService {
+
+    /**
+     * Checks if power saving mode is enabled on this device.
+     * On platforms that do not support power saving mode it
+     * evaluates to false.
+     *
+     * @see android.os.PowerManager.isPowerSaveMode
+     */
+    val isPowerSavingEnabled: Boolean
+
+    /**
+     * Checks if the device vendor requires power saving
+     * exclusion workaround.
+     *
+     * @return true if workaround is required, false otherwise
+     */
+    val isPowerSavingExclusionAvailable: Boolean
+
+}

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

@@ -0,0 +1,32 @@
+package com.nextcloud.client.device
+
+import android.annotation.TargetApi
+import android.os.Build
+import android.os.PowerManager
+
+internal class PowerManagementServiceImpl(
+    private val powerManager: PowerManager,
+    private val deviceInfo: DeviceInfo = DeviceInfo()
+) : PowerManagementService {
+
+    companion object {
+        /**
+         * Vendors on this list use aggressive power saving methods that might
+         * break application experience.
+         */
+        val OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS = setOf("samsung", "huawei", "xiaomi")
+    }
+
+    override val isPowerSavingEnabled: Boolean
+        get() {
+            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+            if (deviceInfo.apiLevel >= Build.VERSION_CODES.LOLLIPOP) {
+                return powerManager.isPowerSaveMode
+            }
+            // For older versions, we just say that device is not in power save mode
+            return false
+        }
+
+    override val isPowerSavingExclusionAvailable: Boolean
+        get() = deviceInfo.vendor in OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS
+}

+ 2 - 0
src/main/java/com/nextcloud/client/di/AppComponent.java

@@ -23,6 +23,7 @@ package com.nextcloud.client.di;
 import android.app.Application;
 
 import com.nextcloud.client.appinfo.AppInfoModule;
+import com.nextcloud.client.device.DeviceModule;
 import com.nextcloud.client.network.NetworkModule;
 import com.nextcloud.client.whatsnew.WhatsNewModule;
 import com.owncloud.android.MainApp;
@@ -39,6 +40,7 @@ import dagger.android.support.AndroidSupportInjectionModule;
     AppInfoModule.class,
     WhatsNewModule.class,
     NetworkModule.class,
+    DeviceModule.class
 })
 @Singleton
 public interface AppComponent {

+ 83 - 0
src/test/java/com/nextcloud/client/device/TestPowerManagementService.kt

@@ -0,0 +1,83 @@
+package com.nextcloud.client.device
+
+import android.os.Build
+import android.os.PowerManager
+import com.nhaarman.mockitokotlin2.never
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.whenever
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.junit.MockitoJUnitRunner
+
+
+@RunWith(MockitoJUnitRunner::class)
+class TestPowerManagementService {
+
+    @Mock
+    lateinit var platformPowerManager: PowerManager
+
+    @Mock
+    lateinit var deviceInfo: DeviceInfo
+
+    private lateinit var powerManagementService: PowerManagementServiceImpl
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        powerManagementService = PowerManagementServiceImpl(
+            powerManager = platformPowerManager,
+            deviceInfo = deviceInfo
+        )
+    }
+
+    @Test
+    fun `power saving queries power manager on API 21+`() {
+        // GIVEN
+        //      API level >= 21
+        //      power save mode is on
+        whenever(deviceInfo.apiLevel).thenReturn(Build.VERSION_CODES.LOLLIPOP)
+        whenever(platformPowerManager.isPowerSaveMode).thenReturn(true)
+
+        // WHEN
+        //      power save mode is checked
+        // THEN
+        //      power save mode is enabled
+        //      state is obtained from platform power manager
+        assertTrue(powerManagementService.isPowerSavingEnabled)
+        verify(platformPowerManager).isPowerSaveMode
+    }
+
+    @Test
+    fun `power saving is not available below API 21`() {
+        // GIVEN
+        //      API level <21
+        whenever(deviceInfo.apiLevel).thenReturn(Build.VERSION_CODES.KITKAT)
+
+        // WHEN
+        //      power save mode is checked
+
+        // THEN
+        //      power save mode is disabled
+        //      power manager is not queried
+        assertFalse(powerManagementService.isPowerSavingEnabled)
+        verify(platformPowerManager, never()).isPowerSaveMode
+    }
+
+    @Test
+    fun `power save exclusion is available for flagged vendors`() {
+        for (vendor in PowerManagementServiceImpl.OVERLY_AGGRESSIVE_POWER_SAVING_VENDORS) {
+            whenever(deviceInfo.vendor).thenReturn(vendor)
+            assertTrue("Vendor $vendor check failed", powerManagementService.isPowerSavingExclusionAvailable)
+        }
+    }
+
+    @Test
+    fun `power save exclusion is not available for other vendors`() {
+        whenever(deviceInfo.vendor).thenReturn("some_other_nice_vendor")
+        assertFalse(powerManagementService.isPowerSavingExclusionAvailable)
+    }
+}

+ 1 - 0
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker

@@ -0,0 +1 @@
+mock-maker-inline