chromium/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/PowerSavingModeMonitor.java

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.night_mode;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;

import androidx.annotation.Nullable;

import org.chromium.base.ApplicationState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.ContextUtils;
import org.chromium.base.ObserverList;

/** Observes and keeps a record of whether the system power saving mode is on. */
public class PowerSavingModeMonitor {
    private static PowerSavingModeMonitor sInstance;

    /** Returns the instance of this singleton. */
    public static PowerSavingModeMonitor getInstance() {
        if (sInstance == null) {
            sInstance = new PowerSavingModeMonitor();
        }
        return sInstance;
    }

    private final ObserverList<Runnable> mObservers = new ObserverList<>();
    @Nullable private final PowerManager mPowerManager;
    @Nullable private BroadcastReceiver mPowerModeReceiver;

    private boolean mPowerSavingIsOn;

    /** Returns whether power saving mode is currently on. */
    public boolean powerSavingIsOn() {
        return mPowerSavingIsOn;
    }

    /** Adds an observer of power saving mode changes. */
    public void addObserver(Runnable observer) {
        mObservers.addObserver(observer);
    }

    /** Removes an observer of power saving mode changes. */
    public void removeObserver(Runnable observer) {
        mObservers.removeObserver(observer);
    }

    private PowerSavingModeMonitor() {
        mPowerManager =
                (PowerManager)
                        ContextUtils.getApplicationContext()
                                .getSystemService(Context.POWER_SERVICE);

        updatePowerSaveMode();
        updateAccordingToAppState();
        ApplicationStatus.registerApplicationStateListener(state -> updateAccordingToAppState());
    }

    private void updateAccordingToAppState() {
        final int applicationState = ApplicationStatus.getStateForApplication();
        if (applicationState == ApplicationState.HAS_RUNNING_ACTIVITIES
                || applicationState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
            start();
        } else {
            stop();
        }
    }

    private void start() {
        if (mPowerModeReceiver == null) {
            mPowerModeReceiver =
                    new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            updatePowerSaveMode();
                        }
                    };
            ContextUtils.registerProtectedBroadcastReceiver(
                    ContextUtils.getApplicationContext(),
                    mPowerModeReceiver,
                    new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
        }
        updatePowerSaveMode();
    }

    private void stop() {
        if (mPowerModeReceiver != null) {
            ContextUtils.getApplicationContext().unregisterReceiver(mPowerModeReceiver);
            mPowerModeReceiver = null;
        }
    }

    private void updatePowerSaveMode() {
        boolean newValue = mPowerManager != null && mPowerManager.isPowerSaveMode();
        if (newValue == mPowerSavingIsOn) return;

        mPowerSavingIsOn = newValue;
        for (Runnable observer : mObservers) {
            observer.run();
        }
    }
}