// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef ASH_ACCELEROMETER_ACCELEROMETER_PROVIDER_MOJO_H_ #define ASH_ACCELEROMETER_ACCELEROMETER_PROVIDER_MOJO_H_ #include #include #include #include #include #include "ash/accelerometer/accelerometer_reader.h" #include "ash/accelerometer/accelerometer_samples_observer.h" #include "ash/ash_export.h" #include "base/sequence_checker.h" #include "chromeos/components/sensors/mojom/cros_sensor_service.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { // As devices may be late-present, the state and available devices cannot be // determined within any given time or requests. This MojoState helps // AccelerometerProviderMojo determine the current available devices and // provides a clear finite state machine. States that should provide samples: // LID, LID_BASE, ANGL_LID. enum class MojoState { INITIALIZING, // No devices available yet. LID, // Only lid-accelerometer is available. BASE, // Only base-accelerometer is available. LID_BASE, // Both accelerometers are available. ANGL, // Only lid-angle driver is available. ANGL_LID, // Both lid-angle driver and lid-accelerometer are available. }; class AccelerometerProviderMojoTest; // Work that runs on the UI thread. As a sensor client, it communicates with IIO // Service, determines the accelerometers' configuration, and waits for the // accelerometers' samples. Upon receiving a sample, it will notify all // observers. class ASH_EXPORT AccelerometerProviderMojo : public AccelerometerProviderInterface, public chromeos::sensors::mojom::SensorHalClient, public chromeos::sensors::mojom::SensorServiceNewDevicesObserver { public: AccelerometerProviderMojo(); AccelerometerProviderMojo(const AccelerometerProviderMojo&) = delete; AccelerometerProviderMojo& operator=(const AccelerometerProviderMojo&) = delete; // AccelerometerProviderInterface: void PrepareAndInitialize() override; void TriggerRead() override; void CancelRead() override; // chromeos::sensors::mojom::SensorHalClient: void SetUpChannel(mojo::PendingRemote pending_remote) override; // chromeos::sensors::mojom::SensorServiceNewDevicesObserver void OnNewDeviceAdded( int32_t iio_device_id, const std::vector& types) override; MojoState GetInitializationStateForTesting() const; protected: // AccelerometerProviderInterface: bool ShouldDelayOnTabletPhysicalStateChanged() override; private: friend AccelerometerProviderMojoTest; struct AccelerometerData { AccelerometerData(); ~AccelerometerData(); bool ignored = false; // Temporarily stores the accelerometer remote, waiting for it's scale and // location information. It'll be passed to |samples_observer| as an // argument after all information is collected. mojo::Remote remote; absl::optional location; absl::optional scale; std::unique_ptr samples_observer; }; ~AccelerometerProviderMojo() override; // 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(); void SetECLidAngleDriverSupported(); // Update |initialization_state_| upon new devices' arrival. // MojoState (|initialization_state_|) transition: // INITIALIZING -> ANGL // LID -> ANGL_LID // BASE -> ANGL // ANGL Shouldn't happen // ANGL_LID Shouldn't happen void UpdateStateWithECLidAngleDriverSupported(); // MojoState (|initialization_state_|) transition: // INITIALIZING -> LID // LID Shouldn't happen // BASE -> LID_BASE // ANGL -> ANGL_LID // ANGL_LID Shouldn't happen void UpdateStateWithLidAccelerometer(); // MojoState (|initialization_state_|) transition: // INITIALIZING -> BASE // LID -> LID_BASE // BASE Shouldn't happen // ANGL -> ANGL // ANGL_LID -> ANGL_LID void UpdateStateWithBaseAccelerometer(); void SetNewDevicesObserver(); void OnNewDevicesObserverDisconnect(); // Timeout of new devices. If lid-angle driver is still not present, assumes // it not supported and notifies observers. // This class still listens to new devices after the timeout to catch the // really late-present devices and avoid those issues, as the current use // cases/observers allow that. void OnNewDevicesTimeout(); // Callback of GetDeviceIds(ANGL), containing the lid-angle device's id if it // exists. void GetLidAngleIdsCallback(const std::vector& lid_angle_ids); // Callback of GetDeviceIds(ACCEL), containing all iio_device_ids of // accelerometers. void GetAccelerometerIdsCallback( const std::vector& accelerometer_ids); // Creates the Mojo channel for the accelerometer, and requests the // accelerometer's required attributes before creating the // AccelerometerSamplesObserver of it. void RegisterAccelerometerWithId(int32_t id); void OnAccelerometerRemoteDisconnect(int32_t id, uint32_t custom_reason_code, const std::string& description); void GetAttributesCallback( int32_t id, const std::vector>& values); // Ignores the accelerometer as the attributes are not expected. void IgnoreAccelerometer(int32_t id); // Creates the AccelerometerSamplesObserver for the accelerometer with |id|. void CreateAccelerometerSamplesObserver(int32_t id); // Controls accelerometer reading. void EnableAccelerometerReading(); void DisableAccelerometerReading(); // Called by |AccelerometerData::samples_observer| stored in the // |accelerometers_| map, containing a sample of the accelerometer. void OnSampleUpdatedCallback(int iio_device_id, std::vector sample); // The state that contains the information of devices we have now. Used for // late-present devices. MojoState initialization_state_ = MojoState::INITIALIZING; // The Mojo channel connecting to Sensor Hal Dispatcher. mojo::Receiver sensor_hal_client_{ this}; // The Mojo channel to query and request for devices. mojo::Remote sensor_service_remote_; // The Mojo channel to get notified when new devices are added to IIO Service. mojo::Receiver new_devices_observer_{this}; // First is the accelerometer's iio device id, second is it's data, mojo // remote and samples observer. std::map accelerometers_; // First is the location index, second is the id of the accelerometer being // used in this reader. std::map location_to_accelerometer_id_; // The flag to delay |OnTabletPhysicalStateChanged| until // |ec_lid_angle_driver_status_| is set. bool pending_on_tablet_physical_state_changed_ = false; // True if periodical accelerometer read is on. bool accelerometer_read_on_ = false; // The last seen accelerometer data. AccelerometerUpdate update_; SEQUENCE_CHECKER(sequence_checker_); }; } // namespace ash #endif // ASH_ACCELEROMETER_ACCELEROMETER_PROVIDER_MOJO_H_