blob: b79373d8025f74f8b9f913197bee4268d939e862 [file] [log] [blame]
Mathias Agopian1bf79782010-07-14 23:41:37 -07001/*
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 <sys/types.h>
19
20#include <utils/SortedVector.h>
21#include <utils/KeyedVector.h>
22#include <utils/threads.h>
23#include <utils/Atomic.h>
24#include <utils/Errors.h>
25#include <utils/RefBase.h>
Mathias Agopian6f8b4d22010-07-19 15:03:55 -070026#include <utils/Singleton.h>
Mathias Agopian1bf79782010-07-14 23:41:37 -070027
28#include <binder/BinderService.h>
Mathias Agopian6f8b4d22010-07-19 15:03:55 -070029#include <binder/IServiceManager.h>
Mathias Agopian1bf79782010-07-14 23:41:37 -070030
31#include <gui/ISensorServer.h>
32#include <gui/ISensorEventConnection.h>
33
34#include <hardware/sensors.h>
35
36#include "SensorService.h"
37
38namespace android {
39// ---------------------------------------------------------------------------
40
41/*
42 * TODO:
Mathias Agopian1bf79782010-07-14 23:41:37 -070043 * - make sure to keep the last value of each event type so we can quickly
44 * send something to application when they enable a sensor that is already
45 * active (the issue here is that it can take time before a value is
46 * produced by the h/w if the rate is low or if it's a one-shot sensor).
Mathias Agopian6f8b4d22010-07-19 15:03:55 -070047 * - send sensor info to battery service
Mathias Agopian1bf79782010-07-14 23:41:37 -070048 */
49
Mathias Agopian6f8b4d22010-07-19 15:03:55 -070050// ---------------------------------------------------------------------------
51
52class BatteryService : public Singleton<BatteryService> {
53 friend class Singleton<BatteryService>;
54 sp<IBinder> mBatteryStatService;
55 BatteryService() {
56 const String16 name("batteryinfo");
57 //getService(name, &mBatteryStatService);
58 }
59public:
60 void enableSensor(int handle) {
61 if (mBatteryStatService != 0) {
62 int uid = IPCThreadState::self()->getCallingUid();
63 //mBatteryStatService->noteStartSensor(uid, handle);
64 }
65 }
66 void disableSensor(int handle) {
67 if (mBatteryStatService != 0) {
68 int uid = IPCThreadState::self()->getCallingUid();
69 //mBatteryStatService->noteStopSensor(uid, handle);
70 }
71 }
72};
73
74ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
75
76// ---------------------------------------------------------------------------
77
Mathias Agopian23e8de22010-07-21 15:59:50 -070078// 100 events/s max
79static const nsecs_t MINIMUM_EVENT_PERIOD = ms2ns(10);
80
Mathias Agopian1bf79782010-07-14 23:41:37 -070081SensorService::SensorService()
82 : Thread(false),
Mathias Agopian5df13ef2010-07-19 19:09:10 -070083 mSensorDevice(0),
84 mSensorModule(0),
85 mDump("android.permission.DUMP"),
86 mInitCheck(NO_INIT)
Mathias Agopian1bf79782010-07-14 23:41:37 -070087{
88}
89
90void SensorService::onFirstRef()
91{
Mathias Agopian5df13ef2010-07-19 19:09:10 -070092 LOGD("nuSensorService starting...");
93
Mathias Agopian1bf79782010-07-14 23:41:37 -070094 status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
95 (hw_module_t const**)&mSensorModule);
96
97 LOGE_IF(err, "couldn't load %s module (%s)",
98 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
99
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700100 if (mSensorModule) {
101 err = sensors_open(&mSensorModule->common, &mSensorDevice);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700102
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700103 LOGE_IF(err, "couldn't open device for module %s (%s)",
104 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
Mathias Agopian1bf79782010-07-14 23:41:37 -0700105
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700106 struct sensor_t const* list;
107 int count = mSensorModule->get_sensors_list(mSensorModule, &list);
108 for (int i=0 ; i<count ; i++) {
109 Sensor sensor(list + i);
110 LOGI("%s", sensor.getName().string());
111 mSensorList.add(sensor);
112 if (mSensorDevice) {
113 mSensorDevice->activate(mSensorDevice, sensor.getHandle(), 0);
114 }
115 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700116
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700117 if (mSensorDevice) {
118 run("SensorService", PRIORITY_URGENT_DISPLAY);
119 mInitCheck = NO_ERROR;
120 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700121 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700122}
123
124SensorService::~SensorService()
125{
126}
127
128status_t SensorService::dump(int fd, const Vector<String16>& args)
129{
130 const size_t SIZE = 1024;
131 char buffer[SIZE];
132 String8 result;
133 if (!mDump.checkCalling()) {
134 snprintf(buffer, SIZE, "Permission Denial: "
135 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
136 IPCThreadState::self()->getCallingPid(),
137 IPCThreadState::self()->getCallingUid());
138 result.append(buffer);
139 } else {
140 Mutex::Autolock _l(mLock);
Mathias Agopiand8653512010-07-21 15:59:50 -0700141 snprintf(buffer, SIZE, "%d active connections\n",
142 mActiveConnections.size());
Mathias Agopian1bf79782010-07-14 23:41:37 -0700143 result.append(buffer);
144 snprintf(buffer, SIZE, "Active sensors:\n");
145 result.append(buffer);
146 for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
Mathias Agopian42e1b392010-07-19 15:20:39 -0700147 int handle = mActiveSensors.keyAt(i);
148 snprintf(buffer, SIZE, "%s (handle=%d, connections=%d)\n",
149 getSensorName(handle).string(),
150 handle,
Mathias Agopian1bf79782010-07-14 23:41:37 -0700151 mActiveSensors.valueAt(i)->getNumConnections());
152 result.append(buffer);
153 }
154 }
155 write(fd, result.string(), result.size());
156 return NO_ERROR;
157}
158
159bool SensorService::threadLoop()
160{
161 LOGD("nuSensorService thread starting...");
162
163 sensors_event_t buffer[16];
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700164 sensors_event_t scratch[16];
Mathias Agopian1bf79782010-07-14 23:41:37 -0700165 struct sensors_poll_device_t* device = mSensorDevice;
166 ssize_t count;
167
168 do {
169 count = device->poll(device, buffer, sizeof(buffer)/sizeof(*buffer));
170 if (count<0) {
171 LOGE("sensor poll failed (%s)", strerror(-count));
172 break;
173 }
174
175 const SortedVector< wp<SensorEventConnection> > activeConnections(
176 getActiveConnections());
177
178 size_t numConnections = activeConnections.size();
179 if (numConnections) {
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700180 Mutex::Autolock _l(mLock);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700181 for (size_t i=0 ; i<numConnections ; i++) {
182 sp<SensorEventConnection> connection(activeConnections[i].promote());
183 if (connection != 0) {
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700184 connection->sendEvents(buffer, count, scratch);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700185 }
186 }
187 }
188
189 } while (count >= 0 || Thread::exitPending());
190
191 LOGW("Exiting SensorService::threadLoop!");
192 return false;
193}
194
195SortedVector< wp<SensorService::SensorEventConnection> >
196SensorService::getActiveConnections() const
197{
198 Mutex::Autolock _l(mLock);
199 return mActiveConnections;
200}
201
Mathias Agopian42e1b392010-07-19 15:20:39 -0700202String8 SensorService::getSensorName(int handle) const {
203 size_t count = mSensorList.size();
204 for (size_t i=0 ; i<count ; i++) {
205 const Sensor& sensor(mSensorList[i]);
206 if (sensor.getHandle() == handle) {
207 return sensor.getName();
208 }
209 }
210 String8 result("unknown");
211 return result;
212}
213
Mathias Agopian1bf79782010-07-14 23:41:37 -0700214Vector<Sensor> SensorService::getSensorList()
215{
216 return mSensorList;
217}
218
219sp<ISensorEventConnection> SensorService::createSensorEventConnection()
220{
221 sp<SensorEventConnection> result(new SensorEventConnection(this));
Mathias Agopian1bf79782010-07-14 23:41:37 -0700222 return result;
223}
224
225void SensorService::cleanupConnection(const wp<SensorEventConnection>& connection)
226{
227 Mutex::Autolock _l(mLock);
Mathias Agopiand8653512010-07-21 15:59:50 -0700228 size_t size = mActiveSensors.size();
229 for (size_t i=0 ; i<size ; ) {
230 SensorRecord* rec = mActiveSensors.valueAt(i);
231 if (rec && rec->removeConnection(connection)) {
232 mSensorDevice->activate(mSensorDevice, mActiveSensors.keyAt(i), 0);
233 mActiveSensors.removeItemsAt(i, 1);
234 delete rec;
235 size--;
236 } else {
237 i++;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700238 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700239 }
Mathias Agopiand8653512010-07-21 15:59:50 -0700240 mActiveConnections.remove(connection);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700241}
242
243status_t SensorService::enable(const sp<SensorEventConnection>& connection,
244 int handle)
245{
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700246 if (mInitCheck != NO_ERROR)
247 return mInitCheck;
248
Mathias Agopian1bf79782010-07-14 23:41:37 -0700249 status_t err = NO_ERROR;
250 Mutex::Autolock _l(mLock);
251 SensorRecord* rec = mActiveSensors.valueFor(handle);
252 if (rec == 0) {
253 rec = new SensorRecord(connection);
254 mActiveSensors.add(handle, rec);
255 err = mSensorDevice->activate(mSensorDevice, handle, 1);
256 LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
Mathias Agopian6f8b4d22010-07-19 15:03:55 -0700257 if (err == 0) {
258 BatteryService::getInstance().enableSensor(handle);
259 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700260 } else {
Mathias Agopiand8653512010-07-21 15:59:50 -0700261 rec->addConnection(connection);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700262 }
263 if (err == NO_ERROR) {
264 // connection now active
Mathias Agopiand8653512010-07-21 15:59:50 -0700265 if (connection->addSensor(handle)) {
266 // the sensor was added (which means it wasn't already there)
267 // so, see if this connection becomes active
268 if (mActiveConnections.indexOf(connection) < 0) {
269 mActiveConnections.add(connection);
270 }
271 // this could change the sensor event delivery speed
272 recomputeEventsPeriodLocked(handle);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700273 }
274 }
275 return err;
276}
277
278status_t SensorService::disable(const sp<SensorEventConnection>& connection,
279 int handle)
280{
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700281 if (mInitCheck != NO_ERROR)
282 return mInitCheck;
283
Mathias Agopian1bf79782010-07-14 23:41:37 -0700284 status_t err = NO_ERROR;
285 Mutex::Autolock _l(mLock);
286 SensorRecord* rec = mActiveSensors.valueFor(handle);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700287 if (rec) {
288 // see if this connection becomes inactive
289 connection->removeSensor(handle);
290 if (connection->hasAnySensor() == false) {
291 mActiveConnections.remove(connection);
292 }
293 // see if this sensor becomes inactive
294 if (rec->removeConnection(connection)) {
295 mActiveSensors.removeItem(handle);
296 delete rec;
297 err = mSensorDevice->activate(mSensorDevice, handle, 0);
Mathias Agopian6f8b4d22010-07-19 15:03:55 -0700298 if (err == 0) {
299 BatteryService::getInstance().disableSensor(handle);
300 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700301 }
302 }
Mathias Agopiand8653512010-07-21 15:59:50 -0700303 if (err == NO_ERROR) {
304 recomputeEventsPeriodLocked(handle);
305 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700306 return err;
307}
308
Mathias Agopiand8653512010-07-21 15:59:50 -0700309status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
Mathias Agopian1bf79782010-07-14 23:41:37 -0700310 int handle, nsecs_t ns)
311{
Mathias Agopian5df13ef2010-07-19 19:09:10 -0700312 if (mInitCheck != NO_ERROR)
313 return mInitCheck;
314
Mathias Agopian23e8de22010-07-21 15:59:50 -0700315 if (ns < 0)
316 return BAD_VALUE;
317
Mathias Agopiand8653512010-07-21 15:59:50 -0700318 if (ns < MINIMUM_EVENTS_PERIOD)
319 ns = MINIMUM_EVENTS_PERIOD;
Mathias Agopian23e8de22010-07-21 15:59:50 -0700320
Mathias Agopian1bf79782010-07-14 23:41:37 -0700321 Mutex::Autolock _l(mLock);
Mathias Agopiand8653512010-07-21 15:59:50 -0700322 status_t err = connection->setEventRateLocked(handle, ns);
323 if (err == NO_ERROR) {
324 recomputeEventsPeriodLocked(handle);
325 }
326 return err;
327}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700328
Mathias Agopiand8653512010-07-21 15:59:50 -0700329status_t SensorService::recomputeEventsPeriodLocked(int32_t handle)
330{
331 status_t err = NO_ERROR;
332 nsecs_t wanted = ms2ns(1000);
333 size_t count = mActiveConnections.size();
334 for (size_t i=0 ; i<count ; i++) {
335 sp<SensorEventConnection> connection(mActiveConnections[i].promote());
336 if (connection != NULL) {
337 nsecs_t ns = connection->getEventRateForSensor(handle);
338 if (ns) {
339 wanted = wanted < ns ? wanted : ns;
340 }
341 }
342 }
343 err = mSensorDevice->setDelay(mSensorDevice, handle, wanted);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700344 return err;
345}
346
347// ---------------------------------------------------------------------------
348
349SensorService::SensorRecord::SensorRecord(
350 const sp<SensorEventConnection>& connection)
351{
352 mConnections.add(connection);
353}
354
Mathias Agopiand8653512010-07-21 15:59:50 -0700355bool SensorService::SensorRecord::addConnection(
Mathias Agopian1bf79782010-07-14 23:41:37 -0700356 const sp<SensorEventConnection>& connection)
357{
358 if (mConnections.indexOf(connection) < 0) {
359 mConnections.add(connection);
Mathias Agopiand8653512010-07-21 15:59:50 -0700360 return true;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700361 }
Mathias Agopiand8653512010-07-21 15:59:50 -0700362 return false;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700363}
364
365bool SensorService::SensorRecord::removeConnection(
366 const wp<SensorEventConnection>& connection)
367{
368 ssize_t index = mConnections.indexOf(connection);
369 if (index >= 0) {
370 mConnections.removeItemsAt(index, 1);
371 }
372 return mConnections.size() ? false : true;
373}
374
375// ---------------------------------------------------------------------------
376
377SensorService::SensorEventConnection::SensorEventConnection(
378 const sp<SensorService>& service)
379 : mService(service), mChannel(new SensorChannel())
380{
381}
382
383SensorService::SensorEventConnection::~SensorEventConnection()
384{
385 mService->cleanupConnection(this);
386}
387
388void SensorService::SensorEventConnection::onFirstRef()
389{
390}
391
Mathias Agopiand8653512010-07-21 15:59:50 -0700392bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
393 if (mSensorInfo.indexOfKey(handle) <= 0) {
394 SensorInfo info;
395 mSensorInfo.add(handle, info);
396 return true;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700397 }
Mathias Agopiand8653512010-07-21 15:59:50 -0700398 return false;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700399}
400
Mathias Agopiand8653512010-07-21 15:59:50 -0700401bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
402 if (mSensorInfo.removeItem(handle) >= 0) {
403 return true;
404 }
405 return false;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700406}
407
408bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
Mathias Agopiand8653512010-07-21 15:59:50 -0700409 return mSensorInfo.indexOfKey(handle) >= 0;
Mathias Agopian1bf79782010-07-14 23:41:37 -0700410}
411
412bool SensorService::SensorEventConnection::hasAnySensor() const {
Mathias Agopiand8653512010-07-21 15:59:50 -0700413 return mSensorInfo.size() ? true : false;
414}
415
416status_t SensorService::SensorEventConnection::setEventRateLocked(
417 int handle, nsecs_t ns)
418{
419 ssize_t index = mSensorInfo.indexOfKey(handle);
420 if (index >= 0) {
421 SensorInfo& info = mSensorInfo.editValueFor(handle);
422 info.ns = ns;
423 return NO_ERROR;
424 }
425 return status_t(index);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700426}
427
428status_t SensorService::SensorEventConnection::sendEvents(
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700429 sensors_event_t const* buffer, size_t numEvents,
430 sensors_event_t* scratch)
Mathias Agopian1bf79782010-07-14 23:41:37 -0700431{
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700432 // filter out events not for this connection
433 size_t count=0, i=0;
434 while (i<numEvents) {
435 const int32_t curr = buffer[i].sensor;
436 if (mSensorInfo.indexOfKey(curr) >= 0) {
437 do {
438 scratch[count++] = buffer[i++];
439 } while ((i<numEvents) && (buffer[i].sensor == curr));
440 } else {
441 i++;
442 }
443 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700444
Mathias Agopianefba8bf2010-07-22 16:18:10 -0700445 ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t));
Mathias Agopian1bf79782010-07-14 23:41:37 -0700446 if (size == -EAGAIN) {
447 // the destination doesn't accept events anymore, it's probably
448 // full. For now, we just drop the events on the floor.
449 LOGW("dropping %d events on the floor", count);
450 return size;
451 }
452
453 LOGE_IF(size<0, "dropping %d events on the floor (%s)",
454 count, strerror(-size));
455
456 return size < 0 ? size : NO_ERROR;
457}
458
459sp<SensorChannel> SensorService::SensorEventConnection::getSensorChannel() const
460{
461 return mChannel;
462}
463
464status_t SensorService::SensorEventConnection::enableDisable(
465 int handle, bool enabled)
466{
467 status_t err;
468 if (enabled) {
469 err = mService->enable(this, handle);
470 } else {
471 err = mService->disable(this, handle);
472 }
473 return err;
474}
475
476status_t SensorService::SensorEventConnection::setEventRate(
477 int handle, nsecs_t ns)
478{
Mathias Agopiand8653512010-07-21 15:59:50 -0700479 return mService->setEventRate(this, handle, ns);
Mathias Agopian1bf79782010-07-14 23:41:37 -0700480}
481
482// ---------------------------------------------------------------------------
483}; // namespace android
484