blob: 7575ebd19d4ce642aa2eba72bac562733275b67b [file] [log] [blame]
Mathias Agopian671a6ff2010-11-11 17:58:51 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18#include <math.h>
19#include <sys/types.h>
20
21#include <utils/Atomic.h>
22#include <utils/Errors.h>
23#include <utils/Singleton.h>
24
25#include <binder/BinderService.h>
26#include <binder/Parcel.h>
27#include <binder/IServiceManager.h>
28
29#include <hardware/sensors.h>
30
31#include "SensorDevice.h"
Mathias Agopian9ff73de2011-05-27 16:23:58 -070032#include "SensorService.h"
Mathias Agopian671a6ff2010-11-11 17:58:51 -080033
34namespace android {
35// ---------------------------------------------------------------------------
36class BatteryService : public Singleton<BatteryService> {
37 static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3;
38 static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4;
39 static const String16 DESCRIPTOR;
40
41 friend class Singleton<BatteryService>;
42 sp<IBinder> mBatteryStatService;
43
44 BatteryService() {
45 const sp<IServiceManager> sm(defaultServiceManager());
46 if (sm != NULL) {
47 const String16 name("batteryinfo");
48 mBatteryStatService = sm->getService(name);
49 }
50 }
51
52 status_t noteStartSensor(int uid, int handle) {
53 Parcel data, reply;
54 data.writeInterfaceToken(DESCRIPTOR);
55 data.writeInt32(uid);
56 data.writeInt32(handle);
57 status_t err = mBatteryStatService->transact(
58 TRANSACTION_noteStartSensor, data, &reply, 0);
59 err = reply.readExceptionCode();
60 return err;
61 }
62
63 status_t noteStopSensor(int uid, int handle) {
64 Parcel data, reply;
65 data.writeInterfaceToken(DESCRIPTOR);
66 data.writeInt32(uid);
67 data.writeInt32(handle);
68 status_t err = mBatteryStatService->transact(
69 TRANSACTION_noteStopSensor, data, &reply, 0);
70 err = reply.readExceptionCode();
71 return err;
72 }
73
74public:
75 void enableSensor(int handle) {
76 if (mBatteryStatService != 0) {
77 int uid = IPCThreadState::self()->getCallingUid();
78 int64_t identity = IPCThreadState::self()->clearCallingIdentity();
79 noteStartSensor(uid, handle);
80 IPCThreadState::self()->restoreCallingIdentity(identity);
81 }
82 }
83 void disableSensor(int handle) {
84 if (mBatteryStatService != 0) {
85 int uid = IPCThreadState::self()->getCallingUid();
86 int64_t identity = IPCThreadState::self()->clearCallingIdentity();
87 noteStopSensor(uid, handle);
88 IPCThreadState::self()->restoreCallingIdentity(identity);
89 }
90 }
91};
92
93const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats");
94
95ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
96
97// ---------------------------------------------------------------------------
98
99ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
100
101SensorDevice::SensorDevice()
102 : mSensorDevice(0),
103 mSensorModule(0)
104{
105 status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
106 (hw_module_t const**)&mSensorModule);
107
108 LOGE_IF(err, "couldn't load %s module (%s)",
109 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
110
111 if (mSensorModule) {
112 err = sensors_open(&mSensorModule->common, &mSensorDevice);
113
114 LOGE_IF(err, "couldn't open device for module %s (%s)",
115 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
116
117 if (mSensorDevice) {
118 sensor_t const* list;
119 ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
120 mActivationCount.setCapacity(count);
121 Info model;
122 for (size_t i=0 ; i<size_t(count) ; i++) {
123 mActivationCount.add(list[i].handle, model);
124 mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
125 }
126 }
127 }
128}
129
130void SensorDevice::dump(String8& result, char* buffer, size_t SIZE)
131{
132 if (!mSensorModule) return;
133 sensor_t const* list;
134 ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
135
136 snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count));
137 result.append(buffer);
138
139 Mutex::Autolock _l(mLock);
140 for (size_t i=0 ; i<size_t(count) ; i++) {
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700141 const Info& info = mActivationCount.valueFor(list[i].handle);
142 snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ",
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800143 list[i].handle,
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700144 info.rates.size());
145 result.append(buffer);
146 for (size_t j=0 ; j<info.rates.size() ; j++) {
147 snprintf(buffer, SIZE, "%4.1f%s",
148 info.rates.valueAt(j) / 1e6f,
149 j<info.rates.size()-1 ? ", " : "");
150 result.append(buffer);
151 }
152 snprintf(buffer, SIZE, " }, selected=%4.1f ms\n", info.delay / 1e6f);
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800153 result.append(buffer);
154 }
155}
156
157ssize_t SensorDevice::getSensorList(sensor_t const** list) {
158 if (!mSensorModule) return NO_INIT;
159 ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
160 return count;
161}
162
163status_t SensorDevice::initCheck() const {
164 return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
165}
166
167ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
168 if (!mSensorDevice) return NO_INIT;
Mathias Agopian37d95f62011-11-09 17:50:15 -0800169 ssize_t c;
170 do {
171 c = mSensorDevice->poll(mSensorDevice, buffer, count);
172 } while (c == -EINTR);
173 return c;
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800174}
175
176status_t SensorDevice::activate(void* ident, int handle, int enabled)
177{
178 if (!mSensorDevice) return NO_INIT;
179 status_t err(NO_ERROR);
180 bool actuateHardware = false;
181
182 Info& info( mActivationCount.editValueFor(handle) );
Mathias Agopian9ff73de2011-05-27 16:23:58 -0700183
184
185 LOGD_IF(DEBUG_CONNECTIONS,
186 "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
187 ident, handle, enabled, info.rates.size());
188
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800189 if (enabled) {
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800190 Mutex::Autolock _l(mLock);
Mathias Agopian9ff73de2011-05-27 16:23:58 -0700191 LOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
192 info.rates.indexOfKey(ident));
193
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800194 if (info.rates.indexOfKey(ident) < 0) {
195 info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
Mathias Agopian9ff73de2011-05-27 16:23:58 -0700196 if (info.rates.size() == 1) {
197 actuateHardware = true;
198 }
Mathias Agopianb483d5c2010-11-29 17:26:51 -0800199 } else {
200 // sensor was already activated for this ident
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800201 }
202 } else {
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800203 Mutex::Autolock _l(mLock);
Mathias Agopian9ff73de2011-05-27 16:23:58 -0700204 LOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
205 info.rates.indexOfKey(ident));
206
207 ssize_t idx = info.rates.removeItem(ident);
208 if (idx >= 0) {
Mathias Agopianb483d5c2010-11-29 17:26:51 -0800209 if (info.rates.size() == 0) {
210 actuateHardware = true;
211 }
212 } else {
213 // sensor wasn't enabled for this ident
214 }
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800215 }
Mathias Agopianb483d5c2010-11-29 17:26:51 -0800216
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800217 if (actuateHardware) {
Mathias Agopian9ff73de2011-05-27 16:23:58 -0700218 LOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w");
219
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800220 err = mSensorDevice->activate(mSensorDevice, handle, enabled);
221 if (enabled) {
222 LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
223 if (err == 0) {
224 BatteryService::getInstance().enableSensor(handle);
225 }
226 } else {
227 if (err == 0) {
228 BatteryService::getInstance().disableSensor(handle);
229 }
230 }
231 }
232
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700233 { // scope for the lock
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800234 Mutex::Autolock _l(mLock);
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700235 nsecs_t ns = info.selectDelay();
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800236 mSensorDevice->setDelay(mSensorDevice, handle, ns);
237 }
238
239 return err;
240}
241
242status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
243{
244 if (!mSensorDevice) return NO_INIT;
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700245 Mutex::Autolock _l(mLock);
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800246 Info& info( mActivationCount.editValueFor(handle) );
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700247 status_t err = info.setDelayForIdent(ident, ns);
248 if (err < 0) return err;
249 ns = info.selectDelay();
250 return mSensorDevice->setDelay(mSensorDevice, handle, ns);
251}
252
253// ---------------------------------------------------------------------------
254
255status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
256{
257 ssize_t index = rates.indexOfKey(ident);
258 if (index < 0) {
259 LOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
260 ident, ns, strerror(-index));
261 return BAD_INDEX;
262 }
263 rates.editValueAt(index) = ns;
264 return NO_ERROR;
265}
266
267nsecs_t SensorDevice::Info::selectDelay()
268{
269 nsecs_t ns = rates.valueAt(0);
270 for (size_t i=1 ; i<rates.size() ; i++) {
271 nsecs_t cur = rates.valueAt(i);
272 if (cur < ns) {
273 ns = cur;
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800274 }
275 }
Mathias Agopian6f4f8e72011-09-14 16:43:34 -0700276 delay = ns;
277 return ns;
Mathias Agopian671a6ff2010-11-11 17:58:51 -0800278}
279
280// ---------------------------------------------------------------------------
281}; // namespace android
282