Merge "Add default phone/sms to battery whitelist apps." into pi-dev

This commit is contained in:
TreeHugger Robot
2018-05-30 03:08:19 +00:00
committed by Android (Google) Code Review
4 changed files with 173 additions and 22 deletions

View File

@@ -16,15 +16,19 @@
package com.android.settingslib.fuelgauge;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.telecom.DefaultDialerManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.ArrayUtils;
/**
@@ -38,19 +42,20 @@ public class PowerWhitelistBackend {
private static PowerWhitelistBackend sInstance;
private final Context mAppContext;
private final IDeviceIdleController mDeviceIdleService;
private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>();
public PowerWhitelistBackend() {
mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(DEVICE_IDLE_SERVICE));
refreshList();
public PowerWhitelistBackend(Context context) {
this(context, IDeviceIdleController.Stub.asInterface(
ServiceManager.getService(DEVICE_IDLE_SERVICE)));
}
@VisibleForTesting
PowerWhitelistBackend(IDeviceIdleController deviceIdleService) {
PowerWhitelistBackend(Context context, IDeviceIdleController deviceIdleService) {
mAppContext = context.getApplicationContext();
mDeviceIdleService = deviceIdleService;
refreshList();
}
@@ -64,7 +69,27 @@ public class PowerWhitelistBackend {
}
public boolean isWhitelisted(String pkg) {
return mWhitelistedApps.contains(pkg);
if (mWhitelistedApps.contains(pkg)) {
return true;
}
// Additionally, check if pkg is default dialer/sms. They are considered essential apps and
// should be automatically whitelisted (otherwise user may be able to set restriction on
// them, leading to bad device behavior.)
if (!mAppContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
return false;
}
final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
true /* updateIfNeeded */);
if (defaultSms != null && TextUtils.equals(pkg, defaultSms.getPackageName())) {
return true;
}
final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
if (TextUtils.equals(pkg, defaultDialer)) {
return true;
}
return false;
}
public boolean isWhitelisted(String[] pkgs) {
@@ -120,16 +145,19 @@ public class PowerWhitelistBackend {
mSysWhitelistedApps.clear();
mSysWhitelistedAppsExceptIdle.clear();
mWhitelistedApps.clear();
if (mDeviceIdleService == null) {
return;
}
try {
String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
final String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
for (String app : whitelistedApps) {
mWhitelistedApps.add(app);
}
String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
final String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
for (String app : sysWhitelistedApps) {
mSysWhitelistedApps.add(app);
}
String[] sysWhitelistedAppsExceptIdle =
final String[] sysWhitelistedAppsExceptIdle =
mDeviceIdleService.getSystemPowerWhitelistExceptIdle();
for (String app : sysWhitelistedAppsExceptIdle) {
mSysWhitelistedAppsExceptIdle.add(app);
@@ -139,9 +167,9 @@ public class PowerWhitelistBackend {
}
}
public static PowerWhitelistBackend getInstance() {
public static PowerWhitelistBackend getInstance(Context context) {
if (sInstance == null) {
sInstance = new PowerWhitelistBackend();
sInstance = new PowerWhitelistBackend(context);
}
return sInstance;
}

View File

@@ -23,35 +23,52 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
import com.android.settingslib.testutils.shadow.ShadowSmsApplication;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(SettingsLibRobolectricTestRunner.class)
@Config(shadows = {ShadowDefaultDialerManager.class, ShadowSmsApplication.class})
public class PowerWhitelistBackendTest {
private static final String PACKAGE_ONE = "com.example.packageone";
private static final String PACKAGE_TWO = "com.example.packagetwo";
private PowerWhitelistBackend mPowerWhitelistBackend;
@Mock
private IDeviceIdleController mDeviceIdleService;
private PowerWhitelistBackend mPowerWhitelistBackend;
private ShadowPackageManager mPackageManager;
private Context mContext;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist();
doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist();
doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
doNothing().when(mDeviceIdleService).addPowerSaveWhitelistApp(anyString());
doNothing().when(mDeviceIdleService).removePowerSaveWhitelistApp(anyString());
mPowerWhitelistBackend = new PowerWhitelistBackend(mDeviceIdleService);
mPackageManager = Shadow.extract(mContext.getPackageManager());
mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY, true);
mPowerWhitelistBackend = new PowerWhitelistBackend(mContext, mDeviceIdleService);
}
@Test
@@ -61,8 +78,8 @@ public class PowerWhitelistBackendTest {
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
mPowerWhitelistBackend.addApp(PACKAGE_TWO);
@@ -70,15 +87,15 @@ public class PowerWhitelistBackendTest {
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(
new String[]{PACKAGE_ONE, PACKAGE_TWO})).isTrue();
new String[] {PACKAGE_ONE, PACKAGE_TWO})).isTrue();
mPowerWhitelistBackend.removeApp(PACKAGE_TWO);
verify(mDeviceIdleService, atLeastOnce()).removePowerSaveWhitelistApp(PACKAGE_TWO);
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
mPowerWhitelistBackend.removeApp(PACKAGE_ONE);
@@ -86,7 +103,23 @@ public class PowerWhitelistBackendTest {
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
assertThat(mPowerWhitelistBackend.isWhitelisted(
new String[]{PACKAGE_ONE, PACKAGE_TWO})).isFalse();
new String[] {PACKAGE_ONE, PACKAGE_TWO})).isFalse();
}
@Test
public void isWhitelisted_shouldWhitelistDefaultSms() {
final String testSms = "com.android.test.defaultsms";
ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
}
@Test
public void isWhitelisted_shouldWhitelistDefaultDialer() {
final String testDialer = "com.android.test.defaultdialer";
ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
}
@Test
@@ -101,7 +134,7 @@ public class PowerWhitelistBackendTest {
@Test
public void testIsSystemWhitelistedExceptIdle_onePackage() throws Exception {
doReturn(new String[]{PACKAGE_TWO}).when(
doReturn(new String[] {PACKAGE_TWO}).when(
mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
mPowerWhitelistBackend.refreshList();
@@ -111,7 +144,7 @@ public class PowerWhitelistBackendTest {
@Test
public void testIsSystemWhitelistedExceptIdle_packageArray() throws Exception {
doReturn(new String[]{PACKAGE_TWO}).when(
doReturn(new String[] {PACKAGE_TWO}).when(
mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
mPowerWhitelistBackend.refreshList();

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.testutils.shadow;
import android.content.Context;
import android.telecom.DefaultDialerManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@Implements(DefaultDialerManager.class)
public class ShadowDefaultDialerManager {
private static String sDefaultDailer;
@Resetter
public void reset() {
sDefaultDailer = null;
}
@Implementation
public static String getDefaultDialerApplication(Context context) {
return sDefaultDailer;
}
public static void setDefaultDialerApplication(String dialer) {
sDefaultDailer = dialer;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.testutils.shadow;
import android.content.ComponentName;
import android.content.Context;
import com.android.internal.telephony.SmsApplication;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@Implements(SmsApplication.class)
public class ShadowSmsApplication {
private static ComponentName sDefaultSmsApplication;
@Resetter
public void reset() {
sDefaultSmsApplication = null;
}
@Implementation
public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
return sDefaultSmsApplication;
}
public static void setDefaultSmsApplication(ComponentName cn) {
sDefaultSmsApplication = cn;
}
}