| // Copyright 2014 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_READER_H_ |
| #define ASH_ACCELEROMETER_ACCELEROMETER_READER_H_ |
| |
| #include "ash/accelerometer/accelerometer_types.h" |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/tablet_mode_observer.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/no_destructor.h" |
| #include "base/observer_list.h" |
| |
| namespace base { |
| class SequencedTaskRunner; |
| } // namespace base |
| |
| namespace ash { |
| |
| enum class ECLidAngleDriverStatus { UNKNOWN, SUPPORTED, NOT_SUPPORTED }; |
| |
| class AccelerometerProviderInterface; |
| |
| // AccelerometerReader should only be used on the UI thread. |
| // It notifies observers if EC Lid Angle Driver is supported, and provides |
| // accelerometers' (lid and base) samples. |
| // The current usages of accelerometers' samples are for calculating the angle |
| // between the lid and the base, which can be substituted by EC Lid Angle |
| // Driver, if it exists, and the auto rotation, which only needs |
| // lid-accelerometer's data. |
| // Therefore, if EC Lid Angle Driver is present, base-accelerometer's samples |
| // may be ignored and not sent to the observers. |
| class ASH_EXPORT AccelerometerReader { |
| public: |
| // An interface to receive data from the AccelerometerReader. |
| class Observer { |
| public: |
| // Normally called only once, when |
| // |AcceleromterProviderInterface::ec_lid_angle_driver_status_| is set to |
| // either SUPPORTED or NOT_SUPPORTED, unless the lid angle driver is |
| // late-present after timed out, which will be called twice with |
| // |is_supported| being false and true respectively. |
| // It's guaranteed to be called before |OnAccelerometerUpdated|. |
| virtual void OnECLidAngleDriverStatusChanged(bool is_supported) = 0; |
| virtual void OnAccelerometerUpdated(const AccelerometerUpdate& update) = 0; |
| |
| protected: |
| virtual ~Observer() {} |
| }; |
| |
| static AccelerometerReader* GetInstance(); |
| |
| void Initialize(); |
| |
| // Add/Remove observers. |
| void AddObserver(Observer* observer); |
| void RemoveObserver(Observer* observer); |
| |
| // Accelerometer file reader starts/stops listening to tablet mode controller. |
| void StartListenToTabletModeController(); |
| void StopListenToTabletModeController(); |
| |
| // Controls the availability of emitting acccelerometer reader events to |
| // its observers. This shouldn't be called normally, but Tast tests should |
| // be able to control the accelerometer feature. |
| void SetEnabled(bool enabled); |
| |
| void SetECLidAngleDriverStatusForTesting( |
| ECLidAngleDriverStatus ec_lid_angle_driver_status); |
| |
| protected: |
| AccelerometerReader(); |
| AccelerometerReader(const AccelerometerReader&) = delete; |
| AccelerometerReader& operator=(const AccelerometerReader&) = delete; |
| virtual ~AccelerometerReader(); |
| |
| private: |
| friend class base::NoDestructor<AccelerometerReader>; |
| |
| // Worker that will run on the base::SequencedTaskRunner provided to |
| // Initialize. It will determine accelerometer configuration, read the data, |
| // and notify observers. |
| scoped_refptr<AccelerometerProviderInterface> accelerometer_provider_; |
| }; |
| |
| class ASH_EXPORT AccelerometerProviderInterface |
| : public base::RefCountedThreadSafe<AccelerometerProviderInterface>, |
| public TabletModeObserver { |
| public: |
| // Prepare and start async initialization. |
| virtual void PrepareAndInitialize() = 0; |
| // With ChromeOS EC lid angle driver present, it's triggered when the device |
| // is physically used as a tablet (even thought its UI might be in clamshell |
| // mode), cancelled otherwise. |
| virtual void TriggerRead() = 0; |
| virtual void CancelRead() = 0; |
| |
| // TabletModeObserver: |
| void OnTabletPhysicalStateChanged() override; |
| |
| // Add/Remove observers. |
| void AddObserver(AccelerometerReader::Observer* observer); |
| void RemoveObserver(AccelerometerReader::Observer* observer); |
| |
| // Start/Stop listening to tablet mode controller. |
| void StartListenToTabletModeController(); |
| void StopListenToTabletModeController(); |
| |
| // Set emitting events (samples) to observers or not. |
| void SetEmitEvents(bool emit_events); |
| |
| void SetECLidAngleDriverStatusForTesting(ECLidAngleDriverStatus status); |
| |
| protected: |
| AccelerometerProviderInterface(); |
| ~AccelerometerProviderInterface() override; |
| |
| // Used in |OnTabletPhysicalStateChanged()|. As there might be |
| // initialization steps, each implementation can override this function to |
| // determine if this class is ready to process the state changed. |
| // If returns true, |OnTabletPhysicalStateChanged()| will be skipped, and it's |
| // the implementation's responsibility to call it again when the class is |
| // ready. If returns false, |OnTabletPhysicalStateChanged()| will be processed |
| // as usual. |
| // Default to return false. |
| virtual bool ShouldDelayOnTabletPhysicalStateChanged(); |
| |
| void SetECLidAngleDriverStatus(ECLidAngleDriverStatus status); |
| ECLidAngleDriverStatus GetECLidAngleDriverStatus() const; |
| |
| void NotifyAccelerometerUpdated(const AccelerometerUpdate& update); |
| |
| // Set in the constructor. |
| scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; |
| |
| private: |
| // State of ChromeOS EC lid angle driver, if SUPPORTED, it means EC can handle |
| // lid angle calculation. |
| ECLidAngleDriverStatus ec_lid_angle_driver_status_ = |
| ECLidAngleDriverStatus::UNKNOWN; |
| |
| bool emit_events_ = true; |
| |
| // The observers to notify of accelerometer updates. |
| // Bound to the UI thread. |
| base::ObserverList<AccelerometerReader::Observer>::Unchecked observers_; |
| |
| friend class base::RefCountedThreadSafe<AccelerometerProviderInterface>; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_ACCELEROMETER_ACCELEROMETER_READER_H_ |