blob: 7fcab4cf72770ea5cb1fbb0048b329f8aaaa0b5e [file] [log] [blame]
Mathias Agopianfc328812010-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 Agopian451beee2010-07-19 15:03:55 -070026#include <utils/Singleton.h>
Mathias Agopianfc328812010-07-14 23:41:37 -070027
28#include <binder/BinderService.h>
Mathias Agopian451beee2010-07-19 15:03:55 -070029#include <binder/IServiceManager.h>
Mathias Agopianfc328812010-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 Agopian451beee2010-07-19 15:03:55 -070043 * - send sensor info to battery service
Mathias Agopian3560fb22010-07-22 21:24:39 -070044 *
45
46static final int TRANSACTION_noteStartSensor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
47static final int TRANSACTION_noteStopSensor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
48
49 _data.writeInterfaceToken(DESCRIPTOR);
50 _data.writeInt(uid);
51 _data.writeInt(sensor);
52 mRemote.transact(Stub.TRANSACTION_noteStartSensor, _data, _reply, 0);
53 _reply.readException();
54 *
Mathias Agopianfc328812010-07-14 23:41:37 -070055 */
56
Mathias Agopian451beee2010-07-19 15:03:55 -070057// ---------------------------------------------------------------------------
58
59class BatteryService : public Singleton<BatteryService> {
60 friend class Singleton<BatteryService>;
61 sp<IBinder> mBatteryStatService;
62 BatteryService() {
63 const String16 name("batteryinfo");
64 //getService(name, &mBatteryStatService);
65 }
66public:
67 void enableSensor(int handle) {
68 if (mBatteryStatService != 0) {
69 int uid = IPCThreadState::self()->getCallingUid();
70 //mBatteryStatService->noteStartSensor(uid, handle);
71 }
72 }
73 void disableSensor(int handle) {
74 if (mBatteryStatService != 0) {
75 int uid = IPCThreadState::self()->getCallingUid();
76 //mBatteryStatService->noteStopSensor(uid, handle);
77 }
78 }
79};
80
81ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
82
83// ---------------------------------------------------------------------------
84
Mathias Agopian1cd70002010-07-21 15:59:50 -070085// 100 events/s max
86static const nsecs_t MINIMUM_EVENT_PERIOD = ms2ns(10);
87
Mathias Agopianfc328812010-07-14 23:41:37 -070088SensorService::SensorService()
89 : Thread(false),
Mathias Agopian50df2952010-07-19 19:09:10 -070090 mSensorDevice(0),
91 mSensorModule(0),
92 mDump("android.permission.DUMP"),
93 mInitCheck(NO_INIT)
Mathias Agopianfc328812010-07-14 23:41:37 -070094{
95}
96
97void SensorService::onFirstRef()
98{
Mathias Agopian50df2952010-07-19 19:09:10 -070099 LOGD("nuSensorService starting...");
100
Mathias Agopianfc328812010-07-14 23:41:37 -0700101 status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
102 (hw_module_t const**)&mSensorModule);
103
104 LOGE_IF(err, "couldn't load %s module (%s)",
105 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
106
Mathias Agopian50df2952010-07-19 19:09:10 -0700107 if (mSensorModule) {
108 err = sensors_open(&mSensorModule->common, &mSensorDevice);
Mathias Agopianfc328812010-07-14 23:41:37 -0700109
Mathias Agopian50df2952010-07-19 19:09:10 -0700110 LOGE_IF(err, "couldn't open device for module %s (%s)",
111 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
Mathias Agopianfc328812010-07-14 23:41:37 -0700112
Mathias Agopian3560fb22010-07-22 21:24:39 -0700113 sensors_event_t event;
114 memset(&event, 0, sizeof(event));
115
Mathias Agopian50df2952010-07-19 19:09:10 -0700116 struct sensor_t const* list;
117 int count = mSensorModule->get_sensors_list(mSensorModule, &list);
Mathias Agopian3560fb22010-07-22 21:24:39 -0700118 mLastEventSeen.setCapacity(count);
Mathias Agopian50df2952010-07-19 19:09:10 -0700119 for (int i=0 ; i<count ; i++) {
120 Sensor sensor(list + i);
121 LOGI("%s", sensor.getName().string());
122 mSensorList.add(sensor);
123 if (mSensorDevice) {
124 mSensorDevice->activate(mSensorDevice, sensor.getHandle(), 0);
125 }
Mathias Agopian3560fb22010-07-22 21:24:39 -0700126 mLastEventSeen.add(sensor.getHandle(), event);
Mathias Agopian50df2952010-07-19 19:09:10 -0700127 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700128
Mathias Agopian50df2952010-07-19 19:09:10 -0700129 if (mSensorDevice) {
130 run("SensorService", PRIORITY_URGENT_DISPLAY);
131 mInitCheck = NO_ERROR;
132 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700133 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700134}
135
136SensorService::~SensorService()
137{
138}
139
140status_t SensorService::dump(int fd, const Vector<String16>& args)
141{
142 const size_t SIZE = 1024;
143 char buffer[SIZE];
144 String8 result;
145 if (!mDump.checkCalling()) {
146 snprintf(buffer, SIZE, "Permission Denial: "
147 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
148 IPCThreadState::self()->getCallingPid(),
149 IPCThreadState::self()->getCallingUid());
150 result.append(buffer);
151 } else {
152 Mutex::Autolock _l(mLock);
Mathias Agopian3560fb22010-07-22 21:24:39 -0700153 snprintf(buffer, SIZE, "Sensor List:\n");
154 result.append(buffer);
155 for (size_t i=0 ; i<mSensorList.size() ; i++) {
156 const Sensor& s(mSensorList[i]);
157 const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
158 snprintf(buffer, SIZE, "%s (vendor=%s, handle=%d, last=<%5.1f,%5.1f,%5.1f>)\n",
159 s.getName().string(),
160 s.getVendor().string(),
161 s.getHandle(),
162 e.data[0], e.data[1], e.data[2]);
163 result.append(buffer);
164 }
165
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700166 snprintf(buffer, SIZE, "%d active connections\n",
167 mActiveConnections.size());
Mathias Agopianfc328812010-07-14 23:41:37 -0700168 result.append(buffer);
169 snprintf(buffer, SIZE, "Active sensors:\n");
170 result.append(buffer);
171 for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
Mathias Agopian5d270722010-07-19 15:20:39 -0700172 int handle = mActiveSensors.keyAt(i);
173 snprintf(buffer, SIZE, "%s (handle=%d, connections=%d)\n",
174 getSensorName(handle).string(),
175 handle,
Mathias Agopianfc328812010-07-14 23:41:37 -0700176 mActiveSensors.valueAt(i)->getNumConnections());
177 result.append(buffer);
178 }
179 }
180 write(fd, result.string(), result.size());
181 return NO_ERROR;
182}
183
184bool SensorService::threadLoop()
185{
186 LOGD("nuSensorService thread starting...");
187
188 sensors_event_t buffer[16];
Mathias Agopiancf510012010-07-22 16:18:10 -0700189 sensors_event_t scratch[16];
Mathias Agopianfc328812010-07-14 23:41:37 -0700190 struct sensors_poll_device_t* device = mSensorDevice;
191 ssize_t count;
192
193 do {
194 count = device->poll(device, buffer, sizeof(buffer)/sizeof(*buffer));
195 if (count<0) {
196 LOGE("sensor poll failed (%s)", strerror(-count));
197 break;
198 }
199
200 const SortedVector< wp<SensorEventConnection> > activeConnections(
201 getActiveConnections());
202
203 size_t numConnections = activeConnections.size();
204 if (numConnections) {
Mathias Agopiancf510012010-07-22 16:18:10 -0700205 Mutex::Autolock _l(mLock);
Mathias Agopian3560fb22010-07-22 21:24:39 -0700206
207 // record the last event for each sensor
208 int32_t prev = buffer[0].sensor;
209 for (ssize_t i=1 ; i<count ; i++) {
210 // record the last event of each sensor type in this buffer
211 int32_t curr = buffer[i].sensor;
212 if (curr != prev) {
213 mLastEventSeen.editValueFor(prev) = buffer[i-1];
214 prev = curr;
215 }
216 }
217 mLastEventSeen.editValueFor(prev) = buffer[count-1];
218
Mathias Agopianfc328812010-07-14 23:41:37 -0700219 for (size_t i=0 ; i<numConnections ; i++) {
220 sp<SensorEventConnection> connection(activeConnections[i].promote());
221 if (connection != 0) {
Mathias Agopiancf510012010-07-22 16:18:10 -0700222 connection->sendEvents(buffer, count, scratch);
Mathias Agopianfc328812010-07-14 23:41:37 -0700223 }
224 }
225 }
226
227 } while (count >= 0 || Thread::exitPending());
228
229 LOGW("Exiting SensorService::threadLoop!");
230 return false;
231}
232
233SortedVector< wp<SensorService::SensorEventConnection> >
234SensorService::getActiveConnections() const
235{
236 Mutex::Autolock _l(mLock);
237 return mActiveConnections;
238}
239
Mathias Agopian5d270722010-07-19 15:20:39 -0700240String8 SensorService::getSensorName(int handle) const {
241 size_t count = mSensorList.size();
242 for (size_t i=0 ; i<count ; i++) {
243 const Sensor& sensor(mSensorList[i]);
244 if (sensor.getHandle() == handle) {
245 return sensor.getName();
246 }
247 }
248 String8 result("unknown");
249 return result;
250}
251
Mathias Agopianfc328812010-07-14 23:41:37 -0700252Vector<Sensor> SensorService::getSensorList()
253{
254 return mSensorList;
255}
256
257sp<ISensorEventConnection> SensorService::createSensorEventConnection()
258{
259 sp<SensorEventConnection> result(new SensorEventConnection(this));
Mathias Agopianfc328812010-07-14 23:41:37 -0700260 return result;
261}
262
263void SensorService::cleanupConnection(const wp<SensorEventConnection>& connection)
264{
265 Mutex::Autolock _l(mLock);
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700266 size_t size = mActiveSensors.size();
267 for (size_t i=0 ; i<size ; ) {
268 SensorRecord* rec = mActiveSensors.valueAt(i);
269 if (rec && rec->removeConnection(connection)) {
270 mSensorDevice->activate(mSensorDevice, mActiveSensors.keyAt(i), 0);
271 mActiveSensors.removeItemsAt(i, 1);
272 delete rec;
273 size--;
274 } else {
275 i++;
Mathias Agopianfc328812010-07-14 23:41:37 -0700276 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700277 }
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700278 mActiveConnections.remove(connection);
Mathias Agopianfc328812010-07-14 23:41:37 -0700279}
280
281status_t SensorService::enable(const sp<SensorEventConnection>& connection,
282 int handle)
283{
Mathias Agopian50df2952010-07-19 19:09:10 -0700284 if (mInitCheck != NO_ERROR)
285 return mInitCheck;
286
Mathias Agopianfc328812010-07-14 23:41:37 -0700287 status_t err = NO_ERROR;
288 Mutex::Autolock _l(mLock);
289 SensorRecord* rec = mActiveSensors.valueFor(handle);
290 if (rec == 0) {
291 rec = new SensorRecord(connection);
292 mActiveSensors.add(handle, rec);
293 err = mSensorDevice->activate(mSensorDevice, handle, 1);
294 LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
Mathias Agopian451beee2010-07-19 15:03:55 -0700295 if (err == 0) {
296 BatteryService::getInstance().enableSensor(handle);
297 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700298 } else {
Mathias Agopian3560fb22010-07-22 21:24:39 -0700299 if (rec->addConnection(connection)) {
300 // this sensor is already activated, but we are adding a
301 // connection that uses it. Immediately send down the last
302 // known value of the requested sensor.
303 sensors_event_t scratch;
304 sensors_event_t& event(mLastEventSeen.editValueFor(handle));
305 if (event.version == sizeof(sensors_event_t)) {
306 connection->sendEvents(&event, 1);
307 }
308 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700309 }
310 if (err == NO_ERROR) {
311 // connection now active
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700312 if (connection->addSensor(handle)) {
313 // the sensor was added (which means it wasn't already there)
314 // so, see if this connection becomes active
315 if (mActiveConnections.indexOf(connection) < 0) {
316 mActiveConnections.add(connection);
317 }
318 // this could change the sensor event delivery speed
319 recomputeEventsPeriodLocked(handle);
Mathias Agopianfc328812010-07-14 23:41:37 -0700320 }
321 }
322 return err;
323}
324
325status_t SensorService::disable(const sp<SensorEventConnection>& connection,
326 int handle)
327{
Mathias Agopian50df2952010-07-19 19:09:10 -0700328 if (mInitCheck != NO_ERROR)
329 return mInitCheck;
330
Mathias Agopianfc328812010-07-14 23:41:37 -0700331 status_t err = NO_ERROR;
332 Mutex::Autolock _l(mLock);
333 SensorRecord* rec = mActiveSensors.valueFor(handle);
Mathias Agopianfc328812010-07-14 23:41:37 -0700334 if (rec) {
335 // see if this connection becomes inactive
336 connection->removeSensor(handle);
337 if (connection->hasAnySensor() == false) {
338 mActiveConnections.remove(connection);
339 }
340 // see if this sensor becomes inactive
341 if (rec->removeConnection(connection)) {
342 mActiveSensors.removeItem(handle);
343 delete rec;
344 err = mSensorDevice->activate(mSensorDevice, handle, 0);
Mathias Agopian451beee2010-07-19 15:03:55 -0700345 if (err == 0) {
346 BatteryService::getInstance().disableSensor(handle);
347 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700348 }
349 }
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700350 if (err == NO_ERROR) {
351 recomputeEventsPeriodLocked(handle);
352 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700353 return err;
354}
355
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700356status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
Mathias Agopianfc328812010-07-14 23:41:37 -0700357 int handle, nsecs_t ns)
358{
Mathias Agopian50df2952010-07-19 19:09:10 -0700359 if (mInitCheck != NO_ERROR)
360 return mInitCheck;
361
Mathias Agopian1cd70002010-07-21 15:59:50 -0700362 if (ns < 0)
363 return BAD_VALUE;
364
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700365 if (ns < MINIMUM_EVENTS_PERIOD)
366 ns = MINIMUM_EVENTS_PERIOD;
Mathias Agopian1cd70002010-07-21 15:59:50 -0700367
Mathias Agopianfc328812010-07-14 23:41:37 -0700368 Mutex::Autolock _l(mLock);
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700369 status_t err = connection->setEventRateLocked(handle, ns);
370 if (err == NO_ERROR) {
371 recomputeEventsPeriodLocked(handle);
372 }
373 return err;
374}
Mathias Agopianfc328812010-07-14 23:41:37 -0700375
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700376status_t SensorService::recomputeEventsPeriodLocked(int32_t handle)
377{
378 status_t err = NO_ERROR;
379 nsecs_t wanted = ms2ns(1000);
380 size_t count = mActiveConnections.size();
381 for (size_t i=0 ; i<count ; i++) {
382 sp<SensorEventConnection> connection(mActiveConnections[i].promote());
383 if (connection != NULL) {
384 nsecs_t ns = connection->getEventRateForSensor(handle);
385 if (ns) {
386 wanted = wanted < ns ? wanted : ns;
387 }
388 }
389 }
390 err = mSensorDevice->setDelay(mSensorDevice, handle, wanted);
Mathias Agopianfc328812010-07-14 23:41:37 -0700391 return err;
392}
393
394// ---------------------------------------------------------------------------
395
396SensorService::SensorRecord::SensorRecord(
397 const sp<SensorEventConnection>& connection)
398{
399 mConnections.add(connection);
400}
401
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700402bool SensorService::SensorRecord::addConnection(
Mathias Agopianfc328812010-07-14 23:41:37 -0700403 const sp<SensorEventConnection>& connection)
404{
405 if (mConnections.indexOf(connection) < 0) {
406 mConnections.add(connection);
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700407 return true;
Mathias Agopianfc328812010-07-14 23:41:37 -0700408 }
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700409 return false;
Mathias Agopianfc328812010-07-14 23:41:37 -0700410}
411
412bool SensorService::SensorRecord::removeConnection(
413 const wp<SensorEventConnection>& connection)
414{
415 ssize_t index = mConnections.indexOf(connection);
416 if (index >= 0) {
417 mConnections.removeItemsAt(index, 1);
418 }
419 return mConnections.size() ? false : true;
420}
421
422// ---------------------------------------------------------------------------
423
424SensorService::SensorEventConnection::SensorEventConnection(
425 const sp<SensorService>& service)
426 : mService(service), mChannel(new SensorChannel())
427{
428}
429
430SensorService::SensorEventConnection::~SensorEventConnection()
431{
432 mService->cleanupConnection(this);
433}
434
435void SensorService::SensorEventConnection::onFirstRef()
436{
437}
438
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700439bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
440 if (mSensorInfo.indexOfKey(handle) <= 0) {
441 SensorInfo info;
442 mSensorInfo.add(handle, info);
443 return true;
Mathias Agopianfc328812010-07-14 23:41:37 -0700444 }
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700445 return false;
Mathias Agopianfc328812010-07-14 23:41:37 -0700446}
447
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700448bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
449 if (mSensorInfo.removeItem(handle) >= 0) {
450 return true;
451 }
452 return false;
Mathias Agopianfc328812010-07-14 23:41:37 -0700453}
454
455bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700456 return mSensorInfo.indexOfKey(handle) >= 0;
Mathias Agopianfc328812010-07-14 23:41:37 -0700457}
458
459bool SensorService::SensorEventConnection::hasAnySensor() const {
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700460 return mSensorInfo.size() ? true : false;
461}
462
463status_t SensorService::SensorEventConnection::setEventRateLocked(
464 int handle, nsecs_t ns)
465{
466 ssize_t index = mSensorInfo.indexOfKey(handle);
467 if (index >= 0) {
468 SensorInfo& info = mSensorInfo.editValueFor(handle);
469 info.ns = ns;
470 return NO_ERROR;
471 }
472 return status_t(index);
Mathias Agopianfc328812010-07-14 23:41:37 -0700473}
474
475status_t SensorService::SensorEventConnection::sendEvents(
Mathias Agopiancf510012010-07-22 16:18:10 -0700476 sensors_event_t const* buffer, size_t numEvents,
477 sensors_event_t* scratch)
Mathias Agopianfc328812010-07-14 23:41:37 -0700478{
Mathias Agopiancf510012010-07-22 16:18:10 -0700479 // filter out events not for this connection
Mathias Agopian3560fb22010-07-22 21:24:39 -0700480 size_t count = 0;
481 if (scratch) {
482 size_t i=0;
483 while (i<numEvents) {
484 const int32_t curr = buffer[i].sensor;
485 if (mSensorInfo.indexOfKey(curr) >= 0) {
486 do {
487 scratch[count++] = buffer[i++];
488 } while ((i<numEvents) && (buffer[i].sensor == curr));
489 } else {
490 i++;
491 }
Mathias Agopiancf510012010-07-22 16:18:10 -0700492 }
Mathias Agopian3560fb22010-07-22 21:24:39 -0700493 } else {
494 scratch = const_cast<sensors_event_t *>(buffer);
495 count = numEvents;
Mathias Agopiancf510012010-07-22 16:18:10 -0700496 }
Mathias Agopianfc328812010-07-14 23:41:37 -0700497
Mathias Agopian3560fb22010-07-22 21:24:39 -0700498 if (count == 0)
499 return 0;
500
Mathias Agopiancf510012010-07-22 16:18:10 -0700501 ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t));
Mathias Agopianfc328812010-07-14 23:41:37 -0700502 if (size == -EAGAIN) {
503 // the destination doesn't accept events anymore, it's probably
504 // full. For now, we just drop the events on the floor.
505 LOGW("dropping %d events on the floor", count);
506 return size;
507 }
508
509 LOGE_IF(size<0, "dropping %d events on the floor (%s)",
510 count, strerror(-size));
511
512 return size < 0 ? size : NO_ERROR;
513}
514
515sp<SensorChannel> SensorService::SensorEventConnection::getSensorChannel() const
516{
517 return mChannel;
518}
519
520status_t SensorService::SensorEventConnection::enableDisable(
521 int handle, bool enabled)
522{
523 status_t err;
524 if (enabled) {
525 err = mService->enable(this, handle);
526 } else {
527 err = mService->disable(this, handle);
528 }
529 return err;
530}
531
532status_t SensorService::SensorEventConnection::setEventRate(
533 int handle, nsecs_t ns)
534{
Mathias Agopian7c1c5312010-07-21 15:59:50 -0700535 return mService->setEventRate(this, handle, ns);
Mathias Agopianfc328812010-07-14 23:41:37 -0700536}
537
538// ---------------------------------------------------------------------------
539}; // namespace android
540