diff options
author | Timothy Knight <tknight@google.com> | 2014-06-30 17:55:25 -0700 |
---|---|---|
committer | Timothy Knight <tknight@google.com> | 2014-06-30 17:55:25 -0700 |
commit | ecb768002698fe072d568944e2a3d401475e53a6 (patch) | |
tree | ce6ebe348809ce6fc6e06758174897f80c2c87ef /apps | |
parent | 8be79762855388604200009c81a40287a22d57f2 (diff) | |
download | pdk-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.py | 41 | ||||
-rw-r--r-- | apps/CameraITS/service/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | apps/CameraITS/service/src/com/android/camera2/its/ItsService.java | 108 | ||||
-rw-r--r-- | apps/CameraITS/tests/test_sensor_events.py | 37 |
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() + |