1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
// 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.
#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_
|