Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce0bfdfc authored by David Zhao's avatar David Zhao Committed by Android (Google) Code Review
Browse files

Merge changes I01ca2e85,Id7667c0d into main

* changes:
  Add unit test for Explicit LPS mode updates
  Send LowPowerStandby broadcasts also to receivers holding permission
parents 271961a5 f405bbf8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.os;

import android.annotation.FlaggedApi;
import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.CurrentTimeMillisLong;
@@ -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()
     */
@@ -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)
@@ -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
+29 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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")
@@ -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);
@@ -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")
@@ -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() {
@@ -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);
@@ -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);
    }
+63 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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);
@@ -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
@@ -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++;
        }
    }
}