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