chromium/chrome/browser/ash/power/auto_screen_brightness/light_provider_mojo.h

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

#ifndef CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_LIGHT_PROVIDER_MOJO_H_
#define CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_LIGHT_PROVIDER_MOJO_H_

#include <map>
#include <optional>
#include <string>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/ash/power/auto_screen_brightness/als_reader.h"
#include "chrome/browser/ash/power/auto_screen_brightness/light_samples_observer.h"
#include "chromeos/components/sensors/mojom/cros_sensor_service.mojom.h"
#include "chromeos/components/sensors/mojom/sensor.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace ash {
namespace power {
namespace auto_screen_brightness {

class LightProviderMojoTest;

// Used when IIO Service is present. It registers to Sensor Hal Dispatcher as a
// sensor client and waits for the connection to CrOS IIO Service. Once
// connected, it asks for samples of the light sensor (cros-ec-light or
// acpi-als).
class LightProviderMojo
    : public LightProviderInterface,
      public chromeos::sensors::mojom::SensorHalClient,
      public chromeos::sensors::mojom::SensorServiceNewDevicesObserver {
 public:
  explicit LightProviderMojo(AlsReader* als_reader);
  LightProviderMojo(const LightProviderMojo&) = delete;
  LightProviderMojo& operator=(const LightProviderMojo&) = delete;
  ~LightProviderMojo() override;

  // chromeos::sensors::mojom::SensorHalClient:
  void SetUpChannel(mojo::PendingRemote<chromeos::sensors::mojom::SensorService>
                        pending_remote) override;

  // chromeos::sensors::mojom::SensorServiceNewDevicesObserver
  void OnNewDeviceAdded(
      int32_t iio_device_id,
      const std::vector<chromeos::sensors::mojom::DeviceType>& types) override;

 private:
  friend LightProviderMojoTest;

  struct LightData {
    LightData();
    ~LightData();

    // Something wrong with attributes of this light sensor or simply not needed
    // if true.
    bool ignored = false;
    std::optional<std::string> name;
    std::optional<bool> on_lid;

    // Temporarily stores the remote, waiting for its attributes information.
    // It'll be passed to LightProviderMojo' constructor as an argument after
    // all information is collected, if this sensor is needed.
    mojo::Remote<chromeos::sensors::mojom::SensorDevice> remote;
  };

  void OnNewDevicesObserverDisconnect();
  // Timeout of new devices. If the target light sensor is still not present,
  // assumes it not supported, notifies observers with
  // AlsReader::AlsInitStatus::kIncorrectConfig, and fails the initialization.
  void OnNewDevicesTimeout();

  // Registers chromeos::sensors::mojom::SensorHalClient to Sensor Hal
  // Dispatcher, waiting for the Mojo connection to IIO Service.
  void RegisterSensorClient();
  void OnSensorHalClientFailure();

  void OnSensorServiceDisconnect();
  void ResetSensorService();

  // Called when an in-use device is unplugged, and we need to search for other
  // devices to use.
  // Assumes that the angle device won't be unplugged.
  void ResetStates();
  void QueryDevices();

  // Callback of GetDeviceIds(LIGHT), containing all iio_device_ids of light
  // sensors.
  void GetLightIdsCallback(const std::vector<int32_t>& light_ids);

  // Creates the Mojo channel for the light sensor, and requests the light
  // sensor's required attributes before determining which one to be used.
  void RegisterLightWithId(int32_t id);
  void GetNameLocationCallback(
      int32_t id,
      const std::vector<std::optional<std::string>>& values);

  // Ignores the light with |id| due to some errors of it's attributes.
  void IgnoreLight(int32_t id);

  mojo::Remote<chromeos::sensors::mojom::SensorDevice> GetSensorDeviceRemote(
      int32_t id);
  void OnLightRemoteDisconnect(int32_t id,
                               uint32_t custom_reason_code,
                               const std::string& description);

  void DetermineLightSensor(int32_t id);
  void SetupLightSamplesObserver();

  // The Mojo channel connecting to Sensor Hal Dispatcher.
  mojo::Receiver<chromeos::sensors::mojom::SensorHalClient> sensor_hal_client_{
      this};

  // The Mojo channel to query and request for devices.
  mojo::Remote<chromeos::sensors::mojom::SensorService> sensor_service_remote_;

  // The Mojo channel to get notified when new devices are added to IIO Service.
  mojo::Receiver<chromeos::sensors::mojom::SensorServiceNewDevicesObserver>
      new_devices_observer_{this};

  // First is the light sensor's iio device id, second is it's data and mojo
  // remote.
  std::map<int32_t, LightData> lights_;

  bool als_init_status_set_ = false;
  // The device id of light to be used.
  std::optional<int32_t> light_device_id_;

  // The observer that waits for the wanted light sensor's samples and sends
  // them to |als_reader_|.
  std::unique_ptr<LightSamplesObserver> observer_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<LightProviderMojo> weak_ptr_factory_{this};
};

}  // namespace auto_screen_brightness
}  // namespace power
}  // namespace ash

#endif  // CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_LIGHT_PROVIDER_MOJO_H_