1/*
2 * Copyright (C) 2010 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 <stdint.h>
18#include <math.h>
19#include <sys/types.h>
20
21#include <utils/Errors.h>
22
23#include <hardware/sensors.h>
24
25#include "GravitySensor.h"
26#include "SensorDevice.h"
27#include "SensorFusion.h"
28
29namespace android {
30// ---------------------------------------------------------------------------
31
32GravitySensor::GravitySensor(sensor_t const* list, size_t count) {
33    for (size_t i=0 ; i<count ; i++) {
34        if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
35            mAccelerometer = Sensor(list + i);
36            break;
37        }
38    }
39
40    const sensor_t sensor = {
41        .name       = "Gravity Sensor",
42        .vendor     = "AOSP",
43        .version    = 3,
44        .handle     = '_grv',
45        .type       = SENSOR_TYPE_GRAVITY,
46        .maxRange   = GRAVITY_EARTH * 2,
47        .resolution = mAccelerometer.getResolution(),
48        .power      = mSensorFusion.getPowerUsage(),
49        .minDelay   = mSensorFusion.getMinDelay(),
50    };
51    mSensor = Sensor(&sensor);
52}
53
54bool GravitySensor::process(sensors_event_t* outEvent,
55        const sensors_event_t& event)
56{
57    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
58        vec3_t g;
59        if (!mSensorFusion.hasEstimate(FUSION_NOMAG))
60            return false;
61        const mat33_t R(mSensorFusion.getRotationMatrix(FUSION_NOMAG));
62        // FIXME: we need to estimate the length of gravity because
63        // the accelerometer may have a small scaling error. This
64        // translates to an offset in the linear-acceleration sensor.
65        g = R[2] * GRAVITY_EARTH;
66
67        *outEvent = event;
68        outEvent->data[0] = g.x;
69        outEvent->data[1] = g.y;
70        outEvent->data[2] = g.z;
71        outEvent->sensor = '_grv';
72        outEvent->type = SENSOR_TYPE_GRAVITY;
73        return true;
74    }
75    return false;
76}
77
78status_t GravitySensor::activate(void* ident, bool enabled) {
79    return mSensorFusion.activate(FUSION_NOMAG, ident, enabled);
80}
81
82status_t GravitySensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
83    return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
84}
85
86// ---------------------------------------------------------------------------
87}; // namespace android
88
89