1 /*
2  * Copyright (C) 2020 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 #define LOG_TAG "pixelstats-orientation"
18 
19 #include <android/sensor.h>
20 #include <log/log.h>
21 #include <pixelstats/OrientationCollector.h>
22 
23 namespace android {
24 namespace hardware {
25 namespace google {
26 namespace pixel {
27 
28 #define GET_EVENT_TIMEOUT_MILLIS 200
29 #define SENSOR_TYPE_DEVICE_ORIENTATION 27
30 #define ORIENTATION_UNKNOWN -1
31 
createOrientationCollector()32 sp<OrientationCollector> OrientationCollector::createOrientationCollector() {
33     sp<OrientationCollector> orientationCollector;
34     orientationCollector = new OrientationCollector();
35     if (orientationCollector != nullptr && orientationCollector->init() < 0) {
36         orientationCollector->disableOrientationSensor();
37         return nullptr;
38     }
39     return orientationCollector;
40 }
41 
42 /* pollOrientation
43  * orientation: [out] orientation value from sensor Hal.
44  * Return: OK, or error code from sensor Hal
45  */
pollOrientation(int * orientation)46 int32_t OrientationCollector::pollOrientation(int *orientation) {
47     int err = OK;
48     int eventCount = 0;
49     ASensorEvent sensorEvent;
50 
51     *orientation = ORIENTATION_UNKNOWN;
52     /* Get sensor events. */
53     /* Get sensor sample events. */
54     err = getEvents(&sensorEvent, 1, &eventCount);
55     if (eventCount > 0) {
56         ALOGV("%s: ##event data: %f,%f,%f", __func__, sensorEvent.data[0], sensorEvent.data[1],
57               sensorEvent.data[2]);
58         *orientation = sensorEvent.data[0];
59     }
60     return err;
61 }
62 
63 /*
64  * Collects sensor samples and returns them in the sensor sample event list
65  * specified by event_list. Limits the number of returned sample events to the
66  * value specified by event_list_size. Returns the number of returned sample
67  * events in p_event_count.
68  *
69  * event_list               List of collected sample events.
70  * event_list_size          Size of sample event list.
71  * event_count              Returned count of the number of collected sample
72  *                          events.
73  */
getEvents(ASensorEvent * event_list,size_t event_list_size,int * event_count)74 int OrientationCollector::getEvents(ASensorEvent *event_list, size_t event_list_size,
75                                     int *event_count) {
76     int rv;
77     int err = OK;
78 
79     /* Wait for a sensor event to be available */
80     /* The timeout is used to prevent blocking for long time, when sensor pool is
81      * empty, for example the device is put on a horizontal wireless charger.
82      */
83     rv = ALooper_pollOnce(GET_EVENT_TIMEOUT_MILLIS, nullptr, nullptr, nullptr);
84     if (rv == ALOOPER_POLL_ERROR) {
85         ALOGI("Sensor event looper returned a poll error.\n");
86         err = UNKNOWN_ERROR;
87         goto out;
88     }
89 
90     /* Get sensor events. */
91     *event_count = ASensorEventQueue_getEvents(mQueue, event_list, event_list_size);
92 
93 out:
94     return err;
95 }
96 
init()97 int32_t OrientationCollector::init() {
98     int err = OK;
99     ALooper *looper = nullptr;
100 
101     // Get orientation sensor events from the NDK
102     mSensorManager = ASensorManager_getInstanceForPackage(nullptr);
103     if (mSensorManager == nullptr) {
104         ALOGE("%s: Unable to get sensorManager.\n", __func__);
105         return UNKNOWN_ERROR;
106     }
107     looper = ALooper_forThread();
108     if (looper == nullptr) {
109         looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
110     }
111     if (looper == nullptr) {
112         ALOGE("%s: Failed to prepare an event looper.\n", __FUNCTION__);
113         return UNKNOWN_ERROR;
114     }
115     mQueue = ASensorManager_createEventQueue(mSensorManager, looper, 0, nullptr, nullptr);
116     mOrientationSensor =
117             ASensorManager_getDefaultSensor(mSensorManager, SENSOR_TYPE_DEVICE_ORIENTATION);
118     if (mOrientationSensor == nullptr) {
119         ALOGE("%s: Unable to get orientation sensor.\n", __func__);
120         return UNKNOWN_ERROR;
121     }
122     err = ASensorEventQueue_registerSensor(mQueue, mOrientationSensor,
123                                            ASensor_getMinDelay(mOrientationSensor), 0);
124     if (err < 0) {
125         ALOGE("%s: Unable to register for orientation sensor events\n", __func__);
126     }
127     return err;
128 }
129 
disableOrientationSensor()130 void OrientationCollector::disableOrientationSensor() {
131     if (mSensorManager != nullptr && mQueue != nullptr) {
132         if (mOrientationSensor != nullptr) {
133             ASensorEventQueue_disableSensor(mQueue, mOrientationSensor);
134         }
135         ASensorManager_destroyEventQueue(mSensorManager, mQueue);
136     }
137 }
138 
139 }  // namespace pixel
140 }  // namespace google
141 }  // namespace hardware
142 }  // namespace android
143