summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Android Automerger <android-build@android.com>2010-11-18 20:17:46 -0800
committerThe Android Automerger <android-build@android.com>2010-11-18 20:17:46 -0800
commit6471cd5f7d0125713081c9be4772922eedd2a904 (patch)
tree569c08c41c6c810c99395279283f6e1c812fc51d
parentff03f237f9194d5ba3b9af520efa8b27d3266554 (diff)
parent671a6ff4be11b3e2d8eb017e0c7a78e6133fb2b8 (diff)
downloadbase-6471cd5f7d0125713081c9be4772922eedd2a904.tar.gz
Merge branch 'gingerbread' into gingerbread-releaseandroid-2.3_r1
-rw-r--r--[-rwxr-xr-x]data/sounds/ringtones/Carina.oggbin15478 -> 15462 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/ringtones/Eridani.oggbin34856 -> 36585 bytes
-rw-r--r--docs/html/guide/topics/manifest/manifest-element.jd5
-rw-r--r--docs/html/guide/topics/manifest/uses-feature-element.jd76
-rw-r--r--libs/ui/InputDispatcher.cpp80
-rw-r--r--libs/ui/InputReader.cpp4
-rw-r--r--services/sensorservice/Android.mk8
-rw-r--r--services/sensorservice/GravitySensor.cpp112
-rw-r--r--services/sensorservice/GravitySensor.h56
-rw-r--r--services/sensorservice/LinearAccelerationSensor.cpp86
-rw-r--r--services/sensorservice/LinearAccelerationSensor.h53
-rw-r--r--services/sensorservice/RotationVectorSensor.cpp174
-rw-r--r--services/sensorservice/RotationVectorSensor.h60
-rw-r--r--services/sensorservice/SecondOrderLowPassFilter.cpp70
-rw-r--r--services/sensorservice/SecondOrderLowPassFilter.h61
-rw-r--r--services/sensorservice/SensorDevice.cpp239
-rw-r--r--services/sensorservice/SensorDevice.h62
-rw-r--r--services/sensorservice/SensorInterface.cpp70
-rw-r--r--services/sensorservice/SensorInterface.h75
-rw-r--r--services/sensorservice/SensorService.cpp347
-rw-r--r--services/sensorservice/SensorService.h27
21 files changed, 1404 insertions, 261 deletions
diff --git a/data/sounds/ringtones/Carina.ogg b/data/sounds/ringtones/Carina.ogg
index 25cf36e19078..aeb9b36bb6cd 100755..100644
--- a/data/sounds/ringtones/Carina.ogg
+++ b/data/sounds/ringtones/Carina.ogg
Binary files differ
diff --git a/data/sounds/ringtones/Eridani.ogg b/data/sounds/ringtones/Eridani.ogg
index a290a6e72ef1..b665a29fd4a2 100755..100644
--- a/data/sounds/ringtones/Eridani.ogg
+++ b/data/sounds/ringtones/Eridani.ogg
Binary files differ
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index a35c5a13c29a..7f21e6bbb9fb 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -159,6 +159,9 @@ multiple SD cards can be used with the same device.</li>
storage. However, the system will not allow the user to move the application to external storage if
this attribute is set to {@code internalOnly}, which is the default setting.</p>
+<p>Read <a href="{@docRoot}guide/appendix/install-location.html">App Install Location</a> for
+more information about using this attribute (including how to maintain backward compatibility).</p>
+
<p>Introduced in: API Level 8.</p>
@@ -173,7 +176,7 @@ this attribute is set to {@code internalOnly}, which is the default setting.</p>
<p>
<dt>see also:</dt>
-<dd><a href="{@docRoot}guide/appendix/install-location.html">App Install Location</a><br/>
+<dd>
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
</dl>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 45f4a66b1c4a..b5b30f632a1a 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -472,11 +472,11 @@ If you are developing in Eclipse with ADT, right-click the project and select
Package</strong>. Select a destination filename and path and click
<strong>OK</strong>. </li>
<li>Next, locate the <code>aapt</code> tool, if it is not already in your PATH.
-If you are using SDK Tools r7 or earlier, you can find <code>aapt</code> in the
-<code>&lt;<em>SDK</em>&gt;/platforms/android-&lt;<em>platform</em>&gt;/tools/</code> directory.
+If you are using SDK Tools r8 or higher, you can find <code>aapt</code> in the
+<code>&lt;<em>SDK</em>&gt;/platform-tools/</code> directory.
<p class="note"><strong>Note:</strong> You must use the version of
-<code>aapt</code> that is provided for the latest platform release available. If
-you do not have the latest platform release, download it using the <a
+<code>aapt</code> that is provided for the latest Platform-Tools component available. If
+you do not have the latest Platform-Tools component, download it using the <a
href="{@docRoot}sdk/adding-components.html">Android SDK and AVD Manager</a>.
</p></li>
<li>Run <code>aapt</code> using this syntax: </li>
@@ -522,6 +522,14 @@ in a separate <code>&lt;uses-feature&gt;</code> element. </p>
<th>Comments</th>
</tr>
<tr>
+ <td>Audio</td>
+ <td><code>android.hardware.audio.low_latency</td>
+ <td>The application uses a low-latency audio pipeline on the device and
+is sensitive to delays or lag in sound input or output.</td>
+<td>
+</td>
+ </tr>
+ <tr>
<td>Bluetooth</td>
<td><code>android.hardware.bluetooth</td>
<td>The application uses Bluetooth radio features in the device.</td>
@@ -529,7 +537,7 @@ in a separate <code>&lt;uses-feature&gt;</code> element. </p>
</td>
</tr>
<tr>
- <td rowspan="3">Camera</td>
+ <td rowspan="4">Camera</td>
<td><code>android.hardware.camera</code></td>
<td>The application uses the device's camera. If the device supports
multiple cameras, the application uses the camera that facing
@@ -539,7 +547,7 @@ in a separate <code>&lt;uses-feature&gt;</code> element. </p>
<tr>
<td><code>android.hardware.camera.autofocus</code></td>
<td>Subfeature. The application uses the device camera's autofocus capability.</td>
- <td rowspan="2">If declared with the <code>"android:required="true"</code>
+ <td rowspan="3">If declared with the <code>"android:required="true"</code>
attribute, these subfeatures implicitly declare the
<code>android.hardware.camera</code> parent feature. </td>
</tr>
@@ -547,6 +555,10 @@ attribute, these subfeatures implicitly declare the
<td><code>android.hardware.camera.flash</code></td>
<td>Subfeature. The application uses the device camera's flash.</td>
</tr>
+<tr>
+ <td><code>android.hardware.camera.front</code></td>
+ <td>Subfeature. The application uses a front-facing camera on the device.</td>
+</tr>
<tr>
<td rowspan="3">Location</td>
@@ -568,21 +580,43 @@ attribute, these subfeatures implicitly declare the
<td>Subfeature. The application uses precise location coordinates obtained
from a Global Positioning System receiver on the device. </td>
</tr>
-
<tr>
- <td rowspan="4">Sensors</td>
+ <td>Microphone</td>
+ <td><code>android.hardware.microphone</code></td>
+ <td>The application uses a microphone on the device.
+ </td>
+ <td></td>
+</tr>
+<tr>
+ <td>Near Field Communications</td>
+ <td><code>android.hardware.nfc</td>
+ <td>The application uses NFC radio features in the device.</td>
+ <td></td>
+</tr>
+<tr>
+ <td rowspan="6">Sensors</td>
<td><code>android.hardware.sensor.accelerometer</code></td>
<td>The application uses motion readings from an accelerometer on the
device.</td>
<td></td>
</tr>
<tr>
+ <td><code>android.hardware.sensor.barometer</code></td>
+ <td>The application uses the device's barometer.</td>
+ <td></td>
+</tr>
+<tr>
<td><code>android.hardware.sensor.compass</code></td>
<td>The application uses directional readings from a magnetometer (compass) on
the device.</td>
<td></td>
</tr>
<tr>
+ <td><code>android.hardware.sensor.gyroscope</code></td>
+ <td>The application uses the device's gyroscope sensor.</td>
+ <td></td>
+</tr>
+<tr>
<td><code>android.hardware.sensor.light</code></td>
<td>The application uses the device's light sensor.</td>
<td></td>
@@ -593,12 +627,20 @@ the device.</td>
<td></td>
</tr>
<tr>
- <td>Microphone</td>
- <td><code>android.hardware.microphone</code></td>
- <td>The application uses a microphone on the device.
+ <td rowspan="2">SIP/VOIP</td>
+ <td><code>android.hardware.sip</code></td>
+ <td>The application uses SIP service on the device.
</td>
<td></td>
</tr>
+<tr>
+ <td><code>android.hardware.sip.voip</code></td>
+ <td>Subfeature. The application uses SIP-based VOIP service on the device.
+ </td>
+ <td>If declared with the <code>"android:required="true"</code> attribute, this
+subfeature implicitly declares the <code>android.hardware.sip</code>
+parent feature.</td>
+</tr>
<tr>
<td rowspan="3">Telephony</td>
@@ -622,14 +664,14 @@ device.</td>
</tr>
<tr>
- <td rowspan="3">Touchscreen</td>
+ <td rowspan="4">Touchscreen</td>
<td><code>android.hardware.touchscreen</code></td>
<td>The application uses touchscreen capabilities on the device.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.touchscreen.multitouch</code></td>
- <td>The application uses basic two-point multitouch capabilities on the device
+ <td>Subfeature. The application uses basic two-point multitouch capabilities on the device
screen.</td>
<td>If declared with the <code>"android:required="true"</code> attribute, this
subfeature implicitly declares the <code>android.hardware.touchscreen</code>
@@ -640,10 +682,16 @@ parent feature. </td>
<td>Subfeature. The application uses advanced multipoint multitouch
capabilities on the device screen, such as for tracking two or more points fully
independently.</td>
- <td>If declared with the <code>"android:required="true"</code> attribute, this
+ <td rowspan="2">If declared with the <code>"android:required="true"</code> attribute, this
subfeature implicitly declares the
<code>android.hardware.touchscreen.multitouch</code> parent feature. </td>
</tr>
+<tr>
+ <td><code>android.hardware.touchscreen.multitouch.jazzhand</code></td>
+ <td>Subfeature. The application uses advanced multipoint multitouch
+capabilities on the device screen, for tracking up to five points fully
+independently.</td>
+</tr>
<tr>
<td>Wifi</td>
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index c0b27fe2cc43..28ccc43a6727 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -619,38 +619,8 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(
bool InputDispatcher::dispatchKeyLocked(
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
- // Give the policy a chance to intercept the key.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
- if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindow) {
- commandEntry->inputChannel = mFocusedWindow->inputChannel;
- }
- commandEntry->keyEntry = entry;
- entry->refCount += 1;
- return false; // wait for the command to run
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- }
- } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
- if (*dropReason == DROP_REASON_NOT_DROPPED) {
- *dropReason = DROP_REASON_POLICY;
- }
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- resetTargetsLocked();
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
// Preprocessing.
if (! entry->dispatchInProgress) {
- logOutboundKeyDetailsLocked("dispatchKey - ", entry);
-
if (entry->repeatCount == 0
&& entry->action == AKEY_EVENT_ACTION_DOWN
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
@@ -677,6 +647,36 @@ bool InputDispatcher::dispatchKeyLocked(
entry->dispatchInProgress = true;
resetTargetsLocked();
+
+ logOutboundKeyDetailsLocked("dispatchKey - ", entry);
+ }
+
+ // Give the policy a chance to intercept the key.
+ if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
+ if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
+ CommandEntry* commandEntry = postCommandLocked(
+ & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+ if (mFocusedWindow) {
+ commandEntry->inputChannel = mFocusedWindow->inputChannel;
+ }
+ commandEntry->keyEntry = entry;
+ entry->refCount += 1;
+ return false; // wait for the command to run
+ } else {
+ entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+ }
+ } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
+ if (*dropReason == DROP_REASON_NOT_DROPPED) {
+ *dropReason = DROP_REASON_POLICY;
+ }
+ }
+
+ // Clean up if dropping the event.
+ if (*dropReason != DROP_REASON_NOT_DROPPED) {
+ resetTargetsLocked();
+ setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
+ ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+ return true;
}
// Identify targets.
@@ -705,16 +705,24 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
- "downTime=%lld",
+ "repeatCount=%d, downTime=%lld",
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
- entry->downTime);
+ entry->repeatCount, entry->downTime);
#endif
}
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
+ // Preprocessing.
+ if (! entry->dispatchInProgress) {
+ entry->dispatchInProgress = true;
+ resetTargetsLocked();
+
+ logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
+ }
+
// Clean up if dropping the event.
if (*dropReason != DROP_REASON_NOT_DROPPED) {
resetTargetsLocked();
@@ -723,14 +731,6 @@ bool InputDispatcher::dispatchMotionLocked(
return true;
}
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
-
- entry->dispatchInProgress = true;
- resetTargetsLocked();
- }
-
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// Identify targets.
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index d1674390efd6..3197ab229ad7 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -934,7 +934,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
ssize_t keyDownIndex = findKeyDownLocked(scanCode);
if (keyDownIndex >= 0) {
// key repeat, be sure to use same keycode as before in case of rotation
- keyCode = mLocked.keyDowns.top().keyCode;
+ keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
} else {
// key down
mLocked.keyDowns.push();
@@ -949,7 +949,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
ssize_t keyDownIndex = findKeyDownLocked(scanCode);
if (keyDownIndex >= 0) {
// key up, be sure to use same keycode as before in case of rotation
- keyCode = mLocked.keyDowns.top().keyCode;
+ keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
mLocked.keyDowns.removeAt(size_t(keyDownIndex));
} else {
// key was not actually down
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 75f690f1867b..7e17fdd58ede 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -2,7 +2,13 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- SensorService.cpp
+ GravitySensor.cpp \
+ LinearAccelerationSensor.cpp \
+ RotationVectorSensor.cpp \
+ SensorService.cpp \
+ SensorInterface.cpp \
+ SensorDevice.cpp \
+ SecondOrderLowPassFilter.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
new file mode 100644
index 000000000000..18bd359ea27d
--- /dev/null
+++ b/services/sensorservice/GravitySensor.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <hardware/sensors.h>
+
+#include "GravitySensor.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+GravitySensor::GravitySensor(sensor_t const* list, size_t count)
+ : mSensorDevice(SensorDevice::getInstance()),
+ mEnabled(false), mAccTime(0),
+ mLowPass(M_SQRT1_2, 1),
+ mX(mLowPass), mY(mLowPass), mZ(mLowPass)
+
+{
+ for (size_t i=0 ; i<count ; i++) {
+ if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
+ mAccelerometer = Sensor(list + i);
+ break;
+ }
+ }
+}
+
+bool GravitySensor::process(sensors_event_t* outEvent,
+ const sensors_event_t& event)
+{
+ const static double NS2S = 1.0 / 1000000000.0;
+ if (event.type == SENSOR_TYPE_ACCELEROMETER) {
+ float x, y, z;
+ const double now = event.timestamp * NS2S;
+ if (mAccTime == 0) {
+ x = mX.init(event.acceleration.x);
+ y = mY.init(event.acceleration.y);
+ z = mZ.init(event.acceleration.z);
+ } else {
+ double dT = now - mAccTime;
+ mLowPass.setSamplingPeriod(dT);
+ x = mX(event.acceleration.x);
+ y = mY(event.acceleration.y);
+ z = mZ(event.acceleration.z);
+ }
+ mAccTime = now;
+ *outEvent = event;
+ outEvent->data[0] = x;
+ outEvent->data[1] = y;
+ outEvent->data[2] = z;
+ outEvent->sensor = '_grv';
+ outEvent->type = SENSOR_TYPE_GRAVITY;
+ return true;
+ }
+ return false;
+}
+
+bool GravitySensor::isEnabled() const {
+ return mEnabled;
+}
+
+status_t GravitySensor::activate(void* ident, bool enabled) {
+ status_t err = mSensorDevice.activate(this, mAccelerometer.getHandle(), enabled);
+ if (err == NO_ERROR) {
+ mEnabled = enabled;
+ if (enabled) {
+ mAccTime = 0;
+ }
+ }
+ return err;
+}
+
+status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns)
+{
+ return mSensorDevice.setDelay(this, mAccelerometer.getHandle(), ns);
+}
+
+Sensor GravitySensor::getSensor() const {
+ sensor_t hwSensor;
+ hwSensor.name = "Gravity Sensor";
+ hwSensor.vendor = "Google Inc.";
+ hwSensor.version = 1;
+ hwSensor.handle = '_grv';
+ hwSensor.type = SENSOR_TYPE_GRAVITY;
+ hwSensor.maxRange = mAccelerometer.getMaxValue();
+ hwSensor.resolution = mAccelerometer.getResolution();
+ hwSensor.power = mAccelerometer.getPowerUsage();
+ hwSensor.minDelay = mAccelerometer.getMinDelay();
+ Sensor sensor(&hwSensor);
+ return sensor;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
new file mode 100644
index 000000000000..f9850b75f34f
--- /dev/null
+++ b/services/sensorservice/GravitySensor.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GRAVITY_SENSOR_H
+#define ANDROID_GRAVITY_SENSOR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <gui/Sensor.h>
+
+#include "SensorDevice.h"
+#include "SensorInterface.h"
+#include "SecondOrderLowPassFilter.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GravitySensor : public SensorInterface {
+ SensorDevice& mSensorDevice;
+ Sensor mAccelerometer;
+ bool mEnabled;
+ double mAccTime;
+
+ SecondOrderLowPassFilter mLowPass;
+ BiquadFilter mX, mY, mZ;
+
+public:
+ GravitySensor(sensor_t const* list, size_t count);
+ virtual bool process(sensors_event_t* outEvent,
+ const sensors_event_t& event);
+ virtual bool isEnabled() const;
+ virtual status_t activate(void* ident, bool enabled);
+ virtual status_t setDelay(void* ident, int handle, int64_t ns);
+ virtual Sensor getSensor() const;
+ virtual bool isVirtual() const { return true; }
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GRAVITY_SENSOR_H
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
new file mode 100644
index 000000000000..2dc12dc50a33
--- /dev/null
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <hardware/sensors.h>
+
+#include "LinearAccelerationSensor.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
+ : mSensorDevice(SensorDevice::getInstance()),
+ mGravitySensor(list, count)
+{
+ mData[0] = mData[1] = mData[2] = 0;
+}
+
+bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
+ const sensors_event_t& event)
+{
+ bool result = mGravitySensor.process(outEvent, event);
+ if (result) {
+ if (event.type == SENSOR_TYPE_ACCELEROMETER) {
+ mData[0] = event.acceleration.x;
+ mData[1] = event.acceleration.y;
+ mData[2] = event.acceleration.z;
+ }
+ outEvent->data[0] = mData[0] - outEvent->data[0];
+ outEvent->data[1] = mData[1] - outEvent->data[1];
+ outEvent->data[2] = mData[2] - outEvent->data[2];
+ outEvent->sensor = '_lin';
+ outEvent->type = SENSOR_TYPE_LINEAR_ACCELERATION;
+ }
+ return result;
+}
+
+bool LinearAccelerationSensor::isEnabled() const {
+ return mGravitySensor.isEnabled();
+}
+
+status_t LinearAccelerationSensor::activate(void* ident, bool enabled) {
+ return mGravitySensor.activate(ident, enabled);
+}
+
+status_t LinearAccelerationSensor::setDelay(void* ident, int handle, int64_t ns) {
+ return mGravitySensor.setDelay(ident, handle, ns);
+}
+
+Sensor LinearAccelerationSensor::getSensor() const {
+ Sensor gsensor(mGravitySensor.getSensor());
+ sensor_t hwSensor;
+ hwSensor.name = "Linear Acceleration Sensor";
+ hwSensor.vendor = "Google Inc.";
+ hwSensor.version = 1;
+ hwSensor.handle = '_lin';
+ hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
+ hwSensor.maxRange = gsensor.getMaxValue();
+ hwSensor.resolution = gsensor.getResolution();
+ hwSensor.power = gsensor.getPowerUsage();
+ hwSensor.minDelay = gsensor.getMinDelay();
+ Sensor sensor(&hwSensor);
+ return sensor;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
new file mode 100644
index 000000000000..ee918ce1c471
--- /dev/null
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_LINEAR_ACCELERATION_SENSOR_H
+#define ANDROID_LINEAR_ACCELERATION_SENSOR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <gui/Sensor.h>
+
+#include "SensorDevice.h"
+#include "SensorInterface.h"
+#include "GravitySensor.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class LinearAccelerationSensor : public SensorInterface {
+ SensorDevice& mSensorDevice;
+ GravitySensor mGravitySensor;
+ float mData[3];
+
+ virtual bool process(sensors_event_t* outEvent,
+ const sensors_event_t& event);
+public:
+ LinearAccelerationSensor(sensor_t const* list, size_t count);
+ virtual bool isEnabled() const;
+ virtual status_t activate(void* ident, bool enabled);
+ virtual status_t setDelay(void* ident, int handle, int64_t ns);
+ virtual Sensor getSensor() const;
+ virtual bool isVirtual() const { return true; }
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_LINEAR_ACCELERATION_SENSOR_H
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
new file mode 100644
index 000000000000..6f4b8be45fde
--- /dev/null
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <hardware/sensors.h>
+
+#include "RotationVectorSensor.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename T>
+static inline T clamp(T v) {
+ return v < 0 ? 0 : v;
+}
+
+RotationVectorSensor::RotationVectorSensor(sensor_t const* list, size_t count)
+ : mSensorDevice(SensorDevice::getInstance()),
+ mEnabled(false),
+ mALowPass(M_SQRT1_2, 5.0f),
+ mAX(mALowPass), mAY(mALowPass), mAZ(mALowPass),
+ mMLowPass(M_SQRT1_2, 2.5f),
+ mMX(mMLowPass), mMY(mMLowPass), mMZ(mMLowPass)
+{
+ for (size_t i=0 ; i<count ; i++) {
+ if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
+ mAcc = Sensor(list + i);
+ }
+ if (list[i].type == SENSOR_TYPE_MAGNETIC_FIELD) {
+ mMag = Sensor(list + i);
+ }
+ }
+ memset(mMagData, 0, sizeof(mMagData));
+}
+
+bool RotationVectorSensor::process(sensors_event_t* outEvent,
+ const sensors_event_t& event)
+{
+ const static double NS2S = 1.0 / 1000000000.0;
+ if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
+ const double now = event.timestamp * NS2S;
+ if (mMagTime == 0) {
+ mMagData[0] = mMX.init(event.magnetic.x);
+ mMagData[1] = mMY.init(event.magnetic.y);
+ mMagData[2] = mMZ.init(event.magnetic.z);
+ } else {
+ double dT = now - mMagTime;
+ mMLowPass.setSamplingPeriod(dT);
+ mMagData[0] = mMX(event.magnetic.x);
+ mMagData[1] = mMY(event.magnetic.y);
+ mMagData[2] = mMZ(event.magnetic.z);
+ }
+ mMagTime = now;
+ }
+ if (event.type == SENSOR_TYPE_ACCELEROMETER) {
+ const double now = event.timestamp * NS2S;
+ float Ax, Ay, Az;
+ if (mAccTime == 0) {
+ Ax = mAX.init(event.acceleration.x);
+ Ay = mAY.init(event.acceleration.y);
+ Az = mAZ.init(event.acceleration.z);
+ } else {
+ double dT = now - mAccTime;
+ mALowPass.setSamplingPeriod(dT);
+ Ax = mAX(event.acceleration.x);
+ Ay = mAY(event.acceleration.y);
+ Az = mAZ(event.acceleration.z);
+ }
+ mAccTime = now;
+ const float Ex = mMagData[0];
+ const float Ey = mMagData[1];
+ const float Ez = mMagData[2];
+ float Hx = Ey*Az - Ez*Ay;
+ float Hy = Ez*Ax - Ex*Az;
+ float Hz = Ex*Ay - Ey*Ax;
+ const float normH = sqrtf(Hx*Hx + Hy*Hy + Hz*Hz);
+ if (normH < 0.1f) {
+ // device is close to free fall (or in space?), or close to
+ // magnetic north pole. Typical values are > 100.
+ return false;
+ }
+ const float invH = 1.0f / normH;
+ const float invA = 1.0f / sqrtf(Ax*Ax + Ay*Ay + Az*Az);
+ Hx *= invH;
+ Hy *= invH;
+ Hz *= invH;
+ Ax *= invA;
+ Ay *= invA;
+ Az *= invA;
+ const float Mx = Ay*Hz - Az*Hy;
+ const float My = Az*Hx - Ax*Hz;
+ const float Mz = Ax*Hy - Ay*Hx;
+
+ // matrix to rotation vector (normalized quaternion)
+ float qw = sqrtf( clamp( Hx + My + Az + 1) * 0.25f );
+ float qx = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
+ float qy = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
+ float qz = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
+ const float n = 1.0f / (qw*qw + qx*qx + qy*qy + qz*qz);
+ qx = copysignf(qx, Ay - Mz) * n;
+ qy = copysignf(qy, Hz - Ax) * n;
+ qz = copysignf(qz, Mx - Hy) * n;
+
+ *outEvent = event;
+ outEvent->data[0] = qx;
+ outEvent->data[1] = qy;
+ outEvent->data[2] = qz;
+ outEvent->sensor = '_rov';
+ outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
+ return true;
+ }
+ return false;
+}
+
+bool RotationVectorSensor::isEnabled() const {
+ return mEnabled;
+}
+
+status_t RotationVectorSensor::activate(void* ident, bool enabled) {
+ if (mEnabled != enabled) {
+ mSensorDevice.activate(this, mAcc.getHandle(), enabled);
+ mSensorDevice.activate(this, mMag.getHandle(), enabled);
+ mEnabled = enabled;
+ if (enabled) {
+ mMagTime = 0;
+ mAccTime = 0;
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t RotationVectorSensor::setDelay(void* ident, int handle, int64_t ns)
+{
+ mSensorDevice.setDelay(this, mAcc.getHandle(), ns);
+ mSensorDevice.setDelay(this, mMag.getHandle(), ns);
+ return NO_ERROR;
+}
+
+Sensor RotationVectorSensor::getSensor() const {
+ sensor_t hwSensor;
+ hwSensor.name = "Rotation Vector Sensor";
+ hwSensor.vendor = "Google Inc.";
+ hwSensor.version = 1;
+ hwSensor.handle = '_rov';
+ hwSensor.type = SENSOR_TYPE_ROTATION_VECTOR;
+ hwSensor.maxRange = 1;
+ hwSensor.resolution = 1.0f / (1<<24);
+ hwSensor.power = mAcc.getPowerUsage() + mMag.getPowerUsage();
+ hwSensor.minDelay = mAcc.getMinDelay();
+ Sensor sensor(&hwSensor);
+ return sensor;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
new file mode 100644
index 000000000000..e7f28c93a232
--- /dev/null
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ROTATION_VECTOR_SENSOR_H
+#define ANDROID_ROTATION_VECTOR_SENSOR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <gui/Sensor.h>
+
+#include "SensorDevice.h"
+#include "SensorInterface.h"
+#include "SecondOrderLowPassFilter.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class RotationVectorSensor : public SensorInterface {
+ SensorDevice& mSensorDevice;
+ Sensor mAcc;
+ Sensor mMag;
+ bool mEnabled;
+ float mMagData[3];
+ double mAccTime;
+ double mMagTime;
+ SecondOrderLowPassFilter mALowPass;
+ BiquadFilter mAX, mAY, mAZ;
+ SecondOrderLowPassFilter mMLowPass;
+ BiquadFilter mMX, mMY, mMZ;
+
+public:
+ RotationVectorSensor(sensor_t const* list, size_t count);
+ virtual bool process(sensors_event_t* outEvent,
+ const sensors_event_t& event);
+ virtual bool isEnabled() const;
+ virtual status_t activate(void* ident, bool enabled);
+ virtual status_t setDelay(void* ident, int handle, int64_t ns);
+ virtual Sensor getSensor() const;
+ virtual bool isVirtual() const { return true; }
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_ROTATION_VECTOR_SENSOR_H
diff --git a/services/sensorservice/SecondOrderLowPassFilter.cpp b/services/sensorservice/SecondOrderLowPassFilter.cpp
new file mode 100644
index 000000000000..e13e1362d6dd
--- /dev/null
+++ b/services/sensorservice/SecondOrderLowPassFilter.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <math.h>
+
+#include <cutils/log.h>
+
+#include "SecondOrderLowPassFilter.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+SecondOrderLowPassFilter::SecondOrderLowPassFilter(float Q, float fc)
+ : iQ(1.0f / Q), fc(fc)
+{
+}
+
+void SecondOrderLowPassFilter::setSamplingPeriod(float dT)
+{
+ K = tanf(float(M_PI) * fc * dT);
+ iD = 1.0f / (K*K + K*iQ + 1);
+ a0 = K*K*iD;
+ a1 = 2.0f * a0;
+ b1 = 2.0f*(K*K - 1)*iD;
+ b2 = (K*K - K*iQ + 1)*iD;
+}
+
+// ---------------------------------------------------------------------------
+
+BiquadFilter::BiquadFilter(const SecondOrderLowPassFilter& s)
+ : s(s)
+{
+}
+
+float BiquadFilter::init(float x)
+{
+ x1 = x2 = x;
+ y1 = y2 = x;
+ return x;
+}
+
+float BiquadFilter::operator()(float x)
+{
+ float y = (x + x2)*s.a0 + x1*s.a1 - y1*s.b1 - y2*s.b2;
+ x2 = x1;
+ y2 = y1;
+ x1 = x;
+ y1 = y;
+ return y;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/sensorservice/SecondOrderLowPassFilter.h b/services/sensorservice/SecondOrderLowPassFilter.h
new file mode 100644
index 000000000000..998ca35b9b66
--- /dev/null
+++ b/services/sensorservice/SecondOrderLowPassFilter.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
+#define ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class BiquadFilter;
+
+/*
+ * State of a 2nd order low-pass IIR filter
+ */
+class SecondOrderLowPassFilter {
+ friend class BiquadFilter;
+ float iQ, fc;
+ float K, iD;
+ float a0, a1;
+ float b1, b2;
+public:
+ SecondOrderLowPassFilter(float Q, float fc);
+ void setSamplingPeriod(float dT);
+};
+
+/*
+ * Implements a Biquad IIR filter
+ */
+class BiquadFilter {
+ float x1, x2;
+ float y1, y2;
+ const SecondOrderLowPassFilter& s;
+public:
+ BiquadFilter(const SecondOrderLowPassFilter& s);
+ float init(float in);
+ float operator()(float in);
+};
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
new file mode 100644
index 000000000000..73f85ba35ca1
--- /dev/null
+++ b/services/sensorservice/SensorDevice.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+
+#include <binder/BinderService.h>
+#include <binder/Parcel.h>
+#include <binder/IServiceManager.h>
+
+#include <hardware/sensors.h>
+
+#include "SensorDevice.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+class BatteryService : public Singleton<BatteryService> {
+ static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3;
+ static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4;
+ static const String16 DESCRIPTOR;
+
+ friend class Singleton<BatteryService>;
+ sp<IBinder> mBatteryStatService;
+
+ BatteryService() {
+ const sp<IServiceManager> sm(defaultServiceManager());
+ if (sm != NULL) {
+ const String16 name("batteryinfo");
+ mBatteryStatService = sm->getService(name);
+ }
+ }
+
+ status_t noteStartSensor(int uid, int handle) {
+ Parcel data, reply;
+ data.writeInterfaceToken(DESCRIPTOR);
+ data.writeInt32(uid);
+ data.writeInt32(handle);
+ status_t err = mBatteryStatService->transact(
+ TRANSACTION_noteStartSensor, data, &reply, 0);
+ err = reply.readExceptionCode();
+ return err;
+ }
+
+ status_t noteStopSensor(int uid, int handle) {
+ Parcel data, reply;
+ data.writeInterfaceToken(DESCRIPTOR);
+ data.writeInt32(uid);
+ data.writeInt32(handle);
+ status_t err = mBatteryStatService->transact(
+ TRANSACTION_noteStopSensor, data, &reply, 0);
+ err = reply.readExceptionCode();
+ return err;
+ }
+
+public:
+ void enableSensor(int handle) {
+ if (mBatteryStatService != 0) {
+ int uid = IPCThreadState::self()->getCallingUid();
+ int64_t identity = IPCThreadState::self()->clearCallingIdentity();
+ noteStartSensor(uid, handle);
+ IPCThreadState::self()->restoreCallingIdentity(identity);
+ }
+ }
+ void disableSensor(int handle) {
+ if (mBatteryStatService != 0) {
+ int uid = IPCThreadState::self()->getCallingUid();
+ int64_t identity = IPCThreadState::self()->clearCallingIdentity();
+ noteStopSensor(uid, handle);
+ IPCThreadState::self()->restoreCallingIdentity(identity);
+ }
+ }
+};
+
+const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats");
+
+ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
+
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
+
+SensorDevice::SensorDevice()
+ : mSensorDevice(0),
+ mSensorModule(0)
+{
+ status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
+ (hw_module_t const**)&mSensorModule);
+
+ LOGE_IF(err, "couldn't load %s module (%s)",
+ SENSORS_HARDWARE_MODULE_ID, strerror(-err));
+
+ if (mSensorModule) {
+ err = sensors_open(&mSensorModule->common, &mSensorDevice);
+
+ LOGE_IF(err, "couldn't open device for module %s (%s)",
+ SENSORS_HARDWARE_MODULE_ID, strerror(-err));
+
+ if (mSensorDevice) {
+ sensor_t const* list;
+ ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+ mActivationCount.setCapacity(count);
+ Info model;
+ for (size_t i=0 ; i<size_t(count) ; i++) {
+ mActivationCount.add(list[i].handle, model);
+ mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
+ }
+ }
+ }
+}
+
+void SensorDevice::dump(String8& result, char* buffer, size_t SIZE)
+{
+ if (!mSensorModule) return;
+ sensor_t const* list;
+ ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+
+ snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count));
+ result.append(buffer);
+
+ Mutex::Autolock _l(mLock);
+ for (size_t i=0 ; i<size_t(count) ; i++) {
+ snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d / %d\n",
+ list[i].handle,
+ mActivationCount.valueFor(list[i].handle).count,
+ mActivationCount.valueFor(list[i].handle).rates.size());
+ result.append(buffer);
+ }
+}
+
+ssize_t SensorDevice::getSensorList(sensor_t const** list) {
+ if (!mSensorModule) return NO_INIT;
+ ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
+ return count;
+}
+
+status_t SensorDevice::initCheck() const {
+ return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
+}
+
+ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
+ if (!mSensorDevice) return NO_INIT;
+ return mSensorDevice->poll(mSensorDevice, buffer, count);
+}
+
+status_t SensorDevice::activate(void* ident, int handle, int enabled)
+{
+ if (!mSensorDevice) return NO_INIT;
+ status_t err(NO_ERROR);
+ bool actuateHardware = false;
+
+ Info& info( mActivationCount.editValueFor(handle) );
+ int32_t& count(info.count);
+ if (enabled) {
+ if (android_atomic_inc(&count) == 0) {
+ actuateHardware = true;
+ }
+ Mutex::Autolock _l(mLock);
+ if (info.rates.indexOfKey(ident) < 0) {
+ info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
+ }
+ } else {
+ if (android_atomic_dec(&count) == 1) {
+ actuateHardware = true;
+ }
+ Mutex::Autolock _l(mLock);
+ info.rates.removeItem(ident);
+ }
+ if (actuateHardware) {
+ err = mSensorDevice->activate(mSensorDevice, handle, enabled);
+ if (enabled) {
+ LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
+ if (err == 0) {
+ BatteryService::getInstance().enableSensor(handle);
+ }
+ } else {
+ if (err == 0) {
+ BatteryService::getInstance().disableSensor(handle);
+ }
+ }
+ }
+
+ if (!actuateHardware || enabled) {
+ Mutex::Autolock _l(mLock);
+ nsecs_t ns = info.rates.valueAt(0);
+ for (size_t i=1 ; i<info.rates.size() ; i++) {
+ if (info.rates.valueAt(i) < ns) {
+ nsecs_t cur = info.rates.valueAt(i);
+ if (cur < ns) {
+ ns = cur;
+ }
+ }
+ }
+ mSensorDevice->setDelay(mSensorDevice, handle, ns);
+ }
+
+ return err;
+}
+
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
+{
+ if (!mSensorDevice) return NO_INIT;
+ Info& info( mActivationCount.editValueFor(handle) );
+ { // scope for lock
+ Mutex::Autolock _l(mLock);
+ ssize_t index = info.rates.indexOfKey(ident);
+ if (index < 0) return BAD_INDEX;
+ info.rates.editValueAt(index) = ns;
+ ns = info.rates.valueAt(0);
+ for (size_t i=1 ; i<info.rates.size() ; i++) {
+ nsecs_t cur = info.rates.valueAt(i);
+ if (cur < ns) {
+ ns = cur;
+ }
+ }
+ }
+ return mSensorDevice->setDelay(mSensorDevice, handle, ns);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
new file mode 100644
index 000000000000..63ecbcddecc4
--- /dev/null
+++ b/services/sensorservice/SensorDevice.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_DEVICE_H
+#define ANDROID_SENSOR_DEVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+
+#include <gui/Sensor.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; // 5 Hz
+
+class SensorDevice : public Singleton<SensorDevice> {
+ friend class Singleton<SensorDevice>;
+ struct sensors_poll_device_t* mSensorDevice;
+ struct sensors_module_t* mSensorModule;
+ Mutex mLock; // protect mActivationCount[].rates
+ // fixed-size array after construction
+ struct Info {
+ Info() : count(0) { }
+ int32_t count;
+ KeyedVector<void*, nsecs_t> rates;
+ };
+ DefaultKeyedVector<int, Info> mActivationCount;
+
+ SensorDevice();
+public:
+ ssize_t getSensorList(sensor_t const** list);
+ status_t initCheck() const;
+ ssize_t poll(sensors_event_t* buffer, size_t count);
+ status_t activate(void* ident, int handle, int enabled);
+ status_t setDelay(void* ident, int handle, int64_t ns);
+ void dump(String8& result, char* buffer, size_t SIZE);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SENSOR_DEVICE_H
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
new file mode 100644
index 000000000000..93d23d9a40d2
--- /dev/null
+++ b/services/sensorservice/SensorInterface.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include "SensorInterface.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+SensorInterface::~SensorInterface()
+{
+}
+
+// ---------------------------------------------------------------------------
+
+HardwareSensor::HardwareSensor(const sensor_t& sensor)
+ : mSensorDevice(SensorDevice::getInstance()),
+ mSensor(&sensor), mEnabled(false)
+{
+ LOGI("%s", sensor.name);
+}
+
+HardwareSensor::~HardwareSensor() {
+}
+
+bool HardwareSensor::process(sensors_event_t* outEvent,
+ const sensors_event_t& event) {
+ *outEvent = event;
+ return true;
+}
+
+bool HardwareSensor::isEnabled() const {
+ return mEnabled;
+}
+
+status_t HardwareSensor::activate(void* ident,bool enabled) {
+ status_t err = mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
+ if (err == NO_ERROR)
+ mEnabled = enabled;
+ return err;
+}
+
+status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) {
+ return mSensorDevice.setDelay(ident, handle, ns);
+}
+
+Sensor HardwareSensor::getSensor() const {
+ return mSensor;
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
new file mode 100644
index 000000000000..eebd5638f5d0
--- /dev/null
+++ b/services/sensorservice/SensorInterface.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_INTERFACE_H
+#define ANDROID_SENSOR_INTERFACE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Singleton.h>
+
+#include <gui/Sensor.h>
+
+#include "SensorDevice.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class SensorInterface {
+public:
+ virtual ~SensorInterface();
+
+ virtual bool process(sensors_event_t* outEvent,
+ const sensors_event_t& event) = 0;
+
+ virtual bool isEnabled() const = 0;
+ virtual status_t activate(void* ident, bool enabled) = 0;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
+ virtual Sensor getSensor() const = 0;
+ virtual bool isVirtual() const = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+class HardwareSensor : public SensorInterface
+{
+ SensorDevice& mSensorDevice;
+ Sensor mSensor;
+ bool mEnabled;
+
+public:
+ HardwareSensor(const sensor_t& sensor);
+
+ virtual ~HardwareSensor();
+
+ virtual bool process(sensors_event_t* outEvent,
+ const sensors_event_t& event);
+
+ virtual bool isEnabled() const;
+ virtual status_t activate(void* ident, bool enabled);
+ virtual status_t setDelay(void* ident, int handle, int64_t ns);
+ virtual Sensor getSensor() const;
+ virtual bool isVirtual() const { return false; }
+};
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SENSOR_INTERFACE_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 22a45df0603c..ea5e5ccd8e25 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <math.h>
#include <sys/types.h>
#include <utils/SortedVector.h>
@@ -35,80 +36,15 @@
#include <hardware/sensors.h>
#include "SensorService.h"
+#include "GravitySensor.h"
+#include "LinearAccelerationSensor.h"
+#include "RotationVectorSensor.h"
namespace android {
// ---------------------------------------------------------------------------
-class BatteryService : public Singleton<BatteryService> {
- static const int TRANSACTION_noteStartSensor = IBinder::FIRST_CALL_TRANSACTION + 3;
- static const int TRANSACTION_noteStopSensor = IBinder::FIRST_CALL_TRANSACTION + 4;
- static const String16 DESCRIPTOR;
-
- friend class Singleton<BatteryService>;
- sp<IBinder> mBatteryStatService;
-
- BatteryService() {
- const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != NULL) {
- const String16 name("batteryinfo");
- mBatteryStatService = sm->getService(name);
- }
- }
-
- status_t noteStartSensor(int uid, int handle) {
- Parcel data, reply;
- data.writeInterfaceToken(DESCRIPTOR);
- data.writeInt32(uid);
- data.writeInt32(handle);
- status_t err = mBatteryStatService->transact(
- TRANSACTION_noteStartSensor, data, &reply, 0);
- err = reply.readExceptionCode();
- return err;
- }
-
- status_t noteStopSensor(int uid, int handle) {
- Parcel data, reply;
- data.writeInterfaceToken(DESCRIPTOR);
- data.writeInt32(uid);
- data.writeInt32(handle);
- status_t err = mBatteryStatService->transact(
- TRANSACTION_noteStopSensor, data, &reply, 0);
- err = reply.readExceptionCode();
- return err;
- }
-
-public:
- void enableSensor(int handle) {
- if (mBatteryStatService != 0) {
- int uid = IPCThreadState::self()->getCallingUid();
- int64_t identity = IPCThreadState::self()->clearCallingIdentity();
- noteStartSensor(uid, handle);
- IPCThreadState::self()->restoreCallingIdentity(identity);
- }
- }
- void disableSensor(int handle) {
- if (mBatteryStatService != 0) {
- int uid = IPCThreadState::self()->getCallingUid();
- int64_t identity = IPCThreadState::self()->clearCallingIdentity();
- noteStopSensor(uid, handle);
- IPCThreadState::self()->restoreCallingIdentity(identity);
- }
- }
-};
-
-const String16 BatteryService::DESCRIPTOR("com.android.internal.app.IBatteryStats");
-
-ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
-
-// ---------------------------------------------------------------------------
-
-// 100 events/s max
-static const nsecs_t MINIMUM_EVENT_PERIOD = ms2ns(10);
-
SensorService::SensorService()
: Thread(false),
- mSensorDevice(0),
- mSensorModule(0),
mDump("android.permission.DUMP"),
mInitCheck(NO_INIT)
{
@@ -118,43 +54,66 @@ void SensorService::onFirstRef()
{
LOGD("nuSensorService starting...");
- status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
- (hw_module_t const**)&mSensorModule);
-
- LOGE_IF(err, "couldn't load %s module (%s)",
- SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
- if (mSensorModule) {
- err = sensors_open(&mSensorModule->common, &mSensorDevice);
-
- LOGE_IF(err, "couldn't open device for module %s (%s)",
- SENSORS_HARDWARE_MODULE_ID, strerror(-err));
+ SensorDevice& dev(SensorDevice::getInstance());
- sensors_event_t event;
- memset(&event, 0, sizeof(event));
-
- struct sensor_t const* list;
- int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+ if (dev.initCheck() == NO_ERROR) {
+ uint32_t virtualSensorsNeeds =
+ (1<<SENSOR_TYPE_GRAVITY) |
+ (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
+ (1<<SENSOR_TYPE_ROTATION_VECTOR);
+ sensor_t const* list;
+ int count = dev.getSensorList(&list);
mLastEventSeen.setCapacity(count);
for (int i=0 ; i<count ; i++) {
- Sensor sensor(list + i);
- LOGI("%s", sensor.getName().string());
- mSensorList.add(sensor);
- if (mSensorDevice) {
- mSensorDevice->activate(mSensorDevice, sensor.getHandle(), 0);
+ registerSensor( new HardwareSensor(list[i]) );
+ switch (list[i].type) {
+ case SENSOR_TYPE_GRAVITY:
+ case SENSOR_TYPE_LINEAR_ACCELERATION:
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ virtualSensorsNeeds &= ~(1<<list[i].type);
+ break;
}
- mLastEventSeen.add(sensor.getHandle(), event);
}
- if (mSensorDevice) {
- run("SensorService", PRIORITY_URGENT_DISPLAY);
- mInitCheck = NO_ERROR;
+ if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
+ registerVirtualSensor( new GravitySensor(list, count) );
+ }
+ if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
+ registerVirtualSensor( new LinearAccelerationSensor(list, count) );
+ }
+ if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
+ registerVirtualSensor( new RotationVectorSensor(list, count) );
}
+
+ run("SensorService", PRIORITY_URGENT_DISPLAY);
+ mInitCheck = NO_ERROR;
}
}
+void SensorService::registerSensor(SensorInterface* s)
+{
+ sensors_event_t event;
+ memset(&event, 0, sizeof(event));
+
+ const Sensor sensor(s->getSensor());
+ // add to the sensor list (returned to clients)
+ mSensorList.add(sensor);
+ // add to our handle->SensorInterface mapping
+ mSensorMap.add(sensor.getHandle(), s);
+ // create an entry in the mLastEventSeen array
+ mLastEventSeen.add(sensor.getHandle(), event);
+}
+
+void SensorService::registerVirtualSensor(SensorInterface* s)
+{
+ registerSensor(s);
+ mVirtualSensorList.add( s );
+}
+
SensorService::~SensorService()
{
+ for (size_t i=0 ; i<mSensorMap.size() ; i++)
+ delete mSensorMap.valueAt(i);
}
status_t SensorService::dump(int fd, const Vector<String16>& args)
@@ -175,7 +134,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
for (size_t i=0 ; i<mSensorList.size() ; i++) {
const Sensor& s(mSensorList[i]);
const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
- snprintf(buffer, SIZE, "%s (vendor=%s, handle=%d, maxRate=%.2fHz, last=<%5.1f,%5.1f,%5.1f>)\n",
+ snprintf(buffer, SIZE, "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | last=<%5.1f,%5.1f,%5.1f>\n",
s.getName().string(),
s.getVendor().string(),
s.getHandle(),
@@ -183,6 +142,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
e.data[0], e.data[1], e.data[2]);
result.append(buffer);
}
+ SensorDevice::getInstance().dump(result, buffer, SIZE);
snprintf(buffer, SIZE, "%d active connections\n",
mActiveConnections.size());
@@ -191,7 +151,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
result.append(buffer);
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
int handle = mActiveSensors.keyAt(i);
- snprintf(buffer, SIZE, "%s (handle=%d, connections=%d)\n",
+ snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n",
getSensorName(handle).string(),
handle,
mActiveSensors.valueAt(i)->getNumConnections());
@@ -206,13 +166,15 @@ bool SensorService::threadLoop()
{
LOGD("nuSensorService thread starting...");
- sensors_event_t buffer[16];
- sensors_event_t scratch[16];
- struct sensors_poll_device_t* device = mSensorDevice;
- ssize_t count;
+ const size_t numEventMax = 16 * (1 + mVirtualSensorList.size());
+ sensors_event_t buffer[numEventMax];
+ sensors_event_t scratch[numEventMax];
+ SensorDevice& device(SensorDevice::getInstance());
+ const size_t vcount = mVirtualSensorList.size();
+ ssize_t count;
do {
- count = device->poll(device, buffer, sizeof(buffer)/sizeof(*buffer));
+ count = device.poll(buffer, numEventMax);
if (count<0) {
LOGE("sensor poll failed (%s)", strerror(-count));
break;
@@ -220,19 +182,44 @@ bool SensorService::threadLoop()
recordLastValue(buffer, count);
+ // handle virtual sensors
+ if (count && vcount) {
+ const DefaultKeyedVector<int, SensorInterface*> virtualSensors(
+ getActiveVirtualSensors());
+ const size_t activeVirtualSensorCount = virtualSensors.size();
+ if (activeVirtualSensorCount) {
+ size_t k = 0;
+ for (size_t i=0 ; i<size_t(count) ; i++) {
+ sensors_event_t const * const event = buffer;
+ for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
+ sensors_event_t out;
+ if (virtualSensors.valueAt(j)->process(&out, event[i])) {
+ buffer[count + k] = out;
+ k++;
+ }
+ }
+ }
+ if (k) {
+ // record the last synthesized values
+ recordLastValue(&buffer[count], k);
+ count += k;
+ // sort the buffer by time-stamps
+ sortEventBuffer(buffer, count);
+ }
+ }
+ }
+
+ // send our events to clients...
const SortedVector< wp<SensorEventConnection> > activeConnections(
getActiveConnections());
-
size_t numConnections = activeConnections.size();
- if (numConnections) {
- for (size_t i=0 ; i<numConnections ; i++) {
- sp<SensorEventConnection> connection(activeConnections[i].promote());
- if (connection != 0) {
- connection->sendEvents(buffer, count, scratch);
- }
+ for (size_t i=0 ; i<numConnections ; i++) {
+ sp<SensorEventConnection> connection(
+ activeConnections[i].promote());
+ if (connection != 0) {
+ connection->sendEvents(buffer, count, scratch);
}
}
-
} while (count >= 0 || Thread::exitPending());
LOGW("Exiting SensorService::threadLoop!");
@@ -257,6 +244,18 @@ void SensorService::recordLastValue(
mLastEventSeen.editValueFor(prev) = buffer[count-1];
}
+void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
+{
+ struct compar {
+ static int cmp(void const* lhs, void const* rhs) {
+ sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
+ sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs);
+ return r->timestamp - l->timestamp;
+ }
+ };
+ qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
+}
+
SortedVector< wp<SensorService::SensorEventConnection> >
SensorService::getActiveConnections() const
{
@@ -264,6 +263,13 @@ SensorService::getActiveConnections() const
return mActiveConnections;
}
+DefaultKeyedVector<int, SensorInterface*>
+SensorService::getActiveVirtualSensors() const
+{
+ Mutex::Autolock _l(mLock);
+ return mActiveVirtualSensors;
+}
+
String8 SensorService::getSensorName(int handle) const {
size_t count = mSensorList.size();
for (size_t i=0 ; i<count ; i++) {
@@ -294,8 +300,13 @@ void SensorService::cleanupConnection(const wp<SensorEventConnection>& connectio
for (size_t i=0 ; i<size ; ) {
SensorRecord* rec = mActiveSensors.valueAt(i);
if (rec && rec->removeConnection(connection)) {
- mSensorDevice->activate(mSensorDevice, mActiveSensors.keyAt(i), 0);
+ int handle = mActiveSensors.keyAt(i);
+ SensorInterface* sensor = mSensorMap.valueFor( handle );
+ if (sensor) {
+ sensor->activate(connection.unsafe_get(), false);
+ }
mActiveSensors.removeItemsAt(i, 1);
+ mActiveVirtualSensors.removeItem(handle);
delete rec;
size--;
} else {
@@ -311,39 +322,38 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
if (mInitCheck != NO_ERROR)
return mInitCheck;
- status_t err = NO_ERROR;
Mutex::Autolock _l(mLock);
- SensorRecord* rec = mActiveSensors.valueFor(handle);
- if (rec == 0) {
- rec = new SensorRecord(connection);
- mActiveSensors.add(handle, rec);
- err = mSensorDevice->activate(mSensorDevice, handle, 1);
- LOGE_IF(err, "Error activating sensor %d (%s)", handle, strerror(-err));
- if (err == 0) {
- BatteryService::getInstance().enableSensor(handle);
- }
- } else {
- if (rec->addConnection(connection)) {
- // this sensor is already activated, but we are adding a
- // connection that uses it. Immediately send down the last
- // known value of the requested sensor.
- sensors_event_t scratch;
- sensors_event_t& event(mLastEventSeen.editValueFor(handle));
- if (event.version == sizeof(sensors_event_t)) {
- connection->sendEvents(&event, 1);
+ SensorInterface* sensor = mSensorMap.valueFor(handle);
+ status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
+ if (err == NO_ERROR) {
+ SensorRecord* rec = mActiveSensors.valueFor(handle);
+ if (rec == 0) {
+ rec = new SensorRecord(connection);
+ mActiveSensors.add(handle, rec);
+ if (sensor->isVirtual()) {
+ mActiveVirtualSensors.add(handle, sensor);
+ }
+ } else {
+ if (rec->addConnection(connection)) {
+ // this sensor is already activated, but we are adding a
+ // connection that uses it. Immediately send down the last
+ // known value of the requested sensor.
+ sensors_event_t scratch;
+ sensors_event_t& event(mLastEventSeen.editValueFor(handle));
+ if (event.version == sizeof(sensors_event_t)) {
+ connection->sendEvents(&event, 1);
+ }
}
}
- }
- if (err == NO_ERROR) {
- // connection now active
- if (connection->addSensor(handle)) {
- // the sensor was added (which means it wasn't already there)
- // so, see if this connection becomes active
- if (mActiveConnections.indexOf(connection) < 0) {
- mActiveConnections.add(connection);
+ if (err == NO_ERROR) {
+ // connection now active
+ if (connection->addSensor(handle)) {
+ // the sensor was added (which means it wasn't already there)
+ // so, see if this connection becomes active
+ if (mActiveConnections.indexOf(connection) < 0) {
+ mActiveConnections.add(connection);
+ }
}
- // this could change the sensor event delivery speed
- recomputeEventsPeriodLocked(handle);
}
}
return err;
@@ -367,15 +377,11 @@ status_t SensorService::disable(const sp<SensorEventConnection>& connection,
// see if this sensor becomes inactive
if (rec->removeConnection(connection)) {
mActiveSensors.removeItem(handle);
+ mActiveVirtualSensors.removeItem(handle);
delete rec;
- err = mSensorDevice->activate(mSensorDevice, handle, 0);
- if (err == 0) {
- BatteryService::getInstance().disableSensor(handle);
- }
}
- }
- if (err == NO_ERROR) {
- recomputeEventsPeriodLocked(handle);
+ SensorInterface* sensor = mSensorMap.valueFor(handle);
+ err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
}
return err;
}
@@ -392,30 +398,9 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection
if (ns < MINIMUM_EVENTS_PERIOD)
ns = MINIMUM_EVENTS_PERIOD;
- Mutex::Autolock _l(mLock);
- status_t err = connection->setEventRateLocked(handle, ns);
- if (err == NO_ERROR) {
- recomputeEventsPeriodLocked(handle);
- }
- return err;
-}
-
-status_t SensorService::recomputeEventsPeriodLocked(int32_t handle)
-{
- status_t err = NO_ERROR;
- nsecs_t wanted = ms2ns(1000);
- size_t count = mActiveConnections.size();
- for (size_t i=0 ; i<count ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != NULL) {
- nsecs_t ns = connection->getEventRateForSensor(handle);
- if (ns) {
- wanted = wanted < ns ? wanted : ns;
- }
- }
- }
- err = mSensorDevice->setDelay(mSensorDevice, handle, wanted);
- return err;
+ SensorInterface* sensor = mSensorMap.valueFor(handle);
+ if (!sensor) return BAD_VALUE;
+ return sensor->setDelay(connection.get(), handle, ns);
}
// ---------------------------------------------------------------------------
@@ -465,9 +450,8 @@ void SensorService::SensorEventConnection::onFirstRef()
bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- if (mSensorInfo.indexOfKey(handle) <= 0) {
- SensorInfo info;
- mSensorInfo.add(handle, info);
+ if (mSensorInfo.indexOf(handle) <= 0) {
+ mSensorInfo.add(handle);
return true;
}
return false;
@@ -475,7 +459,7 @@ bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- if (mSensorInfo.removeItem(handle) >= 0) {
+ if (mSensorInfo.remove(handle) >= 0) {
return true;
}
return false;
@@ -483,7 +467,7 @@ bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
Mutex::Autolock _l(mConnectionLock);
- return mSensorInfo.indexOfKey(handle) >= 0;
+ return mSensorInfo.indexOf(handle) >= 0;
}
bool SensorService::SensorEventConnection::hasAnySensor() const {
@@ -491,19 +475,6 @@ bool SensorService::SensorEventConnection::hasAnySensor() const {
return mSensorInfo.size() ? true : false;
}
-status_t SensorService::SensorEventConnection::setEventRateLocked(
- int handle, nsecs_t ns)
-{
- Mutex::Autolock _l(mConnectionLock);
- ssize_t index = mSensorInfo.indexOfKey(handle);
- if (index >= 0) {
- SensorInfo& info = mSensorInfo.editValueFor(handle);
- info.ns = ns;
- return NO_ERROR;
- }
- return status_t(index);
-}
-
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch)
@@ -515,7 +486,7 @@ status_t SensorService::SensorEventConnection::sendEvents(
size_t i=0;
while (i<numEvents) {
const int32_t curr = buffer[i].sensor;
- if (mSensorInfo.indexOfKey(curr) >= 0) {
+ if (mSensorInfo.indexOf(curr) >= 0) {
do {
scratch[count++] = buffer[i++];
} while ((i<numEvents) && (buffer[i].sensor == curr));
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index c0922f553c76..540c7e2a5fe8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -34,6 +34,8 @@
#include <gui/ISensorServer.h>
#include <gui/ISensorEventConnection.h>
+#include "SensorInterface.h"
+
// ---------------------------------------------------------------------------
struct sensors_poll_device_t;
@@ -50,7 +52,6 @@ class SensorService :
friend class BinderService<SensorService>;
static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
- static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; // 5 Hz
SensorService();
virtual ~SensorService();
@@ -77,12 +78,8 @@ class SensorService :
sp<SensorChannel> const mChannel;
mutable Mutex mConnectionLock;
- // protected mConnectionLock
- struct SensorInfo {
- SensorInfo() : ns(DEFAULT_EVENTS_PERIOD) { }
- nsecs_t ns;
- };
- DefaultKeyedVector<int32_t, SensorInfo> mSensorInfo;
+ // protected by SensorService::mLock
+ SortedVector<int> mSensorInfo;
public:
SensorEventConnection(const sp<SensorService>& service);
@@ -93,10 +90,6 @@ class SensorService :
bool hasAnySensor() const;
bool addSensor(int32_t handle);
bool removeSensor(int32_t handle);
- status_t setEventRateLocked(int handle, nsecs_t ns);
- nsecs_t getEventRateForSensor(int32_t handle) const {
- return mSensorInfo.valueFor(handle).ns;
- }
};
class SensorRecord {
@@ -109,21 +102,25 @@ class SensorService :
};
SortedVector< wp<SensorEventConnection> > getActiveConnections() const;
- String8 getSensorName(int handle) const;
- status_t recomputeEventsPeriodLocked(int32_t handle);
+ DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const;
+ String8 getSensorName(int handle) const;
void recordLastValue(sensors_event_t const * buffer, size_t count);
+ static void sortEventBuffer(sensors_event_t* buffer, size_t count);
+ void registerSensor(SensorInterface* sensor);
+ void registerVirtualSensor(SensorInterface* sensor);
// constants
Vector<Sensor> mSensorList;
- struct sensors_poll_device_t* mSensorDevice;
- struct sensors_module_t* mSensorModule;
+ DefaultKeyedVector<int, SensorInterface*> mSensorMap;
+ Vector<SensorInterface *> mVirtualSensorList;
Permission mDump;
status_t mInitCheck;
// protected by mLock
mutable Mutex mLock;
DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
+ DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
SortedVector< wp<SensorEventConnection> > mActiveConnections;
// The size of this vector is constant, only the items are mutable