Loading packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java +40 −12 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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(); } Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java +43 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -89,6 +106,22 @@ public class PowerWhitelistBackendTest { 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 public void testIsSystemWhitelisted() throws Exception { doReturn(new String[] {PACKAGE_ONE}).when(mDeviceIdleService).getSystemPowerWhitelist(); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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; } } No newline at end of file packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * 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; } } No newline at end of file Loading
packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java +40 −12 Original line number Diff line number Diff line Loading @@ -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; /** Loading @@ -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(); } Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java +43 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -89,6 +106,22 @@ public class PowerWhitelistBackendTest { 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 public void testIsSystemWhitelisted() throws Exception { doReturn(new String[] {PACKAGE_ONE}).when(mDeviceIdleService).getSystemPowerWhitelist(); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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; } } No newline at end of file
packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * 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; } } No newline at end of file