Loading core/java/android/os/PowerManager.java +4 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.os; import android.annotation.FlaggedApi; import android.Manifest.permission; import android.annotation.CallbackExecutor; import android.annotation.CurrentTimeMillisLong; Loading Loading @@ -3103,7 +3102,8 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby is enabled or disabled. * This broadcast is only sent to registered receivers. * This broadcast is only sent to registered receivers and receivers holding * {@code android.permission.MANAGE_LOW_POWER_STANDBY}. * * @see #isLowPowerStandbyEnabled() */ Loading @@ -3113,7 +3113,8 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby policy is changed. * This broadcast is only sent to registered receivers. * This broadcast is only sent to registered receivers and receivers holding * {@code android.permission.MANAGE_LOW_POWER_STANDBY}. * * @see #isExemptFromLowPowerStandby() * @see #isAllowedInLowPowerStandby(int) Loading @@ -3125,7 +3126,6 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby exempt ports change. * This broadcast is only sent to registered receivers. * * @see #getActiveLowPowerStandbyPorts * @hide Loading services/core/java/com/android/server/power/LowPowerStandbyController.java +29 −8 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; Loading Loading @@ -146,6 +147,7 @@ public class LowPowerStandbyController { this::onStandbyTimeoutExpired; private final LowPowerStandbyControllerInternal mLocalService = new LocalService(); private final SparseIntArray mUidAllowedReasons = new SparseIntArray(); private final List<String> mLowPowerStandbyManagingPackages = new ArrayList<>(); private final List<StandbyPortsLock> mStandbyPortLocks = new ArrayList<>(); @GuardedBy("mLock") Loading Loading @@ -370,6 +372,14 @@ public class LowPowerStandbyController { return; } List<PackageInfo> manageLowPowerStandbyPackages = mContext.getPackageManager() .getPackagesHoldingPermissions(new String[]{ Manifest.permission.MANAGE_LOW_POWER_STANDBY }, PackageManager.MATCH_SYSTEM_ONLY); for (PackageInfo packageInfo : manageLowPowerStandbyPackages) { mLowPowerStandbyManagingPackages.add(packageInfo.packageName); } mAlarmManager = mContext.getSystemService(AlarmManager.class); mPowerManager = mContext.getSystemService(PowerManager.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); Loading Loading @@ -756,9 +766,7 @@ public class LowPowerStandbyController { Slog.d(TAG, "notifyEnabledChangedLocked, mIsEnabled=" + mIsEnabled); } final Intent intent = new Intent(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); sendExplicitBroadcast(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); } @GuardedBy("mLock") Loading @@ -772,10 +780,7 @@ public class LowPowerStandbyController { Slog.d(TAG, "notifyPolicyChanged, policy=" + policy); } final Intent intent = new Intent( PowerManager.ACTION_LOW_POWER_STANDBY_POLICY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); sendExplicitBroadcast(PowerManager.ACTION_LOW_POWER_STANDBY_POLICY_CHANGED); } private void onStandbyTimeoutExpired() { Loading @@ -787,6 +792,22 @@ public class LowPowerStandbyController { } } private void sendExplicitBroadcast(String intentType) { final Intent intent = new Intent(intentType); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); // Send explicit broadcast to holders of MANAGE_LOW_POWER_STANDBY final Intent privilegedIntent = new Intent(intentType); privilegedIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); for (String packageName : mLowPowerStandbyManagingPackages) { final Intent explicitIntent = new Intent(privilegedIntent); explicitIntent.setPackage(packageName); mContext.sendBroadcastAsUser(explicitIntent, UserHandle.ALL, Manifest.permission.MANAGE_LOW_POWER_STANDBY); } } @GuardedBy("mLock") private void enqueueNotifyActiveChangedLocked() { final Message msg = mHandler.obtainMessage(MSG_NOTIFY_ACTIVE_CHANGED, mIsActive); Loading Loading @@ -1360,7 +1381,7 @@ public class LowPowerStandbyController { } final Intent intent = new Intent(PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.MANAGE_LOW_POWER_STANDBY); } Loading services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java +63 −3 Original line number Diff line number Diff line Loading @@ -49,8 +49,11 @@ import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IForegroundServiceObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; Loading @@ -68,7 +71,7 @@ import android.provider.Settings; import android.test.mock.MockContentResolver; import android.util.ArraySet; import androidx.test.InstrumentationRegistry; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; Loading @@ -85,9 +88,11 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; Loading Loading @@ -145,7 +150,8 @@ public class LowPowerStandbyControllerTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContextSpy = spy(new BroadcastInterceptingContext(InstrumentationRegistry.getContext())); mContextSpy = spy(new BroadcastInterceptingContext(InstrumentationRegistry .getInstrumentation().getTargetContext())); when(mContextSpy.getPackageManager()).thenReturn(mPackageManagerMock); when(mContextSpy.getSystemService(AlarmManager.class)).thenReturn(mAlarmManagerMock); when(mContextSpy.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); Loading Loading @@ -395,26 +401,65 @@ public class LowPowerStandbyControllerTest { setLowPowerStandbySupportedConfig(true); mController.systemReady(); TestReceiver receiver = new TestReceiver(); mContextSpy.registerReceiver(receiver, new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(false); futureIntent.assertNotReceived(); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(true); assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); assertThat(receiver.receivedCount).isEqualTo(1); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(true); futureIntent.assertNotReceived(); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(false); assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); assertThat(receiver.receivedCount).isEqualTo(1); receiver.reset(); } @Test public void testLowPowerStandbyEnabled_EnabledChangedExplicitBroadcastSent() throws Exception { setLowPowerStandbySupportedConfig(true); List<PackageInfo> packagesHoldingPermission = new ArrayList<>(); when(mPackageManagerMock.getPackagesHoldingPermissions(Mockito.any(), Mockito.anyInt())).thenReturn(packagesHoldingPermission); PackageInfo testInfo = new PackageInfo(); testInfo.packageName = mContextSpy.getPackageName(); packagesHoldingPermission.add(testInfo); mController.systemReady(); TestReceiver receiver = new TestReceiver(); mContextSpy.registerReceiver(receiver, new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); mController.setEnabled(false); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); mController.setEnabled(true); // Since we added a package manually to the packages that are allowed to // manage LPS, the interceptor should have intercepted two broadcasts, one // implicit via registration and one explicit to the package added above. assertThat(receiver.receivedCount).isEqualTo(2); receiver.reset(); } @Test Loading Loading @@ -906,4 +951,19 @@ public class LowPowerStandbyControllerTest { LocalServices.removeServiceForTest(clazz); LocalServices.addService(clazz, mock); } public static class TestReceiver extends BroadcastReceiver { public int receivedCount = 0; /** * Resets the count of this receiver */ public void reset() { receivedCount = 0; } @Override public void onReceive(Context context, Intent intent) { receivedCount++; } } } Loading
core/java/android/os/PowerManager.java +4 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.os; import android.annotation.FlaggedApi; import android.Manifest.permission; import android.annotation.CallbackExecutor; import android.annotation.CurrentTimeMillisLong; Loading Loading @@ -3103,7 +3102,8 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby is enabled or disabled. * This broadcast is only sent to registered receivers. * This broadcast is only sent to registered receivers and receivers holding * {@code android.permission.MANAGE_LOW_POWER_STANDBY}. * * @see #isLowPowerStandbyEnabled() */ Loading @@ -3113,7 +3113,8 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby policy is changed. * This broadcast is only sent to registered receivers. * This broadcast is only sent to registered receivers and receivers holding * {@code android.permission.MANAGE_LOW_POWER_STANDBY}. * * @see #isExemptFromLowPowerStandby() * @see #isAllowedInLowPowerStandby(int) Loading @@ -3125,7 +3126,6 @@ public final class PowerManager { /** * Intent that is broadcast when Low Power Standby exempt ports change. * This broadcast is only sent to registered receivers. * * @see #getActiveLowPowerStandbyPorts * @hide Loading
services/core/java/com/android/server/power/LowPowerStandbyController.java +29 −8 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; Loading Loading @@ -146,6 +147,7 @@ public class LowPowerStandbyController { this::onStandbyTimeoutExpired; private final LowPowerStandbyControllerInternal mLocalService = new LocalService(); private final SparseIntArray mUidAllowedReasons = new SparseIntArray(); private final List<String> mLowPowerStandbyManagingPackages = new ArrayList<>(); private final List<StandbyPortsLock> mStandbyPortLocks = new ArrayList<>(); @GuardedBy("mLock") Loading Loading @@ -370,6 +372,14 @@ public class LowPowerStandbyController { return; } List<PackageInfo> manageLowPowerStandbyPackages = mContext.getPackageManager() .getPackagesHoldingPermissions(new String[]{ Manifest.permission.MANAGE_LOW_POWER_STANDBY }, PackageManager.MATCH_SYSTEM_ONLY); for (PackageInfo packageInfo : manageLowPowerStandbyPackages) { mLowPowerStandbyManagingPackages.add(packageInfo.packageName); } mAlarmManager = mContext.getSystemService(AlarmManager.class); mPowerManager = mContext.getSystemService(PowerManager.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); Loading Loading @@ -756,9 +766,7 @@ public class LowPowerStandbyController { Slog.d(TAG, "notifyEnabledChangedLocked, mIsEnabled=" + mIsEnabled); } final Intent intent = new Intent(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); sendExplicitBroadcast(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); } @GuardedBy("mLock") Loading @@ -772,10 +780,7 @@ public class LowPowerStandbyController { Slog.d(TAG, "notifyPolicyChanged, policy=" + policy); } final Intent intent = new Intent( PowerManager.ACTION_LOW_POWER_STANDBY_POLICY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); sendExplicitBroadcast(PowerManager.ACTION_LOW_POWER_STANDBY_POLICY_CHANGED); } private void onStandbyTimeoutExpired() { Loading @@ -787,6 +792,22 @@ public class LowPowerStandbyController { } } private void sendExplicitBroadcast(String intentType) { final Intent intent = new Intent(intentType); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); // Send explicit broadcast to holders of MANAGE_LOW_POWER_STANDBY final Intent privilegedIntent = new Intent(intentType); privilegedIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); for (String packageName : mLowPowerStandbyManagingPackages) { final Intent explicitIntent = new Intent(privilegedIntent); explicitIntent.setPackage(packageName); mContext.sendBroadcastAsUser(explicitIntent, UserHandle.ALL, Manifest.permission.MANAGE_LOW_POWER_STANDBY); } } @GuardedBy("mLock") private void enqueueNotifyActiveChangedLocked() { final Message msg = mHandler.obtainMessage(MSG_NOTIFY_ACTIVE_CHANGED, mIsActive); Loading Loading @@ -1360,7 +1381,7 @@ public class LowPowerStandbyController { } final Intent intent = new Intent(PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.MANAGE_LOW_POWER_STANDBY); } Loading
services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java +63 −3 Original line number Diff line number Diff line Loading @@ -49,8 +49,11 @@ import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IForegroundServiceObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Resources; Loading @@ -68,7 +71,7 @@ import android.provider.Settings; import android.test.mock.MockContentResolver; import android.util.ArraySet; import androidx.test.InstrumentationRegistry; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; Loading @@ -85,9 +88,11 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; Loading Loading @@ -145,7 +150,8 @@ public class LowPowerStandbyControllerTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContextSpy = spy(new BroadcastInterceptingContext(InstrumentationRegistry.getContext())); mContextSpy = spy(new BroadcastInterceptingContext(InstrumentationRegistry .getInstrumentation().getTargetContext())); when(mContextSpy.getPackageManager()).thenReturn(mPackageManagerMock); when(mContextSpy.getSystemService(AlarmManager.class)).thenReturn(mAlarmManagerMock); when(mContextSpy.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); Loading Loading @@ -395,26 +401,65 @@ public class LowPowerStandbyControllerTest { setLowPowerStandbySupportedConfig(true); mController.systemReady(); TestReceiver receiver = new TestReceiver(); mContextSpy.registerReceiver(receiver, new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(false); futureIntent.assertNotReceived(); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(true); assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); assertThat(receiver.receivedCount).isEqualTo(1); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(true); futureIntent.assertNotReceived(); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); futureIntent = mContextSpy.nextBroadcastIntent( PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); mController.setEnabled(false); assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull(); assertThat(receiver.receivedCount).isEqualTo(1); receiver.reset(); } @Test public void testLowPowerStandbyEnabled_EnabledChangedExplicitBroadcastSent() throws Exception { setLowPowerStandbySupportedConfig(true); List<PackageInfo> packagesHoldingPermission = new ArrayList<>(); when(mPackageManagerMock.getPackagesHoldingPermissions(Mockito.any(), Mockito.anyInt())).thenReturn(packagesHoldingPermission); PackageInfo testInfo = new PackageInfo(); testInfo.packageName = mContextSpy.getPackageName(); packagesHoldingPermission.add(testInfo); mController.systemReady(); TestReceiver receiver = new TestReceiver(); mContextSpy.registerReceiver(receiver, new IntentFilter(PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED)); mController.setEnabled(false); assertThat(receiver.receivedCount).isEqualTo(0); receiver.reset(); mController.setEnabled(true); // Since we added a package manually to the packages that are allowed to // manage LPS, the interceptor should have intercepted two broadcasts, one // implicit via registration and one explicit to the package added above. assertThat(receiver.receivedCount).isEqualTo(2); receiver.reset(); } @Test Loading Loading @@ -906,4 +951,19 @@ public class LowPowerStandbyControllerTest { LocalServices.removeServiceForTest(clazz); LocalServices.addService(clazz, mock); } public static class TestReceiver extends BroadcastReceiver { public int receivedCount = 0; /** * Resets the count of this receiver */ public void reset() { receivedCount = 0; } @Override public void onReceive(Context context, Intent intent) { receivedCount++; } } }