Move PowerUtils to dedicated power management service (#4073)

Move PowerUtils to dedicated power management service
This commit is contained in:
Tobias Kaminsky 2019-05-28 11:30:35 +02:00 committed by GitHub
commit df3ac186b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 279 additions and 0 deletions

View file

@ -0,0 +1,29 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
*
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.device
import android.os.Build
class DeviceInfo {
val vendor: String = Build.MANUFACTURER.toLowerCase()
val apiLevel: Int = Build.VERSION.SDK_INT
}

View file

@ -0,0 +1,40 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
*
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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()
)
}
}

View file

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

View file

@ -0,0 +1,46 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
*
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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
}

View file

@ -0,0 +1,53 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
*
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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
}

View file

@ -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 {

View file

@ -0,0 +1,104 @@
/*
* Nextcloud Android client application
*
* @author Chris Narkiewicz
*
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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.assertFalse
import org.junit.Assert.assertTrue
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)
}
}

View file

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