chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryMonitorFactory.java

// Copyright 2014 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.device.battery;

import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.device.battery.BatteryStatusManager.BatteryStatusCallback;
import org.chromium.device.mojom.BatteryMonitor;
import org.chromium.device.mojom.BatteryStatus;
import org.chromium.services.service_manager.InterfaceFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * Factory that creates instances of BatteryMonitor implementations and notifies them about battery
 * status changes.
 */
public class BatteryMonitorFactory implements InterfaceFactory<BatteryMonitor> {
    private static final String TAG = "BattMonitorFactory";

    // Backing source of battery information.
    private final BatteryStatusManager mManager;
    // Monitors currently interested in the battery status notifications.
    private final HashSet<BatteryMonitorImpl> mSubscribedMonitors =
            new HashSet<BatteryMonitorImpl>();
    // Tracks the latest battery status update for newly added observers.
    private boolean mHasStatusUpdate;
    private BatteryStatus mBatteryStatus;

    private final BatteryStatusCallback mCallback =
            new BatteryStatusCallback() {
                @Override
                public void onBatteryStatusChanged(BatteryStatus batteryStatus) {
                    ThreadUtils.assertOnUiThread();

                    mHasStatusUpdate = true;
                    mBatteryStatus = batteryStatus;

                    List<BatteryMonitorImpl> monitors = new ArrayList<>(mSubscribedMonitors);
                    for (BatteryMonitorImpl monitor : monitors) {
                        monitor.didChange(batteryStatus);
                    }
                }
            };

    public BatteryMonitorFactory() {
        mHasStatusUpdate = false;
        mManager = new BatteryStatusManager(mCallback);
    }

    @Override
    public BatteryMonitor createImpl() {
        ThreadUtils.assertOnUiThread();

        if (mSubscribedMonitors.isEmpty() && !mManager.start()) {
            Log.e(TAG, "BatteryStatusManager failed to start.");
        }

        BatteryMonitorImpl monitor = new BatteryMonitorImpl(this);
        if (mHasStatusUpdate) {
            monitor.didChange(mBatteryStatus);
        }

        mSubscribedMonitors.add(monitor);
        return monitor;
    }

    void unsubscribe(BatteryMonitorImpl monitor) {
        ThreadUtils.assertOnUiThread();

        assert mSubscribedMonitors.contains(monitor);
        mSubscribedMonitors.remove(monitor);
        if (mSubscribedMonitors.isEmpty()) {
            mManager.stop();
            mHasStatusUpdate = false;
        }
    }
}