11bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian/*
21bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * Copyright (C) 2010 The Android Open Source Project
31bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian *
41bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
51bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * you may not use this file except in compliance with the License.
61bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * You may obtain a copy of the License at
71bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian *
81bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
91bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian *
101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * Unless required by applicable law or agreed to in writing, software
111bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
121bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * See the License for the specific language governing permissions and
141bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian * limitations under the License.
151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian */
161bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
171bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <stdint.h>
18671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian#include <math.h>
191bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <sys/types.h>
201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
216043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian#include <cutils/properties.h>
226043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian
231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/SortedVector.h>
241bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/KeyedVector.h>
251bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/threads.h>
261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/Atomic.h>
271bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/Errors.h>
281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <utils/RefBase.h>
296f8b4d28d41508e3a563c12f5841918bb3869819Mathias Agopian#include <utils/Singleton.h>
3032123fde1b82fc7f5d04f35e2b972364d4352ec9Mathias Agopian#include <utils/String16.h>
311bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
321bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <binder/BinderService.h>
336f8b4d28d41508e3a563c12f5841918bb3869819Mathias Agopian#include <binder/IServiceManager.h>
340dd593f22352a0863223fa4ea7e37e926b99282eMathias Agopian#include <binder/PermissionCache.h>
351bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
361bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <gui/ISensorServer.h>
371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <gui/ISensorEventConnection.h>
381bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
391bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian#include <hardware/sensors.h>
401bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
4173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include "CorrectedGyroSensor.h"
42671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian#include "GravitySensor.h"
43671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian#include "LinearAccelerationSensor.h"
4473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include "OrientationSensor.h"
45671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian#include "RotationVectorSensor.h"
4673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include "SensorFusion.h"
4773e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian#include "SensorService.h"
481bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
491bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopiannamespace android {
501bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian// ---------------------------------------------------------------------------
511bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
526043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian/*
536043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian * Notes:
546043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian *
556043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian * - what about a gyro-corrected magnetic-field sensor?
566043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian * - run mag sensor from time to time to force calibration
576043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian * - gravity sensor length is wrong (=> drift in linear-acc sensor)
586043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian *
596043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian */
606043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian
611bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::SensorService()
620dd593f22352a0863223fa4ea7e37e926b99282eMathias Agopian    : mInitCheck(NO_INIT)
631bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
641bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
651bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
661bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianvoid SensorService::onFirstRef()
671bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
685df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian    LOGD("nuSensorService starting...");
695df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian
70671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    SensorDevice& dev(SensorDevice::getInstance());
711bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
72671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    if (dev.initCheck() == NO_ERROR) {
73671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        sensor_t const* list;
7429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian        ssize_t count = dev.getSensorList(&list);
7529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian        if (count > 0) {
7629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            ssize_t orientationIndex = -1;
7729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            bool hasGyro = false;
7829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            uint32_t virtualSensorsNeeds =
7929c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    (1<<SENSOR_TYPE_GRAVITY) |
8029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
8129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
8229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian
8329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            mLastEventSeen.setCapacity(count);
8429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            for (ssize_t i=0 ; i<count ; i++) {
8529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerSensor( new HardwareSensor(list[i]) );
8629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                switch (list[i].type) {
8729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    case SENSOR_TYPE_ORIENTATION:
8829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        orientationIndex = i;
8929c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        break;
9029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    case SENSOR_TYPE_GYROSCOPE:
9129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        hasGyro = true;
9229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        break;
9329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    case SENSOR_TYPE_GRAVITY:
9429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    case SENSOR_TYPE_LINEAR_ACCELERATION:
9529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    case SENSOR_TYPE_ROTATION_VECTOR:
9629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        virtualSensorsNeeds &= ~(1<<list[i].type);
9729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                        break;
9829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                }
995df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian            }
1001bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
10129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            // it's safe to instantiate the SensorFusion object here
10229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            // (it wants to be instantiated after h/w sensors have been
10329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            // registered)
10429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            const SensorFusion& fusion(SensorFusion::getInstance());
10529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian
10629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            if (hasGyro) {
10729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // Always instantiate Android's virtual sensors. Since they are
10829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // instantiated behind sensors from the HAL, they won't
10929c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // interfere with applications, unless they looks specifically
11029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // for them (by name).
11129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian
11229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerVirtualSensor( new RotationVectorSensor() );
11329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerVirtualSensor( new GravitySensor(list, count) );
11429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerVirtualSensor( new LinearAccelerationSensor(list, count) );
11529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian
11629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // these are optional
11729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerVirtualSensor( new OrientationSensor() );
11829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
11929c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian
12029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // virtual debugging sensors...
12129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                char value[PROPERTY_VALUE_MAX];
12229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                property_get("debug.sensors", value, "0");
12329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                if (atoi(value)) {
12429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    registerVirtualSensor( new GyroDriftSensor() );
12529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                }
1266043e5329cc023ae1bf6c0b7b750e584c1ebfbf4Mathias Agopian            }
127671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
12829c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            // build the sensor list returned to users
12929c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            mUserSensorList = mSensorList;
13029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            if (hasGyro &&
13129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
13229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // if we have the fancy sensor fusion, and it's not provided by the
13329c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // HAL, use our own (fused) orientation sensor by removing the
13429c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                // HAL supplied one form the user list.
13529c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                if (orientationIndex >= 0) {
13629c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                    mUserSensorList.removeItemsAt(orientationIndex);
13729c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian                }
138f8a6737f3d812b6b151990ad1695b55bfb0d8ddaMathias Agopian            }
139f8a6737f3d812b6b151990ad1695b55bfb0d8ddaMathias Agopian
14029c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            run("SensorService", PRIORITY_URGENT_DISPLAY);
14129c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian            mInitCheck = NO_ERROR;
14229c176f043333c2d286bbe7d5e6a82d2af97b535Mathias Agopian        }
1431bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
1441bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
1451bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
146671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopianvoid SensorService::registerSensor(SensorInterface* s)
147671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian{
148671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    sensors_event_t event;
149671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    memset(&event, 0, sizeof(event));
150671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
151671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    const Sensor sensor(s->getSensor());
152671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    // add to the sensor list (returned to clients)
153671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    mSensorList.add(sensor);
154671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    // add to our handle->SensorInterface mapping
155671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    mSensorMap.add(sensor.getHandle(), s);
156671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    // create an entry in the mLastEventSeen array
157671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    mLastEventSeen.add(sensor.getHandle(), event);
158671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian}
159671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
160671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopianvoid SensorService::registerVirtualSensor(SensorInterface* s)
161671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian{
162671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    registerSensor(s);
163671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    mVirtualSensorList.add( s );
164671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian}
165671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
1661bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::~SensorService()
1671bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
168671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    for (size_t i=0 ; i<mSensorMap.size() ; i++)
169671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        delete mSensorMap.valueAt(i);
1701bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
1711bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
1720dd593f22352a0863223fa4ea7e37e926b99282eMathias Agopianstatic const String16 sDump("android.permission.DUMP");
1730dd593f22352a0863223fa4ea7e37e926b99282eMathias Agopian
1741bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::dump(int fd, const Vector<String16>& args)
1751bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
1761bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    const size_t SIZE = 1024;
1771bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    char buffer[SIZE];
1781bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    String8 result;
1790dd593f22352a0863223fa4ea7e37e926b99282eMathias Agopian    if (!PermissionCache::checkCallingPermission(sDump)) {
1801bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        snprintf(buffer, SIZE, "Permission Denial: "
1811bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
1821bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                IPCThreadState::self()->getCallingPid(),
1831bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                IPCThreadState::self()->getCallingUid());
1841bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        result.append(buffer);
1851bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    } else {
1861bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        Mutex::Autolock _l(mLock);
187aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        snprintf(buffer, SIZE, "Sensor List:\n");
188aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        result.append(buffer);
189aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        for (size_t i=0 ; i<mSensorList.size() ; i++) {
190aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            const Sensor& s(mSensorList[i]);
191aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
19273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian            snprintf(buffer, SIZE,
19373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                    "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | "
19473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                    "last=<%5.1f,%5.1f,%5.1f>\n",
195aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                    s.getName().string(),
196aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                    s.getVendor().string(),
197aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                    s.getHandle(),
19894c4f5c1b28344001bae5ac4ad22dd01dc2fd679Mathias Agopian                    s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f,
199aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                    e.data[0], e.data[1], e.data[2]);
200aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            result.append(buffer);
201aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        }
20273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian        SensorFusion::getInstance().dump(result, buffer, SIZE);
203671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        SensorDevice::getInstance().dump(result, buffer, SIZE);
204aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian
205d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        snprintf(buffer, SIZE, "%d active connections\n",
206d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian                mActiveConnections.size());
2071bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        result.append(buffer);
2081bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        snprintf(buffer, SIZE, "Active sensors:\n");
2091bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        result.append(buffer);
2101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
21142e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian            int handle = mActiveSensors.keyAt(i);
212671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n",
21342e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian                    getSensorName(handle).string(),
21442e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian                    handle,
2151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                    mActiveSensors.valueAt(i)->getNumConnections());
2161bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            result.append(buffer);
2171bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
2181bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
2191bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    write(fd, result.string(), result.size());
2201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return NO_ERROR;
2211bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
2221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
2231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianbool SensorService::threadLoop()
2241bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
2251bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    LOGD("nuSensorService thread starting...");
2261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
227671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    const size_t numEventMax = 16 * (1 + mVirtualSensorList.size());
228671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    sensors_event_t buffer[numEventMax];
229671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    sensors_event_t scratch[numEventMax];
230671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    SensorDevice& device(SensorDevice::getInstance());
231671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    const size_t vcount = mVirtualSensorList.size();
2321bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
233671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    ssize_t count;
2341bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    do {
235671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        count = device.poll(buffer, numEventMax);
2361bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        if (count<0) {
2371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            LOGE("sensor poll failed (%s)", strerror(-count));
2381bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            break;
2391bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
2401bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
2413a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        recordLastValue(buffer, count);
2423a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian
243671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        // handle virtual sensors
244671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        if (count && vcount) {
24573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian            sensors_event_t const * const event = buffer;
246671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            const DefaultKeyedVector<int, SensorInterface*> virtualSensors(
247671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    getActiveVirtualSensors());
248671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            const size_t activeVirtualSensorCount = virtualSensors.size();
249671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (activeVirtualSensorCount) {
250671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                size_t k = 0;
25173e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                SensorFusion& fusion(SensorFusion::getInstance());
25273e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                if (fusion.isEnabled()) {
25373e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                    for (size_t i=0 ; i<size_t(count) ; i++) {
25473e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                        fusion.process(event[i]);
25573e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                    }
25673e0bc805a143d8cc2202fccb73230459edc6869Mathias Agopian                }
257671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                for (size_t i=0 ; i<size_t(count) ; i++) {
258671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
259671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                        sensors_event_t out;
260671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                        if (virtualSensors.valueAt(j)->process(&out, event[i])) {
261671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                            buffer[count + k] = out;
262671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                            k++;
263671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                        }
264671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    }
265671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                }
266671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                if (k) {
267671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    // record the last synthesized values
268671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    recordLastValue(&buffer[count], k);
269671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    count += k;
270671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    // sort the buffer by time-stamps
271671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    sortEventBuffer(buffer, count);
272671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                }
273671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            }
274671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        }
275671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
276671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        // send our events to clients...
2771bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        const SortedVector< wp<SensorEventConnection> > activeConnections(
2781bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian                getActiveConnections());
2791bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        size_t numConnections = activeConnections.size();
280671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        for (size_t i=0 ; i<numConnections ; i++) {
281671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            sp<SensorEventConnection> connection(
282671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    activeConnections[i].promote());
283671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (connection != 0) {
284671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                connection->sendEvents(buffer, count, scratch);
2851bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            }
2861bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
2871bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    } while (count >= 0 || Thread::exitPending());
2881bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
28937d95f6f91713825ebb5edd6ce4e376fc093a750Mathias Agopian    LOGW("Exiting SensorService::threadLoop => aborting...");
29037d95f6f91713825ebb5edd6ce4e376fc093a750Mathias Agopian    abort();
2911bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return false;
2921bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
2931bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
2943a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopianvoid SensorService::recordLastValue(
2953a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        sensors_event_t const * buffer, size_t count)
2963a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian{
2973a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    Mutex::Autolock _l(mLock);
2983a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian
2993a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    // record the last event for each sensor
3003a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    int32_t prev = buffer[0].sensor;
3013a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    for (size_t i=1 ; i<count ; i++) {
3023a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        // record the last event of each sensor type in this buffer
3033a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        int32_t curr = buffer[i].sensor;
3043a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        if (curr != prev) {
3053a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian            mLastEventSeen.editValueFor(prev) = buffer[i-1];
3063a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian            prev = curr;
3073a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian        }
3083a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    }
3093a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian    mLastEventSeen.editValueFor(prev) = buffer[count-1];
3103a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian}
3113a9223ebf881b10996dac34b00e51e08a602d44bMathias Agopian
312671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopianvoid SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
313671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian{
314671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    struct compar {
315671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        static int cmp(void const* lhs, void const* rhs) {
316671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
317671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs);
318671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            return r->timestamp - l->timestamp;
319671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        }
320671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    };
321671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
322671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian}
323671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
3241bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSortedVector< wp<SensorService::SensorEventConnection> >
3251bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::getActiveConnections() const
3261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
3271bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    Mutex::Autolock _l(mLock);
3281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return mActiveConnections;
3291bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
3301bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
331671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias AgopianDefaultKeyedVector<int, SensorInterface*>
332671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias AgopianSensorService::getActiveVirtualSensors() const
333671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian{
334671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    Mutex::Autolock _l(mLock);
335671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    return mActiveVirtualSensors;
336671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian}
337671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian
33842e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias AgopianString8 SensorService::getSensorName(int handle) const {
339f8a6737f3d812b6b151990ad1695b55bfb0d8ddaMathias Agopian    size_t count = mUserSensorList.size();
34042e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian    for (size_t i=0 ; i<count ; i++) {
341f8a6737f3d812b6b151990ad1695b55bfb0d8ddaMathias Agopian        const Sensor& sensor(mUserSensorList[i]);
34242e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian        if (sensor.getHandle() == handle) {
34342e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian            return sensor.getName();
34442e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian        }
34542e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian    }
34642e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian    String8 result("unknown");
34742e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian    return result;
34842e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian}
34942e1b39ac53709d9a9a74cd803e8ded10cf03848Mathias Agopian
3501bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianVector<Sensor> SensorService::getSensorList()
3511bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
352f8a6737f3d812b6b151990ad1695b55bfb0d8ddaMathias Agopian    return mUserSensorList;
3531bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
3541bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
3551bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopiansp<ISensorEventConnection> SensorService::createSensorEventConnection()
3561bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
3571bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    sp<SensorEventConnection> result(new SensorEventConnection(this));
3581bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return result;
3591bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
3601bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
361f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopianvoid SensorService::cleanupConnection(SensorEventConnection* c)
3621bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
3631bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    Mutex::Autolock _l(mLock);
364f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian    const wp<SensorEventConnection> connection(c);
365d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    size_t size = mActiveSensors.size();
3669ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian    LOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size);
367d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    for (size_t i=0 ; i<size ; ) {
368f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian        int handle = mActiveSensors.keyAt(i);
369f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian        if (c->hasSensor(handle)) {
3709ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian            LOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle);
371671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            SensorInterface* sensor = mSensorMap.valueFor( handle );
3729ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian            LOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
373671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (sensor) {
374f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian                sensor->activate(c, false);
375671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            }
376f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian        }
377f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian        SensorRecord* rec = mActiveSensors.valueAt(i);
3789ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian        LOGE_IF(!rec, "mActiveSensors[%d] is null (handle=0x%08x)!", i, handle);
3799ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian        LOGD_IF(DEBUG_CONNECTIONS,
3809ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian                "removing connection %p for sensor[%d].handle=0x%08x",
3819ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian                c, i, handle);
3829ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian
383f0aec213ec02fb833f3c927206dad9693e0672deMathias Agopian        if (rec && rec->removeConnection(connection)) {
3849ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian            LOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
385d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian            mActiveSensors.removeItemsAt(i, 1);
386671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            mActiveVirtualSensors.removeItem(handle);
387d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian            delete rec;
388d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian            size--;
389d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        } else {
390d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian            i++;
3911bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
3921bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
393d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    mActiveConnections.remove(connection);
3941bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
3951bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
3961bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::enable(const sp<SensorEventConnection>& connection,
3971bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        int handle)
3981bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
3995df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian    if (mInitCheck != NO_ERROR)
4005df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian        return mInitCheck;
4015df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian
4021bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    Mutex::Autolock _l(mLock);
403671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    SensorInterface* sensor = mSensorMap.valueFor(handle);
404671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
405671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    if (err == NO_ERROR) {
406671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        SensorRecord* rec = mActiveSensors.valueFor(handle);
407671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        if (rec == 0) {
408671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            rec = new SensorRecord(connection);
409671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            mActiveSensors.add(handle, rec);
410671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (sensor->isVirtual()) {
411671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                mActiveVirtualSensors.add(handle, sensor);
412671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            }
413671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        } else {
414671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (rec->addConnection(connection)) {
415671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                // this sensor is already activated, but we are adding a
416671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                // connection that uses it. Immediately send down the last
4178d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                // known value of the requested sensor if it's not a
4188d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                // "continuous" sensor.
4198d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                if (sensor->getSensor().getMinDelay() == 0) {
4208d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                    sensors_event_t scratch;
4218d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                    sensors_event_t& event(mLastEventSeen.editValueFor(handle));
4228d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                    if (event.version == sizeof(sensors_event_t)) {
4238d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                        connection->sendEvents(&event, 1);
4248d94d82a6dcf987edec0cf642a4d21b8a367550cMathias Agopian                    }
425671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                }
426aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            }
427aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        }
428671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        if (err == NO_ERROR) {
429671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            // connection now active
430671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (connection->addSensor(handle)) {
431671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                // the sensor was added (which means it wasn't already there)
432671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                // so, see if this connection becomes active
433671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                if (mActiveConnections.indexOf(connection) < 0) {
434671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                    mActiveConnections.add(connection);
435671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian                }
436d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian            }
4371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
4381bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
4391bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return err;
4401bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
4411bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
4421bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::disable(const sp<SensorEventConnection>& connection,
4431bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        int handle)
4441bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
4455df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian    if (mInitCheck != NO_ERROR)
4465df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian        return mInitCheck;
4475df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian
4481bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    status_t err = NO_ERROR;
4491bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    Mutex::Autolock _l(mLock);
4501bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    SensorRecord* rec = mActiveSensors.valueFor(handle);
4511bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    if (rec) {
4521bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        // see if this connection becomes inactive
4531bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        connection->removeSensor(handle);
4541bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        if (connection->hasAnySensor() == false) {
4551bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            mActiveConnections.remove(connection);
4561bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
4571bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        // see if this sensor becomes inactive
4581bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        if (rec->removeConnection(connection)) {
4591bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            mActiveSensors.removeItem(handle);
460671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            mActiveVirtualSensors.removeItem(handle);
4611bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian            delete rec;
4621bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        }
463671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        SensorInterface* sensor = mSensorMap.valueFor(handle);
464671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
465d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    }
4661bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return err;
4671bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
4681bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
469d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopianstatus_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
4701bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        int handle, nsecs_t ns)
4711bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
4725df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian    if (mInitCheck != NO_ERROR)
4735df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian        return mInitCheck;
4745df13ef30e7dd58e4e718e6d949ac3d1f5af94e0Mathias Agopian
475f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian    SensorInterface* sensor = mSensorMap.valueFor(handle);
476f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian    if (!sensor)
477f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian        return BAD_VALUE;
478f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian
47923e8de26b7b3d04daf08526f314c2fdd2f8fee65Mathias Agopian    if (ns < 0)
48023e8de26b7b3d04daf08526f314c2fdd2f8fee65Mathias Agopian        return BAD_VALUE;
48123e8de26b7b3d04daf08526f314c2fdd2f8fee65Mathias Agopian
482eed2373321a84560961884697b4bd92d0ee9f7c9Mathias Agopian    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
483eed2373321a84560961884697b4bd92d0ee9f7c9Mathias Agopian    if (ns < minDelayNs) {
484eed2373321a84560961884697b4bd92d0ee9f7c9Mathias Agopian        ns = minDelayNs;
485f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian    }
486f61acdac57ddac5ebc1b1ca009351fca86926152Mathias Agopian
487d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    if (ns < MINIMUM_EVENTS_PERIOD)
488d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        ns = MINIMUM_EVENTS_PERIOD;
48923e8de26b7b3d04daf08526f314c2fdd2f8fee65Mathias Agopian
490671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    return sensor->setDelay(connection.get(), handle, ns);
4911bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
4921bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
4931bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian// ---------------------------------------------------------------------------
4941bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
4951bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::SensorRecord::SensorRecord(
4961bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        const sp<SensorEventConnection>& connection)
4971bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
4981bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    mConnections.add(connection);
4991bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5001bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
501d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopianbool SensorService::SensorRecord::addConnection(
5021bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        const sp<SensorEventConnection>& connection)
5031bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
5041bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    if (mConnections.indexOf(connection) < 0) {
5051bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        mConnections.add(connection);
506d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        return true;
5071bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
508d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    return false;
5091bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5111bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianbool SensorService::SensorRecord::removeConnection(
5121bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        const wp<SensorEventConnection>& connection)
5131bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
5141bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    ssize_t index = mConnections.indexOf(connection);
5151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    if (index >= 0) {
5161bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        mConnections.removeItemsAt(index, 1);
5171bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
5181bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return mConnections.size() ? false : true;
5191bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5211bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian// ---------------------------------------------------------------------------
5221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5231bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::SensorEventConnection::SensorEventConnection(
5241bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        const sp<SensorService>& service)
5251bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    : mService(service), mChannel(new SensorChannel())
5261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
5271bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5291bf797857e025e8a71db86fb9e79765a767ec1ebMathias AgopianSensorService::SensorEventConnection::~SensorEventConnection()
5301bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
5319ff73de08f137ba03e18b8fd9fe0b070029c00f5Mathias Agopian    LOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
5321bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    mService->cleanupConnection(this);
5331bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5341bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5351bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianvoid SensorService::SensorEventConnection::onFirstRef()
5361bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
5371bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5381bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
539d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopianbool SensorService::SensorEventConnection::addSensor(int32_t handle) {
540f33a6e9645517b9bcf7236bc6f2b7fe182a0137dMathias Agopian    Mutex::Autolock _l(mConnectionLock);
541671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    if (mSensorInfo.indexOf(handle) <= 0) {
542671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian        mSensorInfo.add(handle);
543d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        return true;
5441bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
545d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    return false;
5461bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5471bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
548d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopianbool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
549f33a6e9645517b9bcf7236bc6f2b7fe182a0137dMathias Agopian    Mutex::Autolock _l(mConnectionLock);
550671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    if (mSensorInfo.remove(handle) >= 0) {
551d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian        return true;
552d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    }
553d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    return false;
5541bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5551bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5561bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianbool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
557f33a6e9645517b9bcf7236bc6f2b7fe182a0137dMathias Agopian    Mutex::Autolock _l(mConnectionLock);
558671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian    return mSensorInfo.indexOf(handle) >= 0;
5591bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
5601bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
5611bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianbool SensorService::SensorEventConnection::hasAnySensor() const {
562f33a6e9645517b9bcf7236bc6f2b7fe182a0137dMathias Agopian    Mutex::Autolock _l(mConnectionLock);
563d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    return mSensorInfo.size() ? true : false;
564d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian}
565d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian
5661bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::SensorEventConnection::sendEvents(
567efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian        sensors_event_t const* buffer, size_t numEvents,
568efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian        sensors_event_t* scratch)
5691bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
570efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian    // filter out events not for this connection
571aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian    size_t count = 0;
572aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian    if (scratch) {
573f33a6e9645517b9bcf7236bc6f2b7fe182a0137dMathias Agopian        Mutex::Autolock _l(mConnectionLock);
574aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        size_t i=0;
575aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        while (i<numEvents) {
576aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            const int32_t curr = buffer[i].sensor;
577671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8Mathias Agopian            if (mSensorInfo.indexOf(curr) >= 0) {
578aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                do {
579aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                    scratch[count++] = buffer[i++];
580aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                } while ((i<numEvents) && (buffer[i].sensor == curr));
581aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            } else {
582aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian                i++;
583aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian            }
584efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian        }
585aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian    } else {
586aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        scratch = const_cast<sensors_event_t *>(buffer);
587aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        count = numEvents;
588efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian    }
5891bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
590aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian    if (count == 0)
591aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian        return 0;
592aea786f42cee6a899e8f78fdbf82cb1cac544430Mathias Agopian
593efba8bf53aa6d0efb8cf778aaa63a482b813d2b1Mathias Agopian    ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t));
5941bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    if (size == -EAGAIN) {
5951bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        // the destination doesn't accept events anymore, it's probably
5961bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        // full. For now, we just drop the events on the floor.
597f9a4b1366e6d77f5044a4a8de8f14d391baf6a2bMathias Agopian        //LOGW("dropping %d events on the floor", count);
5981bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        return size;
5991bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
6001bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
601f9a4b1366e6d77f5044a4a8de8f14d391baf6a2bMathias Agopian    //LOGE_IF(size<0, "dropping %d events on the floor (%s)",
602f9a4b1366e6d77f5044a4a8de8f14d391baf6a2bMathias Agopian    //        count, strerror(-size));
6031bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
6044fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    return size < 0 ? status_t(size) : status_t(NO_ERROR);
6051bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
6061bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
6071bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopiansp<SensorChannel> SensorService::SensorEventConnection::getSensorChannel() const
6081bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
6091bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return mChannel;
6101bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
6111bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
6121bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::SensorEventConnection::enableDisable(
6131bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        int handle, bool enabled)
6141bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
6151bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    status_t err;
6161bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    if (enabled) {
6171bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        err = mService->enable(this, handle);
6181bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    } else {
6191bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        err = mService->disable(this, handle);
6201bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    }
6211bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    return err;
6221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
6231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
6241bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopianstatus_t SensorService::SensorEventConnection::setEventRate(
6251bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian        int handle, nsecs_t ns)
6261bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian{
627d8653518449e3dbf03fe6f8b11dbdff5ef6ce60eMathias Agopian    return mService->setEventRate(this, handle, ns);
6281bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}
6291bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
6301bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian// ---------------------------------------------------------------------------
6311bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian}; // namespace android
6321bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
633