1 /*
2  * Copyright (C) 2018 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/platform/slpi/see/see_cal_helper.h"
18 
19 #include "chre/platform/assert.h"
20 #include "chre/platform/log.h"
21 #include "chre/platform/slpi/see/see_helper.h"
22 #include "chre/util/lock_guard.h"
23 #include "chre/util/macros.h"
24 
25 namespace chre {
26 
applyCalibration(SensorType sensorType,const float input[3],float output[3]) const27 void SeeCalHelper::applyCalibration(SensorType sensorType, const float input[3],
28                                     float output[3]) const {
29   bool applied = false;
30   size_t index = getCalIndexFromSensorType(sensorType);
31   if (index < ARRAY_SIZE(mCalInfo)) {
32     LockGuard<Mutex> lock(mMutex);
33 
34     // TODO: Support compensation matrix and scaling factor calibration
35     if (mCalInfo[index].cal.hasBias) {
36       for (size_t i = 0; i < 3; i++) {
37         output[i] = input[i] - mCalInfo[index].cal.bias[i];
38       }
39       applied = true;
40     }
41   }
42 
43   if (!applied) {
44     for (size_t i = 0; i < 3; i++) {
45       output[i] = input[i];
46     }
47   }
48 }
49 
getBias(SensorType sensorType,struct chreSensorThreeAxisData * biasData) const50 bool SeeCalHelper::getBias(
51     SensorType sensorType, struct chreSensorThreeAxisData *biasData) const {
52   CHRE_ASSERT(biasData != nullptr);
53 
54   bool success = false;
55   if (biasData != nullptr) {
56     size_t index = getCalIndexFromSensorType(sensorType);
57     if (index < ARRAY_SIZE(mCalInfo)) {
58       LockGuard<Mutex> lock(mMutex);
59 
60       if (mCalInfo[index].cal.hasBias) {
61         biasData->header.baseTimestamp = mCalInfo[index].cal.timestamp;
62         biasData->header.sensorHandle =
63             getSensorHandleFromSensorType(sensorType);
64         biasData->header.readingCount = 1;
65         biasData->header.accuracy = mCalInfo[index].cal.accuracy;
66         biasData->header.reserved = 0;
67 
68         for (size_t i = 0; i < 3; i++) {
69           biasData->readings[0].bias[i] = mCalInfo[index].cal.bias[i];
70         }
71         biasData->readings[0].timestampDelta = 0;
72         success = true;
73       }
74     }
75   }
76 
77   return success;
78 }
79 
areCalUpdatesEnabled(const sns_std_suid & suid) const80 bool SeeCalHelper::areCalUpdatesEnabled(const sns_std_suid &suid) const {
81   size_t index = getCalIndexFromSuid(suid);
82   if (index < ARRAY_SIZE(mCalInfo)) {
83     return mCalInfo[index].enabled;
84   }
85   return false;
86 }
87 
configureCalUpdates(const sns_std_suid & suid,bool enable,SeeHelper & helper)88 bool SeeCalHelper::configureCalUpdates(const sns_std_suid &suid, bool enable,
89                                        SeeHelper &helper) {
90   bool success = false;
91 
92   size_t index = getCalIndexFromSuid(suid);
93   if (index >= ARRAY_SIZE(mCalInfo)) {
94     CHRE_ASSERT(false);
95   } else if ((mCalInfo[index].enabled == enable) ||
96              helper.configureOnChangeSensor(suid, enable)) {
97     success = true;
98     mCalInfo[index].enabled = enable;
99   }
100 
101   return success;
102 }
103 
getCalSuidFromSensorType(SensorType sensorType) const104 const sns_std_suid *SeeCalHelper::getCalSuidFromSensorType(
105     SensorType sensorType) const {
106   // Mutex not needed, SUID is not modified after init
107   size_t calIndex = getCalIndexFromSensorType(sensorType);
108   if (calIndex < ARRAY_SIZE(mCalInfo) && mCalInfo[calIndex].suid.has_value()) {
109     return &mCalInfo[calIndex].suid.value();
110   }
111   return nullptr;
112 }
113 
registerForCalibrationUpdates(SeeHelper & seeHelper)114 bool SeeCalHelper::registerForCalibrationUpdates(SeeHelper& seeHelper) {
115   bool success = true;
116 
117   // Find the cal sensor's SUID, assign it to mCalInfo, and make cal sensor data
118   // request.
119   DynamicVector<sns_std_suid> suids;
120   for (size_t i = 0; i < ARRAY_SIZE(mCalInfo); i++) {
121     const char *calType = getDataTypeForCalSensorIndex(i);
122     if (!seeHelper.findSuidSync(calType, &suids)) {
123       success = false;
124       LOGE("Failed to find sensor '%s'", calType);
125     } else {
126       mCalInfo[i].suid = suids[0];
127       // The calibrated sensor type uses power on the default build
128 #ifndef CHRE_SLPI_DEFAULT_BUILD
129       if (!seeHelper.configureOnChangeSensor(suids[0], true /* enable */)) {
130         success = false;
131         LOGE("Failed to request '%s' data", calType);
132       }
133 #endif
134     }
135   }
136 
137   return success;
138 }
139 
updateCalibration(const sns_std_suid & suid,bool hasBias,float bias[3],bool hasScale,float scale[3],bool hasMatrix,float matrix[9],uint8_t accuracy,uint64_t timestamp)140 void SeeCalHelper::updateCalibration(
141     const sns_std_suid& suid, bool hasBias, float bias[3], bool hasScale,
142     float scale[3], bool hasMatrix, float matrix[9], uint8_t accuracy,
143     uint64_t timestamp) {
144   size_t index = getCalIndexFromSuid(suid);
145   if (index < ARRAY_SIZE(mCalInfo)) {
146     LockGuard<Mutex> lock(mMutex);
147     SeeCalData& calData = mCalInfo[index].cal;
148 
149     calData.hasBias = hasBias;
150     if (hasBias) {
151       memcpy(calData.bias, bias, sizeof(calData.bias));
152     }
153 
154     calData.hasScale = hasScale;
155     if (hasScale) {
156       memcpy(calData.scale, scale, sizeof(calData.scale));
157     }
158 
159     calData.hasMatrix = hasMatrix;
160     if (hasMatrix) {
161       memcpy(calData.matrix, matrix, sizeof(calData.matrix));
162     }
163 
164     calData.accuracy = accuracy;
165     calData.timestamp = timestamp;
166   }
167 }
168 
getSensorTypeFromSuid(const sns_std_suid & suid) const169 SensorType SeeCalHelper::getSensorTypeFromSuid(const sns_std_suid& suid) const {
170   size_t calSensorIndex = getCalIndexFromSuid(suid);
171   switch (static_cast<SeeCalSensor>(calSensorIndex)) {
172 #ifdef CHRE_ENABLE_ACCEL_CAL
173     case SeeCalSensor::AccelCal:
174       return SensorType::Accelerometer;
175 #endif  // CHRE_ENABLE_ACCEL_CAL
176     case SeeCalSensor::GyroCal:
177       return SensorType::Gyroscope;
178     case SeeCalSensor::MagCal:
179       return SensorType::GeomagneticField;
180     default:
181       // Fall-through as CHRE can receive calibration events for other sensors
182       // even if it doesn't request them.
183       break;
184   }
185   return SensorType::Unknown;
186 }
187 
getCalIndexFromSensorType(SensorType sensorType)188 size_t SeeCalHelper::getCalIndexFromSensorType(SensorType sensorType) {
189   SeeCalSensor index;
190   switch (sensorType) {
191 #ifdef CHRE_ENABLE_ACCEL_CAL
192     case SensorType::Accelerometer:
193       index = SeeCalSensor::AccelCal;
194       break;
195 #endif  // CHRE_ENABLE_ACCEL_CAL
196     case SensorType::Gyroscope:
197       index = SeeCalSensor::GyroCal;
198       break;
199     case SensorType::GeomagneticField:
200       index = SeeCalSensor::MagCal;
201       break;
202     default:
203       index = SeeCalSensor::NumCalSensors;
204   }
205   return static_cast<size_t>(index);
206 }
207 
getDataTypeForCalSensorIndex(size_t calSensorIndex)208 const char *SeeCalHelper::getDataTypeForCalSensorIndex(size_t calSensorIndex) {
209   switch (static_cast<SeeCalSensor>(calSensorIndex)) {
210 #ifdef CHRE_ENABLE_ACCEL_CAL
211     case SeeCalSensor::AccelCal:
212       return "accel_cal";
213 #endif  // CHRE_ENABLE_ACCEL_CAL
214     case SeeCalSensor::GyroCal:
215       return "gyro_cal";
216     case SeeCalSensor::MagCal:
217       return "mag_cal";
218     default:
219       CHRE_ASSERT(false);
220   }
221   return nullptr;
222 }
223 
getCalIndexFromSuid(const sns_std_suid & suid) const224 size_t SeeCalHelper::getCalIndexFromSuid(const sns_std_suid& suid) const {
225   size_t i = 0;
226   for (; i < ARRAY_SIZE(mCalInfo); i++) {
227     if (mCalInfo[i].suid.has_value()
228         && suidsMatch(suid, mCalInfo[i].suid.value())) {
229       break;
230     }
231   }
232   return i;
233 }
234 
235 }  // namespace chre
236