1 /*
2  * Copyright (C) 2016 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 "chre/core/event_loop_manager.h"
18 #include "chre/core/sensor_request.h"
19 #include "chre/util/time.h"
20 #include "chre/util/macros.h"
21 #include "chre_api/chre/sensor.h"
22 
23 using chre::EventLoopManager;
24 using chre::EventLoopManagerSingleton;
25 using chre::Nanoseconds;
26 using chre::SensorMode;
27 using chre::SensorRequest;
28 using chre::SensorType;
29 
30 using chre::getSensorModeFromEnum;
31 using chre::getSensorTypeFromUnsignedInt;
32 
33 #if defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
34 namespace {
35 constexpr uint8_t kBigImageAccelSensorType =
36     (CHRE_SENSOR_TYPE_VENDOR_START + 3);
37 constexpr uint8_t kBigImageUncalAccelSensorType =
38     (CHRE_SENSOR_TYPE_VENDOR_START + 6);
39 constexpr uint8_t kBigImageUncalGyroSensorType =
40     (CHRE_SENSOR_TYPE_VENDOR_START + 7);
41 constexpr uint8_t kBigImageUncalMagSensorType =
42     (CHRE_SENSOR_TYPE_VENDOR_START + 8);
43 
isBigImageSensorType(uint8_t sensorType)44 bool isBigImageSensorType(uint8_t sensorType) {
45   return (sensorType == kBigImageAccelSensorType
46           || sensorType == kBigImageUncalAccelSensorType
47           || sensorType == kBigImageUncalGyroSensorType
48           || sensorType == kBigImageUncalMagSensorType);
49 }
50 
51 /**
52  * Rewrites the provided sensorType to its big-image counterpart if it exists.
53  */
rewriteToBigImageSensorType(uint8_t * sensorType)54 void rewriteToBigImageSensorType(uint8_t *sensorType) {
55   CHRE_ASSERT(sensorType);
56 
57   if (*sensorType == CHRE_SENSOR_TYPE_ACCELEROMETER) {
58     *sensorType = kBigImageAccelSensorType;
59   } else if (*sensorType == CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER) {
60     *sensorType = kBigImageUncalAccelSensorType;
61   } else if (*sensorType == CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE) {
62     *sensorType = kBigImageUncalGyroSensorType;
63   } else if (*sensorType == CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD) {
64     *sensorType = kBigImageUncalMagSensorType;
65   }
66 }
67 
68 /**
69  * Rewrites a big-image sensorType to its regular CHRE counterpart.
70  */
rewriteToChreSensorType(uint8_t * sensorType)71 void rewriteToChreSensorType(uint8_t *sensorType) {
72   CHRE_ASSERT(sensorType);
73 
74   if (*sensorType == kBigImageAccelSensorType) {
75     *sensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
76   } else if (*sensorType == kBigImageUncalAccelSensorType) {
77     *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER;
78   } else if (*sensorType == kBigImageUncalGyroSensorType) {
79     *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE;
80   } else if (*sensorType == kBigImageUncalMagSensorType) {
81     *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD;
82   }
83 }
84 } //  anonymous namespace
85 #endif  // defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
86 
chreSensorFindDefault(uint8_t sensorType,uint32_t * handle)87 DLL_EXPORT bool chreSensorFindDefault(uint8_t sensorType, uint32_t *handle) {
88 #if defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
89   // HACK: as SEE does not support software batching in uimg via QCM/uQSockets,
90   // reroute requests for accel and uncal accel/gyro/mag from a big image
91   // nanoapp to a separate sensor type internally. These are the only always-on
92   // sensors used today by big image nanoapps, and this change allows these
93   // requests to transparently go to a separate sensor implementation that
94   // supports uimg batching via CM/QMI.
95   // TODO(P2-5673a9): work with QC to determine a better long-term solution
96   chre::Nanoapp *nanoapp = EventLoopManager::validateChreApiCall(__func__);
97   if (!nanoapp->isUimgApp()) {
98     // Since we have an accompanying hack in PlatformNanoapp::handleEvent(),
99     // hide the vendor sensor type from big image nanoapps as we're unable to
100     // deliver events for it
101     if (isBigImageSensorType(sensorType)) {
102       return false;
103     }
104     rewriteToBigImageSensorType(&sensorType);
105   }
106 #endif  // defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
107 
108   SensorType validatedSensorType = getSensorTypeFromUnsignedInt(sensorType);
109   return (validatedSensorType != SensorType::Unknown
110       && EventLoopManagerSingleton::get()->getSensorRequestManager()
111           .getSensorHandle(validatedSensorType, handle));
112 }
113 
chreGetSensorInfo(uint32_t sensorHandle,struct chreSensorInfo * info)114 DLL_EXPORT bool chreGetSensorInfo(uint32_t sensorHandle,
115                                   struct chreSensorInfo *info) {
116   CHRE_ASSERT(info);
117 
118   chre::Nanoapp *nanoapp = EventLoopManager::validateChreApiCall(__func__);
119 
120   bool success = false;
121   if (info != nullptr) {
122     success = EventLoopManagerSingleton::get()->getSensorRequestManager().
123         getSensorInfo(sensorHandle, *nanoapp, info);
124 
125     // The distinction between big/uimg accel and uncal accel/gyro/mag should
126     // be abstracted away from big image nanoapps, so overwrite any platform
127     // implementation here.
128 #if defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
129     if (!nanoapp->isUimgApp()) {
130       rewriteToChreSensorType(&info->sensorType);
131     }
132 #endif  // defined(CHRE_SLPI_SEE) && defined(CHRE_SLPI_UIMG_ENABLED)
133 
134   }
135   return success;
136 }
137 
chreGetSensorSamplingStatus(uint32_t sensorHandle,struct chreSensorSamplingStatus * status)138 DLL_EXPORT bool chreGetSensorSamplingStatus(
139     uint32_t sensorHandle, struct chreSensorSamplingStatus *status) {
140   CHRE_ASSERT(status);
141 
142   bool success = false;
143   if (status != nullptr) {
144     success = EventLoopManagerSingleton::get()->getSensorRequestManager().
145         getSensorSamplingStatus(sensorHandle, status);
146   }
147   return success;
148 }
149 
chreSensorConfigure(uint32_t sensorHandle,enum chreSensorConfigureMode mode,uint64_t interval,uint64_t latency)150 DLL_EXPORT bool chreSensorConfigure(uint32_t sensorHandle,
151                                     enum chreSensorConfigureMode mode,
152                                     uint64_t interval, uint64_t latency) {
153   chre::Nanoapp *nanoapp = EventLoopManager::validateChreApiCall(__func__);
154   SensorMode sensorMode = getSensorModeFromEnum(mode);
155   SensorRequest sensorRequest(nanoapp->getInstanceId(), sensorMode,
156                               Nanoseconds(interval), Nanoseconds(latency));
157   return EventLoopManagerSingleton::get()->getSensorRequestManager()
158       .setSensorRequest(nanoapp, sensorHandle, sensorRequest);
159 }
160 
chreSensorConfigureBiasEvents(uint32_t sensorHandle,bool enable)161 DLL_EXPORT bool chreSensorConfigureBiasEvents(uint32_t sensorHandle,
162                                               bool enable) {
163   chre::Nanoapp *nanoapp = EventLoopManager::validateChreApiCall(__func__);
164   return EventLoopManagerSingleton::get()->getSensorRequestManager()
165       .configureBiasEvents(nanoapp, sensorHandle, enable);
166 }
167 
chreSensorGetThreeAxisBias(uint32_t sensorHandle,struct chreSensorThreeAxisData * bias)168 DLL_EXPORT bool chreSensorGetThreeAxisBias(
169     uint32_t sensorHandle, struct chreSensorThreeAxisData *bias) {
170   return EventLoopManagerSingleton::get()->getSensorRequestManager()
171       .getThreeAxisBias(sensorHandle, bias);
172 }
173 
chreSensorFlushAsync(uint32_t sensorHandle,const void * cookie)174 DLL_EXPORT bool chreSensorFlushAsync(uint32_t sensorHandle,
175                                      const void *cookie) {
176   chre::Nanoapp *nanoapp = EventLoopManager::validateChreApiCall(__func__);
177   return EventLoopManagerSingleton::get()->getSensorRequestManager()
178       .flushAsync(nanoapp, sensorHandle, cookie);
179 }
180