1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_
6 #define ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_
7 
8 #include <string>
9 #include <vector>
10 
11 #include "ash/accelerometer/accelerometer_reader.h"
12 #include "ash/public/cpp/tablet_mode_observer.h"
13 #include "base/files/file_util.h"
14 #include "base/observer_list_threadsafe.h"
15 
16 namespace ash {
17 
18 enum class State { INITIALIZING, SUCCESS, FAILED };
19 
20 // Work that runs on a base::TaskRunner. It determines the accelerometer
21 // configuration, and reads the data. Upon a successful read it will notify
22 // all observers.
23 class AccelerometerFileReader : public AccelerometerProviderInterface,
24                                 public TabletModeObserver {
25  public:
26   AccelerometerFileReader();
27   AccelerometerFileReader(const AccelerometerFileReader&) = delete;
28   AccelerometerFileReader& operator=(const AccelerometerFileReader&) = delete;
29 
30   // AccelerometerProviderInterface:
31   void PrepareAndInitialize(
32       scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) override;
33   void AddObserver(AccelerometerReader::Observer* observer) override;
34   void RemoveObserver(AccelerometerReader::Observer* observer) override;
35   void StartListenToTabletModeController() override;
36   void StopListenToTabletModeController() override;
37   void SetEmitEvents(bool emit_events) override;
38 
39   // Attempts to read the accelerometer data. Upon success, converts the raw
40   // reading to an AccelerometerUpdate and notifies observers. Triggers another
41   // read at the current sampling rate.
42   void Read();
43 
44   // Controls accelerometer reading.
45   void EnableAccelerometerReading();
46   void DisableAccelerometerReading();
47 
48   // Tracks if accelerometer initialization is completed.
49   void CheckInitStatus();
50 
51   // With ChromeOS EC lid angle driver present, accelerometer read is cancelled
52   // in clamshell mode, and triggered when entering tablet mode.
53   void TriggerRead();
54   void CancelRead();
55 
56   // TabletModeObserver:
57   void OnTabletPhysicalStateChanged() override;
58 
59  private:
60   // Represents necessary information in order to read an accelerometer device.
61   struct ReadingData {
62     ReadingData();
63     ReadingData(const ReadingData&);
64     ~ReadingData();
65 
66     // The full path to the accelerometer device to read.
67     base::FilePath path;
68 
69     // The accelerometer sources which can be read from |path|.
70     std::vector<AccelerometerSource> sources;
71   };
72 
73   // Configuration structure for accelerometer device.
74   struct ConfigurationData {
75     ConfigurationData();
76     ~ConfigurationData();
77 
78     // Number of accelerometers on device.
79     size_t count;
80 
81     // sysfs entry to trigger readings.
82     base::FilePath trigger_now;
83 
84     // Which accelerometers are present on device.
85     bool has[ACCELEROMETER_SOURCE_COUNT];
86 
87     // Scale of accelerometers (i.e. raw value * scale = m/s^2).
88     float scale[ACCELEROMETER_SOURCE_COUNT][3];
89 
90     // Index of each accelerometer axis in data stream.
91     int index[ACCELEROMETER_SOURCE_COUNT][3];
92 
93     // The information for each accelerometer device to be read. In kernel 3.18
94     // there is one per ACCELEROMETER_SOURCE_COUNT. On 3.14 there is only one.
95     std::vector<ReadingData> reading_data;
96   };
97 
98   ~AccelerometerFileReader() override;
99 
100   // Detects the accelerometer configuration.
101   // If an accelerometer is available, it triggers reads.
102   // This function MAY be called more than once.
103   // This function contains the actual initialization code to be run by the
104   // Initialize function. It is needed because on some devices the sensor hub
105   // isn't available at the time the call to Initialize is made. If the sensor
106   // is found to be missing we'll make a call to TryScheduleInitializeInternal.
107   void InitializeInternal();
108 
109   // Attempt to reschedule a run of InitializeInternal(). The function will be
110   // scheduled to run again if Now() < initialization_timeout_.
111   void TryScheduleInitializeInternal();
112 
113   // When accelerometers are presented as separate iio_devices this will perform
114   // the initialize for one of the devices, at the given |iio_path| and the
115   // symbolic link |name|. |location| is defined by AccelerometerSource.
116   bool InitializeAccelerometer(const base::FilePath& iio_path,
117                                const base::FilePath& name,
118                                const std::string& location);
119 
120   // TODO(jonross): Separate the initialization into separate files. Add a gyp
121   // rule to have them built for the appropriate kernels. (crbug.com/525658)
122   // When accelerometers are presented as a single iio_device this will perform
123   // the initialization for both of them.
124   bool InitializeLegacyAccelerometers(const base::FilePath& iio_path,
125                                       const base::FilePath& name);
126 
127   // Attempts to read the accelerometer data. Upon a success, converts the raw
128   // reading to an AccelerometerUpdate and notifies observers.
129   void ReadFileAndNotify();
130 
131   void SetEmitEventsInternal(bool emit_events);
132 
133   // The current initialization state of reader.
134   State initialization_state_ = State::INITIALIZING;
135 
136   // True if periodical accelerometer read is on.
137   bool accelerometer_read_on_ = false;
138 
139   bool emit_events_ = true;
140 
141   // The time at which initialization re-tries should stop.
142   base::TimeTicks initialization_timeout_;
143 
144   // The accelerometer configuration.
145   ConfigurationData configuration_;
146 
147   // The observers to notify of accelerometer updates.
148   scoped_refptr<base::ObserverListThreadSafe<AccelerometerReader::Observer>>
149       observers_;
150 
151   // The task runner to use for blocking tasks.
152   scoped_refptr<base::SequencedTaskRunner> task_runner_;
153 
154   // The last seen accelerometer data.
155   scoped_refptr<AccelerometerUpdate> update_;
156 };
157 
158 }  // namespace ash
159 
160 #endif  // ASH_ACCELEROMETER_ACCELEROMETER_FILE_READER_H_
161