• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/chrono_utils.h>
18 #include <android-base/logging.h>
19 #include <android/binder_manager.h>
20 #include <utils/SystemClock.h>
21 
22 #include <thread>
23 
24 #include <aidl/android/hardware/sensors/BnSensors.h>
25 
26 using aidl::android::hardware::sensors::Event;
27 using aidl::android::hardware::sensors::ISensors;
28 using aidl::android::hardware::sensors::SensorInfo;
29 using aidl::android::hardware::sensors::SensorStatus;
30 using aidl::android::hardware::sensors::SensorType;
31 
startSensorInjection()32 std::shared_ptr<ISensors> startSensorInjection() {
33   auto sensors = ISensors::fromBinder(ndk::SpAIBinder(
34       AServiceManager_getService("android.hardware.sensors.ISensors/default")));
35   if (sensors == nullptr) {
36     LOG(FATAL) << "Unable to get ISensors.";
37   }
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   if (!result.isOk()) {
44     LOG(FATAL) << "Unable to set ISensors operation mode to DATA_INJECTION: "
45                << result.getDescription();
46   }
47 
48   return sensors;
49 }
50 
getSensorHandle(SensorType type,const std::shared_ptr<ISensors> sensors)51 int getSensorHandle(SensorType type, const std::shared_ptr<ISensors> sensors) {
52   // Find the first available sensor of the given type.
53   int handle = -1;
54   std::vector<SensorInfo> sensors_list;
55   auto result = sensors->getSensorsList(&sensors_list);
56   if (!result.isOk()) {
57     LOG(FATAL) << "Unable to get ISensors sensors list: "
58                << result.getDescription();
59   }
60   for (const SensorInfo& sensor : sensors_list) {
61     if (sensor.type == type) {
62       handle = sensor.sensorHandle;
63       break;
64     }
65   }
66   if (handle == -1) {
67     LOG(FATAL) << "Unable to find sensor.";
68   }
69   return handle;
70 }
71 
endSensorInjection(const std::shared_ptr<ISensors> sensors)72 void endSensorInjection(const std::shared_ptr<ISensors> sensors) {
73   // Return the ISensors HAL back to NORMAL mode.
74   auto result = sensors->setOperationMode(ISensors::OperationMode::NORMAL);
75   if (!result.isOk()) {
76     LOG(FATAL) << "Unable to set sensors operation mode to NORMAL: "
77                << result.getDescription();
78   }
79 }
80 
81 // Inject ACCELEROMETER events to corresponding to a given physical
82 // device orientation: portrait or landscape.
InjectOrientation(bool portrait)83 void InjectOrientation(bool portrait) {
84   auto sensors = startSensorInjection();
85   int handle = getSensorHandle(SensorType::ACCELEROMETER, sensors);
86 
87   // Create a base ISensors accelerometer event.
88   Event event;
89   event.sensorHandle = handle;
90   event.sensorType = SensorType::ACCELEROMETER;
91   Event::EventPayload::Vec3 vec3;
92   if (portrait) {
93     vec3.x = 0;
94     vec3.y = 9.2;
95   } else {
96     vec3.x = 9.2;
97     vec3.y = 0;
98   }
99   vec3.z = 3.5;
100   vec3.status = SensorStatus::ACCURACY_HIGH;
101   event.payload.set<Event::EventPayload::Tag::vec3>(vec3);
102 
103   // Repeatedly inject accelerometer events. The WindowManager orientation
104   // listener responds to sustained accelerometer data, not just a single event.
105   android::base::Timer timer;
106   while (timer.duration() < 1s) {
107     event.timestamp = android::elapsedRealtimeNano();
108     auto result = sensors->injectSensorData(event);
109     if (!result.isOk()) {
110       LOG(FATAL) << "Unable to inject ISensors accelerometer event: "
111                  << result.getDescription();
112     }
113     std::this_thread::sleep_for(10ms);
114   }
115 
116   endSensorInjection(sensors);
117 }
118 
119 // Inject a single HINGE_ANGLE event at the given angle.
InjectHingeAngle(int angle)120 void InjectHingeAngle(int angle) {
121   auto sensors = startSensorInjection();
122   int handle = getSensorHandle(SensorType::HINGE_ANGLE, sensors);
123 
124   // Create a base ISensors hinge_angle event.
125   Event event;
126   event.sensorHandle = handle;
127   event.sensorType = SensorType::HINGE_ANGLE;
128   event.payload.set<Event::EventPayload::Tag::scalar>((float)angle);
129   event.timestamp = android::elapsedRealtimeNano();
130 
131   auto result = sensors->injectSensorData(event);
132   if (!result.isOk()) {
133     LOG(FATAL) << "Unable to inject HINGE_ANGLE data"
134                << result.getDescription();
135   }
136 
137   endSensorInjection(sensors);
138 }
139 
main(int argc,char ** argv)140 int main(int argc, char** argv) {
141   if (argc == 2) {
142     LOG(FATAL) << "Expected command line args 'rotate <portrait|landscape>' or "
143                   "'hinge_angle <value>'";
144   }
145 
146   if (!strcmp(argv[1], "rotate")) {
147     bool portrait = true;
148     if (!strcmp(argv[2], "portrait")) {
149       portrait = true;
150     } else if (!strcmp(argv[2], "landscape")) {
151       portrait = false;
152     } else {
153       LOG(FATAL) << "Expected command line arg 'portrait' or 'landscape'";
154     }
155     InjectOrientation(portrait);
156   } else if (!strcmp(argv[1], "hinge_angle")) {
157     int angle = std::stoi(argv[2]);
158     if (angle < 0 || angle > 360) {
159       LOG(FATAL) << "Bad hinge_angle value: " << argv[2];
160     }
161     InjectHingeAngle(angle);
162   } else {
163     LOG(FATAL) << "Unknown arg: " << argv[1];
164   }
165 }
166