aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTimothy Knight <tknight@google.com>2014-06-30 17:55:25 -0700
committerTimothy Knight <tknight@google.com>2014-06-30 17:55:25 -0700
commitecb768002698fe072d568944e2a3d401475e53a6 (patch)
treece6ebe348809ce6fc6e06758174897f80c2c87ef /apps
parent8be79762855388604200009c81a40287a22d57f2 (diff)
downloadpdk-ecb768002698fe072d568944e2a3d401475e53a6.tar.gz
CameraITS: Added method to get sensor event traces
Change-Id: Ibc59c722ec85ac45c2e69618eb7197f6d14b414d
Diffstat (limited to 'apps')
-rw-r--r--apps/CameraITS/pymodules/its/device.py41
-rw-r--r--apps/CameraITS/service/AndroidManifest.xml7
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsService.java108
-rw-r--r--apps/CameraITS/tests/test_sensor_events.py37
4 files changed, 185 insertions, 8 deletions
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index be97ada..429c8db 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -128,6 +128,47 @@ class ItsSession(object):
buf = numpy.frombuffer(buf, dtype=numpy.uint8)
return jobj, buf
+ def start_sensor_events(self):
+ """Start collecting sensor events on the device.
+
+ See get_sensor_events for more info.
+
+ Returns:
+ Nothing.
+ """
+ cmd = {}
+ cmd["cmdName"] = "startSensorEvents"
+ self.sock.send(json.dumps(cmd) + "\n")
+
+ def get_sensor_events(self):
+ """Get a trace of all sensor events on the device.
+
+ The trace starts when the start_sensor_events function is called. If
+ the test runs for a long time after this call, then the device's
+ internal memory can fill up. Calling get_sensor_events gets all events
+ from the device, and then stops the device from collecting events and
+ clears the internal buffer; to start again, the start_sensor_events
+ call must be used again.
+
+ Events from the accelerometer, compass, and gyro are returned; each
+ has a timestamp and x,y,z values.
+
+ Note that sensor events are only produced if the device isn't in its
+ standby mode (i.e.) if the screen is on.
+
+ Returns:
+ A Python dictionary with three keys ("accel", "mag", "gyro") each
+ of which maps to a list of objects containing "time","x","y","z"
+ keys.
+ """
+ cmd = {}
+ cmd["cmdName"] = "getSensorEvents"
+ self.sock.send(json.dumps(cmd) + "\n")
+ data,_ = self.__read_response_from_socket()
+ if data['tag'] != 'sensorEvents':
+ raise its.error.Error('Invalid command response')
+ return data['objValue']
+
def get_camera_properties(self):
"""Get the camera properties object for the device.
diff --git a/apps/CameraITS/service/AndroidManifest.xml b/apps/CameraITS/service/AndroidManifest.xml
index ba69ab0..186675f 100644
--- a/apps/CameraITS/service/AndroidManifest.xml
+++ b/apps/CameraITS/service/AndroidManifest.xml
@@ -21,14 +21,19 @@
android:versionName="1.0"
package="com.android.camera2.its">
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="19"/>
- <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
+ <uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
+ <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
+ <uses-feature android:name="android.hardware.sensor.compass" android:required="true" />
+ <uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:label="@string/app_name"
android:largeHeap="true"
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
index 97bc4b2..0f1d34e 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
@@ -30,6 +30,10 @@ import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.DngCreator;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.media.Image;
import android.media.ImageReader;
import android.net.Uri;
@@ -66,6 +70,7 @@ import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
@@ -73,7 +78,7 @@ import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-public class ItsService extends Service {
+public class ItsService extends Service implements SensorEventListener {
public static final String TAG = ItsService.class.getSimpleName();
// Timeouts, in seconds.
@@ -134,6 +139,22 @@ public class ItsService extends Service {
private volatile boolean mConvergedAF = false;
private volatile boolean mConvergedAWB = false;
+ class MySensorEvent {
+ public Sensor sensor;
+ public int accuracy;
+ public long timestamp;
+ public float values[];
+ };
+
+ // For capturing motion sensor traces.
+ private SensorManager mSensorManager = null;
+ private Sensor mAccelSensor = null;
+ private Sensor mMagSensor = null;
+ private Sensor mGyroSensor = null;
+ private volatile LinkedList<MySensorEvent> mEvents = null;
+ private volatile Object mEventLock = new Object();
+ private volatile boolean mEventsEnabled = false;
+
private CountDownLatch mCaptureCallbackLatch;
public interface CaptureListener {
@@ -184,6 +205,15 @@ public class ItsService extends Service {
throw new ItsException("Failed to open camera (after blocking)", e);
}
+ mEvents = new LinkedList<MySensorEvent>();
+ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+ mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mMagSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+ mSensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_FASTEST);
+ mSensorManager.registerListener(this, mMagSensor, SensorManager.SENSOR_DELAY_FASTEST);
+ mSensorManager.registerListener(this, mGyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
+
// Create threads to receive images and save them.
for (int i = 0; i < MAX_NUM_OUTPUT_SURFACES; i++) {
mSaveThreads[i] = new HandlerThread("SaveThread" + i);
@@ -354,14 +384,15 @@ public class ItsService extends Service {
JSONObject cmdObj = new JSONObject(cmd);
if ("getCameraProperties".equals(cmdObj.getString("cmdName"))) {
doGetProps();
- }
- else if ("do3A".equals(cmdObj.getString("cmdName"))) {
+ } else if ("startSensorEvents".equals(cmdObj.getString("cmdName"))) {
+ doStartSensorEvents();
+ } else if ("getSensorEvents".equals(cmdObj.getString("cmdName"))) {
+ doGetSensorEvents();
+ } else if ("do3A".equals(cmdObj.getString("cmdName"))) {
do3A(cmdObj);
- }
- else if ("doCapture".equals(cmdObj.getString("cmdName"))) {
+ } else if ("doCapture".equals(cmdObj.getString("cmdName"))) {
doCapture(cmdObj);
- }
- else {
+ } else {
throw new ItsException("Unknown command: " + cmd);
}
} catch (org.json.JSONException e) {
@@ -415,6 +446,36 @@ public class ItsService extends Service {
sendResponse(tag, null, null, bbuf);
}
+ public void sendResponse(LinkedList<MySensorEvent> events)
+ throws ItsException {
+ try {
+ JSONArray accels = new JSONArray();
+ JSONArray mags = new JSONArray();
+ JSONArray gyros = new JSONArray();
+ for (MySensorEvent event : events) {
+ JSONObject obj = new JSONObject();
+ obj.put("time", event.timestamp);
+ obj.put("x", event.values[0]);
+ obj.put("y", event.values[1]);
+ obj.put("z", event.values[2]);
+ if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+ accels.put(obj);
+ } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
+ mags.put(obj);
+ } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
+ gyros.put(obj);
+ }
+ }
+ JSONObject obj = new JSONObject();
+ obj.put("accel", accels);
+ obj.put("mag", mags);
+ obj.put("gyro", gyros);
+ sendResponse("sensorEvents", null, obj, null);
+ } catch (org.json.JSONException e) {
+ throw new ItsException("JSON error: ", e);
+ }
+ }
+
public void sendResponse(CameraCharacteristics props)
throws ItsException {
try {
@@ -490,6 +551,20 @@ public class ItsService extends Service {
};
}
+ private void doStartSensorEvents() throws ItsException {
+ synchronized(mEventLock) {
+ mEventsEnabled = true;
+ }
+ }
+
+ private void doGetSensorEvents() throws ItsException {
+ synchronized(mEventLock) {
+ mSocketRunnableObj.sendResponse(mEvents);
+ mEvents.clear();
+ mEventsEnabled = false;
+ }
+ }
+
private void doGetProps() throws ItsException {
mSocketRunnableObj.sendResponse(mCameraCharacteristics);
}
@@ -787,6 +862,25 @@ public class ItsService extends Service {
}
}
+ @Override
+ public final void onSensorChanged(SensorEvent event) {
+ synchronized(mEventLock) {
+ if (mEventsEnabled) {
+ MySensorEvent ev2 = new MySensorEvent();
+ ev2.sensor = event.sensor;
+ ev2.accuracy = event.accuracy;
+ ev2.timestamp = event.timestamp;
+ ev2.values = new float[event.values.length];
+ System.arraycopy(event.values, 0, ev2.values, 0, event.values.length);
+ mEvents.add(ev2);
+ }
+ }
+ }
+
+ @Override
+ public final void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
private final CaptureListener mCaptureListener = new CaptureListener() {
@Override
public void onCaptureAvailable(Image capture) {
diff --git a/apps/CameraITS/tests/test_sensor_events.py b/apps/CameraITS/tests/test_sensor_events.py
new file mode 100644
index 0000000..22cb3b8
--- /dev/null
+++ b/apps/CameraITS/tests/test_sensor_events.py
@@ -0,0 +1,37 @@
+# Copyright 2014 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.
+
+import its.device
+import pprint
+import time
+
+def main():
+ """Basic test to query and print out sensor events.
+
+ Test will only work if the screen is on (i.e.) the device isn't in standby.
+ """
+
+ with its.device.ItsSession() as cam:
+
+ cam.start_sensor_events()
+
+ print "Sleeping for 3s; move the camera to generate some events"
+ time.sleep(3)
+
+ events = cam.get_sensor_events()
+ pprint.pprint(events)
+
+if __name__ == '__main__':
+ main()
+