1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cmath>
18 #include <thread>
19 
20 #include <android-base/chrono_utils.h>
21 #include <android-base/logging.h>
22 #include <android/binder_manager.h>
23 #include <android-base/parsedouble.h>
24 #include <android-base/parseint.h>
25 #include <utils/SystemClock.h>
26 #include <aidl/android/hardware/sensors/BnSensors.h>
27 
28 using aidl::android::hardware::sensors::Event;
29 using aidl::android::hardware::sensors::ISensors;
30 using aidl::android::hardware::sensors::SensorInfo;
31 using aidl::android::hardware::sensors::SensorStatus;
32 using aidl::android::hardware::sensors::SensorType;
33 
startSensorInjection()34 std::shared_ptr<ISensors> startSensorInjection() {
35   auto sensors = ISensors::fromBinder(ndk::SpAIBinder(
36       AServiceManager_getService("android.hardware.sensors.ISensors/default")));
37   CHECK(sensors != nullptr) << "Unable to get ISensors.";
38 
39   // Place the ISensors HAL into DATA_INJECTION mode so that we can
40   // inject events.
41   auto result =
42       sensors->setOperationMode(ISensors::OperationMode::DATA_INJECTION);
43   CHECK(result.isOk())
44       << "Unable to set ISensors operation mode to DATA_INJECTION: "
45       << result.getDescription();
46 
47   return sensors;
48 }
49 
getSensorHandle(SensorType type,const std::shared_ptr<ISensors> sensors)50 int getSensorHandle(SensorType type, const std::shared_ptr<ISensors> sensors) {
51   // Find the first available sensor of the given type.
52   int handle = -1;
53   std::vector<SensorInfo> sensors_list;
54   auto result = sensors->getSensorsList(&sensors_list);
55   CHECK(result.isOk()) << "Unable to get ISensors sensors list: "
56                         << result.getDescription();
57   for (const SensorInfo& sensor : sensors_list) {
58     if (sensor.type == type) {
59       handle = sensor.sensorHandle;
60       break;
61     }
62   }
63   CHECK(handle != -1) << "Unable to find sensor.";
64   return handle;
65 }
66 
endSensorInjection(const std::shared_ptr<ISensors> sensors)67 void endSensorInjection(const std::shared_ptr<ISensors> sensors) {
68   // Return the ISensors HAL back to NORMAL mode.
69   auto result = sensors->setOperationMode(ISensors::OperationMode::NORMAL);
70   CHECK(result.isOk()) << "Unable to set sensors operation mode to NORMAL: "
71                        << result.getDescription();
72 }
73 
74 // Inject ACCELEROMETER events to corresponding to a given physical
75 // device position.
InjectOrientation(int rotationDeg)76 void InjectOrientation(int rotationDeg) {
77   auto rad = M_PI * rotationDeg / 180.0;
78   auto sensors = startSensorInjection();
79   int handle = getSensorHandle(SensorType::ACCELEROMETER, sensors);
80 
81   // Create a base ISensors accelerometer event.
82   Event event;
83   event.sensorHandle = handle;
84   event.sensorType = SensorType::ACCELEROMETER;
85   Event::EventPayload::Vec3 vec3;
86   // (x^2 + y^2 + z^2)^1/2 = ~9.8 = 1G
87   vec3.x = 9.2 * std::sin(rad);
88   vec3.y = 9.2 * std::cos(rad);
89   // z is fixed at 3.5, meaning the device is positioned vertically with a
90   // slight inclination backwards.
91   vec3.z = 3.5;
92   vec3.status = SensorStatus::ACCURACY_HIGH;
93   event.payload.set<Event::EventPayload::Tag::vec3>(vec3);
94 
95   // Repeatedly inject accelerometer events. The WindowManager orientation
96   // listener responds to sustained accelerometer data, not just a single event.
97   android::base::Timer timer;
98   while (timer.duration() < 1s) {
99     event.timestamp = android::elapsedRealtimeNano();
100     auto result = sensors->injectSensorData(event);
101     CHECK(result.isOk()) << "Unable to inject ISensors accelerometer event: "
102                          << result.getDescription();
103     std::this_thread::sleep_for(10ms);
104   }
105 
106   endSensorInjection(sensors);
107 }
108 
109 // Inject accelerometer event based on rotation in device position.
InjectAccelerometer(double x,double y,double z)110 void InjectAccelerometer(double x, double y, double z) {
111   auto sensors = startSensorInjection();
112   int handle = getSensorHandle(SensorType::ACCELEROMETER, sensors);
113   Event event;
114   event.sensorHandle = handle;
115   event.sensorType = SensorType::ACCELEROMETER;
116 
117   Event::EventPayload::Vec3 vec3;
118   vec3.x = x;
119   vec3.y = y;
120   vec3.z = z;
121   vec3.status = SensorStatus::ACCURACY_HIGH;
122   event.payload.set<Event::EventPayload::Tag::vec3>(vec3);
123   event.timestamp = android::elapsedRealtimeNano();
124   auto result = sensors->injectSensorData(event);
125   CHECK(result.isOk()) << "Unable to inject ISensors accelerometer event: "
126                        << result.getDescription();
127 }
128 
129 // Inject Magnetometer event based on rotation in device position.
InjectMagnetometer(double x,double y,double z)130 void InjectMagnetometer(double x, double y, double z) {
131   auto sensors = startSensorInjection();
132   int handle = getSensorHandle(SensorType::MAGNETIC_FIELD, sensors);
133   Event event;
134   event.sensorHandle = handle;
135   event.sensorType = SensorType::MAGNETIC_FIELD;
136 
137   Event::EventPayload::Vec3 vec3;
138   vec3.x = x;
139   vec3.y = y;
140   vec3.z = z;
141   vec3.status = SensorStatus::ACCURACY_HIGH;
142   event.payload.set<Event::EventPayload::Tag::vec3>(vec3);
143   event.timestamp = android::elapsedRealtimeNano();
144   auto result = sensors->injectSensorData(event);
145   CHECK(result.isOk()) << "Unable to inject ISensors magnetometer event: "
146                        << result.getDescription();
147 }
148 
149 // Inject Gyroscope event based on rotation in device position.
InjectGyroscope(double x,double y,double z)150 void InjectGyroscope(double x, double y, double z){
151   auto sensors = startSensorInjection();
152   int handle = getSensorHandle(SensorType::GYROSCOPE, sensors);
153   Event event;
154   event.sensorHandle = handle;
155   event.sensorType = SensorType::GYROSCOPE;
156 
157   Event::EventPayload::Vec3 vec3;
158   vec3.x = x;
159   vec3.y = y;
160   vec3.z = z;
161   vec3.status = SensorStatus::ACCURACY_HIGH;
162   event.payload.set<Event::EventPayload::Tag::vec3>(vec3);
163   event.timestamp = android::elapsedRealtimeNano();
164   auto result = sensors->injectSensorData(event);
165   CHECK(result.isOk()) << "Unable to inject ISensors gyroscope event: "
166                        << result.getDescription();
167 }
168 
169 // Inject a single HINGE_ANGLE event at the given angle.
InjectHingeAngle(int angle)170 void InjectHingeAngle(int angle) {
171   auto sensors = startSensorInjection();
172   int handle = getSensorHandle(SensorType::HINGE_ANGLE, sensors);
173 
174   // Create a base ISensors hinge_angle event.
175   Event event;
176   event.sensorHandle = handle;
177   event.sensorType = SensorType::HINGE_ANGLE;
178   event.payload.set<Event::EventPayload::Tag::scalar>((float)angle);
179   event.timestamp = android::elapsedRealtimeNano();
180 
181   auto result = sensors->injectSensorData(event);
182   CHECK(result.isOk()) << "Unable to inject HINGE_ANGLE data"
183                        << result.getDescription();
184 
185   endSensorInjection(sensors);
186 }
187 
main(int argc,char ** argv)188 int main(int argc, char** argv) {
189   ::android::base::InitLogging(
190       argv, android::base::LogdLogger(android::base::SYSTEM));
191   CHECK(argc == 3 || argc == 11)
192       << "Expected command line args 'rotate <angle>', 'hinge_angle <value>', or 'motion " <<
193           "<acc_x> <acc_y> <acc_z> <mgn_x> <mgn_y> <mgn_z> <gyro_x> <gyro_y> <gyro_z>'";
194   if (!strcmp(argv[1], "rotate")) {
195     int rotationDeg;
196     CHECK(android::base::ParseInt(argv[2], &rotationDeg))
197         << "Rotation angle must be an integer";
198     InjectOrientation(rotationDeg);
199   } else if (!strcmp(argv[1], "hinge_angle")) {
200     int angle;
201     CHECK(android::base::ParseInt(argv[2], &angle))
202         << "Hinge angle must be an integer";
203     CHECK(angle >= 0 && angle <= 360) << "Bad hinge_angle value: " << argv[2];
204     InjectHingeAngle(angle);
205   } else if (!strcmp(argv[1], "motion")) {
206     double acc_x, acc_y, acc_z, mgn_x, mgn_y, mgn_z, gyro_x, gyro_y, gyro_z;
207     CHECK(android::base::ParseDouble(argv[2], &acc_x)) << "Accelerometer x value must be a double";
208     CHECK(android::base::ParseDouble(argv[3], &acc_y)) << "Accelerometer x value must be a double";
209     CHECK(android::base::ParseDouble(argv[4], &acc_z)) << "Accelerometer x value must be a double";
210     CHECK(android::base::ParseDouble(argv[5], &mgn_x)) << "Magnetometer x value must be a double";
211     CHECK(android::base::ParseDouble(argv[6], &mgn_y)) << "Magnetometer y value must be a double";
212     CHECK(android::base::ParseDouble(argv[7], &mgn_z)) << "Magnetometer z value must be a double";
213     CHECK(android::base::ParseDouble(argv[8], &gyro_x)) << "Gyroscope x value must be a double";
214     CHECK(android::base::ParseDouble(argv[9], &gyro_y)) << "Gyroscope y value must be a double";
215     CHECK(android::base::ParseDouble(argv[10], &gyro_z)) << "Gyroscope z value must be a double";
216     InjectAccelerometer(acc_x, acc_y, acc_z);
217     InjectMagnetometer(mgn_x, mgn_y, mgn_z);
218     InjectGyroscope(gyro_x, gyro_y, gyro_z);
219   } else {
220     LOG(FATAL) << "Unknown arg: " << argv[1];
221   }
222 }
223