summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch)
tree35051494d2af230dce54d6b31c6af8fc24091316 /core/java/android/hardware
downloadframeworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2
Initial Contribution
Diffstat (limited to 'core/java/android/hardware')
-rw-r--r--core/java/android/hardware/Camera.java633
-rw-r--r--core/java/android/hardware/ISensorService.aidl30
-rw-r--r--core/java/android/hardware/SensorListener.java46
-rw-r--r--core/java/android/hardware/SensorManager.java619
-rw-r--r--core/java/android/hardware/package.html5
5 files changed, 1333 insertions, 0 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
new file mode 100644
index 0000000..8330750
--- /dev/null
+++ b/core/java/android/hardware/Camera.java
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package android.hardware;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+/**
+ * The Camera class is used to connect/disconnect with the camera service,
+ * set capture settings, start/stop preview, snap a picture, and retrieve
+ * frames for encoding for video.
+ * <p>There is no default constructor for this class. Use {@link #open()} to
+ * get a Camera object.</p>
+ */
+public class Camera {
+ private static final String TAG = "Camera";
+
+ // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
+ private static final int SHUTTER_CALLBACK = 0;
+ private static final int RAW_PICTURE_CALLBACK = 1;
+ private static final int JPEG_PICTURE_CALLBACK = 2;
+ private static final int PREVIEW_CALLBACK = 3;
+ private static final int AUTOFOCUS_CALLBACK = 4;
+ private static final int ERROR_CALLBACK = 5;
+
+ private int mNativeContext; // accessed by native methods
+ private int mListenerContext;
+ private EventHandler mEventHandler;
+ private ShutterCallback mShutterCallback;
+ private PictureCallback mRawImageCallback;
+ private PictureCallback mJpegCallback;
+ private PreviewCallback mPreviewCallback;
+ private AutoFocusCallback mAutoFocusCallback;
+ private ErrorCallback mErrorCallback;
+
+ /**
+ * Returns a new Camera object.
+ */
+ public static Camera open() {
+ return new Camera();
+ }
+
+ Camera() {
+ mShutterCallback = null;
+ mRawImageCallback = null;
+ mJpegCallback = null;
+ mPreviewCallback = null;
+
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mEventHandler = new EventHandler(this, looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mEventHandler = new EventHandler(this, looper);
+ } else {
+ mEventHandler = null;
+ }
+
+ native_setup(new WeakReference<Camera>(this));
+ }
+
+ protected void finalize() {
+ native_release();
+ }
+
+ private native final void native_setup(Object camera_this);
+ private native final void native_release();
+
+
+ /**
+ * Disconnects and releases the Camera object resources.
+ * <p>It is recommended that you call this as soon as you're done with the
+ * Camera object.</p>
+ */
+ public final void release() {
+ native_release();
+ }
+
+ /**
+ * Sets the SurfaceHolder to be used for a picture preview. If the surface
+ * changed since the last call, the screen will blank. Nothing happens
+ * if the same surface is re-set.
+ *
+ * @param holder the SurfaceHolder upon which to place the picture preview
+ */
+ public final void setPreviewDisplay(SurfaceHolder holder) {
+ setPreviewDisplay(holder.getSurface());
+ }
+
+ private native final void setPreviewDisplay(Surface surface);
+
+ /**
+ * Used to get a copy of each preview frame.
+ */
+ public interface PreviewCallback
+ {
+ /**
+ * The callback that delivers the preview frames.
+ *
+ * @param data The contents of the preview frame in getPreviewFormat()
+ * format.
+ * @param camera The Camera service object.
+ */
+ void onPreviewFrame(byte[] data, Camera camera);
+ };
+
+ /**
+ * Start drawing preview frames to the surface.
+ */
+ public native final void startPreview();
+
+ /**
+ * Stop drawing preview frames to the surface.
+ */
+ public native final void stopPreview();
+
+ /**
+ * Can be called at any time to instruct the camera to use a callback for
+ * each preview frame in addition to displaying it.
+ *
+ * @param cb A callback object that receives a copy of each preview frame.
+ * Pass null to stop receiving callbacks at any time.
+ */
+ public final void setPreviewCallback(PreviewCallback cb) {
+ mPreviewCallback = cb;
+ setHasPreviewCallback(cb != null);
+ }
+ private native final void setHasPreviewCallback(boolean installed);
+
+ private class EventHandler extends Handler
+ {
+ private Camera mCamera;
+
+ public EventHandler(Camera c, Looper looper) {
+ super(looper);
+ mCamera = c;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case SHUTTER_CALLBACK:
+ if (mShutterCallback != null) {
+ mShutterCallback.onShutter();
+ }
+ return;
+ case RAW_PICTURE_CALLBACK:
+ if (mRawImageCallback != null)
+ mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
+ return;
+
+ case JPEG_PICTURE_CALLBACK:
+ if (mJpegCallback != null)
+ mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
+ return;
+
+ case PREVIEW_CALLBACK:
+ if (mPreviewCallback != null)
+ mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera);
+ return;
+
+ case AUTOFOCUS_CALLBACK:
+ if (mAutoFocusCallback != null)
+ mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera);
+ return;
+
+ case ERROR_CALLBACK:
+ Log.e(TAG, "Error " + msg.arg1);
+ if (mErrorCallback != null)
+ mErrorCallback.onError(msg.arg1, mCamera);
+ return;
+
+ default:
+ Log.e(TAG, "Unknown message type " + msg.what);
+ return;
+ }
+ }
+ }
+
+ private static void postEventFromNative(Object camera_ref,
+ int what, int arg1, int arg2, Object obj)
+ {
+ Camera c = (Camera)((WeakReference)camera_ref).get();
+ if (c == null)
+ return;
+
+ if (c.mEventHandler != null) {
+ Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+ c.mEventHandler.sendMessage(m);
+ }
+ }
+
+ /**
+ * Handles the callback for the camera auto focus.
+ */
+ public interface AutoFocusCallback
+ {
+ /**
+ * Callback for the camera auto focus.
+ *
+ * @param success true if focus was successful, false if otherwise
+ * @param camera the Camera service object
+ */
+ void onAutoFocus(boolean success, Camera camera);
+ };
+
+ /**
+ * Registers a callback to be invoked when the auto focus responds.
+ *
+ * @param cb the callback to run
+ */
+ public final void autoFocus(AutoFocusCallback cb)
+ {
+ mAutoFocusCallback = cb;
+ native_autoFocus();
+ }
+ private native final void native_autoFocus();
+
+ /**
+ * An interface which contains a callback for the shutter closing after taking a picture.
+ */
+ public interface ShutterCallback
+ {
+ /**
+ * Can be used to play a shutter sound as soon as the image has been captured, but before
+ * the data is available.
+ */
+ void onShutter();
+ }
+
+ /**
+ * Handles the callback for when a picture is taken.
+ */
+ public interface PictureCallback {
+ /**
+ * Callback for when a picture is taken.
+ *
+ * @param data a byte array of the picture data
+ * @param camera the Camera service object
+ */
+ void onPictureTaken(byte[] data, Camera camera);
+ };
+
+ /**
+ * Registers a callback to be invoked when a picture is taken.
+ *
+ * @param raw the callback to run for raw images, may be null
+ * @param jpeg the callback to run for jpeg images, may be null
+ */
+ public final void takePicture(ShutterCallback shutter, PictureCallback raw,
+ PictureCallback jpeg) {
+ mShutterCallback = shutter;
+ mRawImageCallback = raw;
+ mJpegCallback = jpeg;
+ native_takePicture();
+ }
+ private native final void native_takePicture();
+
+ // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
+ /** Unspecified camerar error. @see #ErrorCallback */
+ public static final int CAMERA_ERROR_UNKNOWN = 1;
+ /** Media server died. In this case, the application must release the
+ * Camera object and instantiate a new one. @see #ErrorCallback */
+ public static final int CAMERA_ERROR_SERVER_DIED = 100;
+
+ /**
+ * Handles the camera error callback.
+ */
+ public interface ErrorCallback
+ {
+ /**
+ * Callback for camera errors.
+ * @param error error code:
+ * <ul>
+ * <li>{@link #CAMERA_ERROR_UNKNOWN}
+ * <li>{@link #CAMERA_ERROR_SERVER_DIED}
+ * </ul>
+ * @param camera the Camera service object
+ */
+ void onError(int error, Camera camera);
+ };
+
+ /**
+ * Registers a callback to be invoked when an error occurs.
+ * @param cb the callback to run
+ */
+ public final void setErrorCallback(ErrorCallback cb)
+ {
+ mErrorCallback = cb;
+ }
+
+ private native final void native_setParameters(String params);
+ private native final String native_getParameters();
+
+ /**
+ * Sets the Parameters for pictures from this Camera service.
+ *
+ * @param params the Parameters to use for this Camera service
+ */
+ public void setParameters(Parameters params) {
+ Log.e(TAG, "setParameters()");
+ //params.dump();
+ native_setParameters(params.flatten());
+ }
+
+ /**
+ * Returns the picture Parameters for this Camera service.
+ */
+ public Parameters getParameters() {
+ Parameters p = new Parameters();
+ String s = native_getParameters();
+ Log.e(TAG, "_getParameters: " + s);
+ p.unflatten(s);
+ return p;
+ }
+
+ /**
+ * Handles the picture size (dimensions).
+ */
+ public class Size {
+ /**
+ * Sets the dimensions for pictures.
+ *
+ * @param w the photo width (pixels)
+ * @param h the photo height (pixels)
+ */
+ public Size(int w, int h) {
+ width = w;
+ height = h;
+ }
+ /** width of the picture */
+ public int width;
+ /** height of the picture */
+ public int height;
+ };
+
+ /**
+ * Handles the parameters for pictures created by a Camera service.
+ */
+ public class Parameters {
+ private HashMap<String, String> mMap;
+
+ private Parameters() {
+ mMap = new HashMap<String, String>();
+ }
+
+ /**
+ * Writes the current Parameters to the log.
+ * @hide
+ * @deprecated
+ */
+ public void dump() {
+ Log.e(TAG, "dump: size=" + mMap.size());
+ for (String k : mMap.keySet()) {
+ Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
+ }
+ }
+
+ /**
+ * Creates a single string with all the parameters set in
+ * this Parameters object.
+ * <p>The {@link #unflatten(String)} method does the reverse.</p>
+ *
+ * @return a String with all values from this Parameters object, in
+ * semi-colon delimited key-value pairs
+ */
+ public String flatten() {
+ StringBuilder flattened = new StringBuilder();
+ for (String k : mMap.keySet()) {
+ flattened.append(k);
+ flattened.append("=");
+ flattened.append(mMap.get(k));
+ flattened.append(";");
+ }
+ // chop off the extra semicolon at the end
+ flattened.deleteCharAt(flattened.length()-1);
+ return flattened.toString();
+ }
+
+ /**
+ * Takes a flattened string of parameters and adds each one to
+ * this Parameters object.
+ * <p>The {@link #flatten()} method does the reverse.</p>
+ *
+ * @param flattened a String of parameters (key-value paired) that
+ * are semi-colon delimited
+ */
+ public void unflatten(String flattened) {
+ mMap.clear();
+ String[] pairs = flattened.split(";");
+ for (String p : pairs) {
+ String[] kv = p.split("=");
+ if (kv.length == 2)
+ mMap.put(kv[0], kv[1]);
+ }
+ }
+
+ public void remove(String key) {
+ mMap.remove(key);
+ }
+
+ /**
+ * Sets a String parameter.
+ *
+ * @param key the key name for the parameter
+ * @param value the String value of the parameter
+ */
+ public void set(String key, String value) {
+ if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
+ Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");
+ return;
+ }
+ if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
+ Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");
+ return;
+ }
+
+ mMap.put(key, value);
+ }
+
+ /**
+ * Sets an integer parameter.
+ *
+ * @param key the key name for the parameter
+ * @param value the int value of the parameter
+ */
+ public void set(String key, int value) {
+ mMap.put(key, Integer.toString(value));
+ }
+
+ /**
+ * Returns the value of a String parameter.
+ *
+ * @param key the key name for the parameter
+ * @return the String value of the parameter
+ */
+ public String get(String key) {
+ return mMap.get(key);
+ }
+
+ /**
+ * Returns the value of an integer parameter.
+ *
+ * @param key the key name for the parameter
+ * @return the int value of the parameter
+ */
+ public int getInt(String key) {
+ return Integer.parseInt(mMap.get(key));
+ }
+
+ /**
+ * Sets the dimensions for preview pictures.
+ *
+ * @param width the width of the pictures, in pixels
+ * @param height the height of the pictures, in pixels
+ */
+ public void setPreviewSize(int width, int height) {
+ String v = Integer.toString(width) + "x" + Integer.toString(height);
+ set("preview-size", v);
+ }
+
+ /**
+ * Returns the dimensions setting for preview pictures.
+ *
+ * @return a Size object with the height and width setting
+ * for the preview picture
+ */
+ public Size getPreviewSize() {
+ String pair = get("preview-size");
+ if (pair == null)
+ return null;
+ String[] dims = pair.split("x");
+ if (dims.length != 2)
+ return null;
+
+ return new Size(Integer.parseInt(dims[0]),
+ Integer.parseInt(dims[1]));
+
+ }
+
+ /**
+ * Sets the rate at which preview frames are received.
+ *
+ * @param fps the frame rate (frames per second)
+ */
+ public void setPreviewFrameRate(int fps) {
+ set("preview-frame-rate", fps);
+ }
+
+ /**
+ * Returns the setting for the rate at which preview frames
+ * are received.
+ *
+ * @return the frame rate setting (frames per second)
+ */
+ public int getPreviewFrameRate() {
+ return getInt("preview-frame-rate");
+ }
+
+ /**
+ * Sets the image format for preview pictures.
+ *
+ * @param pixel_format the desired preview picture format
+ * (<var>PixelFormat.YCbCr_422_SP</var>,
+ * <var>PixelFormat.RGB_565</var>, or
+ * <var>PixelFormat.JPEG</var>)
+ * @see android.graphics.PixelFormat
+ */
+ public void setPreviewFormat(int pixel_format) {
+ String s = cameraFormatForPixelFormat(pixel_format);
+ if (s == null) {
+ throw new IllegalArgumentException();
+ }
+
+ set("preview-format", s);
+ }
+
+ /**
+ * Returns the image format for preview pictures.
+ *
+ * @return the PixelFormat int representing the preview picture format
+ */
+ public int getPreviewFormat() {
+ return pixelFormatForCameraFormat(get("preview-format"));
+ }
+
+ /**
+ * Sets the dimensions for pictures.
+ *
+ * @param width the width for pictures, in pixels
+ * @param height the height for pictures, in pixels
+ */
+ public void setPictureSize(int width, int height) {
+ String v = Integer.toString(width) + "x" + Integer.toString(height);
+ set("picture-size", v);
+ }
+
+ /**
+ * Returns the dimension setting for pictures.
+ *
+ * @return a Size object with the height and width setting
+ * for pictures
+ */
+ public Size getPictureSize() {
+ String pair = get("picture-size");
+ if (pair == null)
+ return null;
+ String[] dims = pair.split("x");
+ if (dims.length != 2)
+ return null;
+
+ return new Size(Integer.parseInt(dims[0]),
+ Integer.parseInt(dims[1]));
+
+ }
+
+ /**
+ * Sets the image format for pictures.
+ *
+ * @param pixel_format the desired picture format
+ * (<var>PixelFormat.YCbCr_422_SP</var>,
+ * <var>PixelFormat.RGB_565</var>, or
+ * <var>PixelFormat.JPEG</var>)
+ * @see android.graphics.PixelFormat
+ */
+ public void setPictureFormat(int pixel_format) {
+ String s = cameraFormatForPixelFormat(pixel_format);
+ if (s == null) {
+ throw new IllegalArgumentException();
+ }
+
+ set("picture-format", s);
+ }
+
+ /**
+ * Returns the image format for pictures.
+ *
+ * @return the PixelFormat int representing the picture format
+ */
+ public int getPictureFormat() {
+ return pixelFormatForCameraFormat(get("picture-format"));
+ }
+
+ private String cameraFormatForPixelFormat(int pixel_format) {
+ switch(pixel_format) {
+ case PixelFormat.YCbCr_422_SP: return "yuv422sp";
+ case PixelFormat.RGB_565: return "rgb565";
+ case PixelFormat.JPEG: return "jpeg";
+ default: return null;
+ }
+ }
+
+ private int pixelFormatForCameraFormat(String format) {
+ if (format == null)
+ return PixelFormat.UNKNOWN;
+
+ if (format.equals("yuv422sp"))
+ return PixelFormat.YCbCr_422_SP;
+
+ if (format.equals("rgb565"))
+ return PixelFormat.RGB_565;
+
+ if (format.equals("jpeg"))
+ return PixelFormat.JPEG;
+
+ return PixelFormat.UNKNOWN;
+ }
+
+ };
+}
+
+
diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl
new file mode 100644
index 0000000..b6ac3ab
--- /dev/null
+++ b/core/java/android/hardware/ISensorService.aidl
@@ -0,0 +1,30 @@
+/* //device/java/android/android/hardware/ISensorService.aidl
+**
+** Copyright 2008, 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.
+*/
+
+package android.hardware;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * {@hide}
+ */
+interface ISensorService
+{
+ ParcelFileDescriptor getDataChanel();
+ boolean enableSensor(IBinder listener, int sensor, int enable);
+ oneway void reportAccuracy(int sensor, int value);
+}
diff --git a/core/java/android/hardware/SensorListener.java b/core/java/android/hardware/SensorListener.java
new file mode 100644
index 0000000..d676a5e
--- /dev/null
+++ b/core/java/android/hardware/SensorListener.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package android.hardware;
+
+/**
+ * Used for receiving notifications from the SensorManager when
+ * sensor values have changed.
+ */
+public interface SensorListener {
+
+ /**
+ * Called when sensor values have changed.
+ * The length and contents of the values array vary
+ * depending on which sensor is being monitored.
+ * See {@link android.hardware.SensorManager SensorManager}
+ * for details on possible sensor types and values.
+ *
+ * @param sensor The ID of the sensor being monitored
+ * @param values The new values for the sensor
+ */
+ public void onSensorChanged(int sensor, float[] values);
+
+ /**
+ * Called when the accuracy of a sensor has changed.
+ * See {@link android.hardware.SensorManager SensorManager}
+ * for details.
+ *
+ * @param sensor The ID of the sensor being monitored
+ * @param accuracy The new accuracy of this sensor
+ */
+ public void onAccuracyChanged(int sensor, int accuracy);
+}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
new file mode 100644
index 0000000..9b88fff
--- /dev/null
+++ b/core/java/android/hardware/SensorManager.java
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package android.hardware;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.Surface;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Class that lets you access the device's sensors. Get an instance of this
+ * class by calling {@link android.content.Context#getSystemService(java.lang.String)
+ * Context.getSystemService()} with an argument of {@link android.content.Context#SENSOR_SERVICE}.
+ */
+public class SensorManager extends IRotationWatcher.Stub
+{
+ private static final String TAG = "SensorManager";
+
+ /** NOTE: sensor IDs must be a power of 2 */
+
+ /** A constant describing an orientation sensor.
+ * Sensor values are yaw, pitch and roll
+ *
+ * Yaw is the compass heading in degrees, range [0, 360[
+ * 0 = North, 90 = East, 180 = South, 270 = West
+ *
+ * Pitch indicates the tilt of the top of the device,
+ * with range -90 to 90.
+ * Positive values indicate that the bottom of the device is tilted up
+ * and negative values indicate the top of the device is tilted up.
+ *
+ * Roll indicates the side to side tilt of the device,
+ * with range -90 to 90.
+ * Positive values indicate that the left side of the device is tilted up
+ * and negative values indicate the right side of the device is tilted up.
+ */
+ public static final int SENSOR_ORIENTATION = 1 << 0;
+
+ /** A constant describing an accelerometer.
+ * Sensor values are acceleration in the X, Y and Z axis,
+ * where the X axis has positive direction toward the right side of the device,
+ * the Y axis has positive direction toward the top of the device
+ * and the Z axis has positive direction toward the front of the device.
+ *
+ * The direction of the force of gravity is indicated by acceleration values in the
+ * X, Y and Z axes. The typical case where the device is flat relative to the surface
+ * of the Earth appears as -STANDARD_GRAVITY in the Z axis
+ * and X and Z values close to zero.
+ *
+ * Acceleration values are given in SI units (m/s^2)
+ *
+ */
+ public static final int SENSOR_ACCELEROMETER = 1 << 1;
+
+ /** A constant describing a temperature sensor
+ * Only the first value is defined for this sensor and it
+ * contains the ambient temperature in degree C.
+ */
+ public static final int SENSOR_TEMPERATURE = 1 << 2;
+
+ /** A constant describing a magnetic sensor
+ * Sensor values are the magnetic vector in the X, Y and Z axis,
+ * where the X axis has positive direction toward the right side of the device,
+ * the Y axis has positive direction toward the top of the device
+ * and the Z axis has positive direction toward the front of the device.
+ *
+ * Magnetic values are given in micro-Tesla (uT)
+ *
+ */
+ public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
+
+ /** A constant describing an ambient light sensor
+ * Only the first value is defined for this sensor and it contains
+ * the ambient light measure in lux.
+ *
+ */
+ public static final int SENSOR_LIGHT = 1 << 4;
+
+ /** A constant describing a proximity sensor
+ * Only the first value is defined for this sensor and it contains
+ * the distance between the sensor and the object in meters (m)
+ */
+ public static final int SENSOR_PROXIMITY = 1 << 5;
+
+ /** A constant describing a Tricorder
+ * When this sensor is available and enabled, the device can be
+ * used as a fully functional Tricorder. All values are returned in
+ * SI units.
+ */
+ public static final int SENSOR_TRICORDER = 1 << 6;
+
+ /** A constant describing an orientation sensor.
+ * Sensor values are yaw, pitch and roll
+ *
+ * Yaw is the compass heading in degrees, 0 <= range < 360
+ * 0 = North, 90 = East, 180 = South, 270 = West
+ *
+ * This is similar to SENSOR_ORIENTATION except the data is not
+ * smoothed or filtered in any way.
+ */
+ public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
+
+ /** A constant that includes all sensors */
+ public static final int SENSOR_ALL = 0x7F;
+
+ /** Smallest sensor ID */
+ public static final int SENSOR_MIN = SENSOR_ORIENTATION;
+
+ /** Largest sensor ID */
+ public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
+
+
+ /** Index of the X value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int DATA_X = 0;
+ /** Index of the Y value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int DATA_Y = 1;
+ /** Index of the Z value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int DATA_Z = 2;
+
+ /** Offset to the raw values in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int RAW_DATA_INDEX = 3;
+
+ /** Index of the raw X value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int RAW_DATA_X = 3;
+ /** Index of the raw X value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int RAW_DATA_Y = 4;
+ /** Index of the raw X value in the array returned by
+ * {@link android.hardware.SensorListener#onSensorChanged} */
+ public static final int RAW_DATA_Z = 5;
+
+
+ /** Standard gravity (g) on Earth. This value is equivalent to 1G */
+ public static final float STANDARD_GRAVITY = 9.80665f;
+
+ /** values returned by the accelerometer in various locations in the universe.
+ * all values are in SI units (m/s^2) */
+ public static final float GRAVITY_SUN = 275.0f;
+ public static final float GRAVITY_MERCURY = 3.70f;
+ public static final float GRAVITY_VENUS = 8.87f;
+ public static final float GRAVITY_EARTH = 9.80665f;
+ public static final float GRAVITY_MOON = 1.6f;
+ public static final float GRAVITY_MARS = 3.71f;
+ public static final float GRAVITY_JUPITER = 23.12f;
+ public static final float GRAVITY_SATURN = 8.96f;
+ public static final float GRAVITY_URANUS = 8.69f;
+ public static final float GRAVITY_NEPTUN = 11.0f;
+ public static final float GRAVITY_PLUTO = 0.6f;
+ public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f;
+ public static final float GRAVITY_THE_ISLAND = 4.815162342f;
+
+
+ /** Maximum magnetic field on Earth's surface */
+ public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
+
+ /** Minimum magnetic field on Earth's surface */
+ public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
+
+
+ /** Various luminance values during the day (lux) */
+ public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
+ public static final float LIGHT_SUNLIGHT = 110000.0f;
+ public static final float LIGHT_SHADE = 20000.0f;
+ public static final float LIGHT_OVERCAST = 10000.0f;
+ public static final float LIGHT_SUNRISE = 400.0f;
+ public static final float LIGHT_CLOUDY = 100.0f;
+ /** Various luminance values during the night (lux) */
+ public static final float LIGHT_FULLMOON = 0.25f;
+ public static final float LIGHT_NO_MOON = 0.001f;
+
+ /** get sensor data as fast as possible */
+ public static final int SENSOR_DELAY_FASTEST = 0;
+ /** rate suitable for games */
+ public static final int SENSOR_DELAY_GAME = 1;
+ /** rate suitable for the user interface */
+ public static final int SENSOR_DELAY_UI = 2;
+ /** rate (default) suitable for screen orientation changes */
+ public static final int SENSOR_DELAY_NORMAL = 3;
+
+
+ /** The values returned by this sensor cannot be trusted, calibration
+ * is needed or the environment doesn't allow readings */
+ public static final int SENSOR_STATUS_UNRELIABLE = 0;
+
+ /** This sensor is reporting data with low accuracy, calibration with the
+ * environment is needed */
+ public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
+
+ /** This sensor is reporting data with an average level of accuracy,
+ * calibration with the environment may improve the readings */
+ public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
+
+ /** This sensor is reporting data with maximum accuracy */
+ public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
+
+
+
+ private static final int SENSOR_DISABLE = -1;
+ private static final int SENSOR_ORDER_MASK = 0x1F;
+ private static final int SENSOR_STATUS_SHIFT = 28;
+ private ISensorService mSensorService;
+ private Looper mLooper;
+
+ private static IWindowManager sWindowManager;
+ private static int sRotation = 0;
+
+ /* The thread and the sensor list are global to the process
+ * but the actual thread is spawned on demand */
+ static final private SensorThread sSensorThread = new SensorThread();
+ static final private ArrayList<ListenerDelegate> sListeners =
+ new ArrayList<ListenerDelegate>();
+
+
+ static private class SensorThread {
+
+ private Thread mThread;
+
+ // must be called with sListeners lock
+ void startLocked(ISensorService service) {
+ try {
+ if (mThread == null) {
+ ParcelFileDescriptor fd = service.getDataChanel();
+ mThread = new Thread(new SensorThreadRunnable(fd, service),
+ SensorThread.class.getName());
+ mThread.start();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in startLocked: ", e);
+ }
+ }
+
+ private class SensorThreadRunnable implements Runnable {
+ private ISensorService mSensorService;
+ private ParcelFileDescriptor mSensorDataFd;
+ private final byte mAccuracies[] = new byte[32];
+ SensorThreadRunnable(ParcelFileDescriptor fd, ISensorService service) {
+ mSensorDataFd = fd;
+ mSensorService = service;
+ Arrays.fill(mAccuracies, (byte)-1);
+ }
+ public void run() {
+ int sensors_of_interest;
+ float[] values = new float[6];
+ Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
+
+ synchronized (sListeners) {
+ _sensors_data_open(mSensorDataFd.getFileDescriptor());
+ try {
+ mSensorDataFd.close();
+ } catch (IOException e) {
+ // *shrug*
+ Log.e(TAG, "IOException: ", e);
+ }
+ mSensorDataFd = null;
+ //mSensorDataFd.
+ // the first time, compute the sensors we need. this is not
+ // a big deal if it changes by the time we call
+ // _sensors_data_poll, it'll get recomputed for the next
+ // round.
+ sensors_of_interest = 0;
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ sensors_of_interest |= sListeners.get(i).mSensors;
+ if ((sensors_of_interest & SENSOR_ALL) == SENSOR_ALL)
+ break;
+ }
+ }
+
+ while (true) {
+ // wait for an event
+ final int sensor_result = _sensors_data_poll(values, sensors_of_interest);
+ final int sensor_order = sensor_result & SENSOR_ORDER_MASK;
+ final int sensor = 1 << sensor_result;
+ int accuracy = sensor_result>>>SENSOR_STATUS_SHIFT;
+
+ if ((sensors_of_interest & sensor)!=0) {
+ // show the notification only if someone is listening for
+ // this sensor
+ if (accuracy != mAccuracies[sensor_order]) {
+ try {
+ mSensorService.reportAccuracy(sensor, accuracy);
+ mAccuracies[sensor_order] = (byte)accuracy;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in reportAccuracy: ", e);
+ }
+ } else {
+ accuracy = -1;
+ }
+ }
+
+ synchronized (sListeners) {
+ if (sListeners.isEmpty()) {
+ // we have no more listeners, terminate the thread
+ _sensors_data_close();
+ mThread = null;
+ break;
+ }
+ // convert for the current screen orientation
+ mapSensorDataToWindow(sensor, values, SensorManager.getRotation());
+ // report the sensor event to all listeners that
+ // care about it.
+ sensors_of_interest = 0;
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate listener = sListeners.get(i);
+ sensors_of_interest |= listener.mSensors;
+ if (listener.hasSensor(sensor)) {
+ // this is asynchronous (okay to call
+ // with sListeners lock held.
+ listener.onSensorChanged(sensor, values, accuracy);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private class ListenerDelegate extends Binder {
+
+ private SensorListener mListener;
+ private int mSensors;
+ private float[] mValuesPool;
+
+ ListenerDelegate(SensorListener listener, int sensors) {
+ mListener = listener;
+ mSensors = sensors;
+ mValuesPool = new float[6];
+ }
+
+ int addSensors(int sensors) {
+ mSensors |= sensors;
+ return mSensors;
+ }
+ int removeSensors(int sensors) {
+ mSensors &= ~sensors;
+ return mSensors;
+ }
+ boolean hasSensor(int sensor) {
+ return ((mSensors & sensor) != 0);
+ }
+
+ void onSensorChanged(int sensor, float[] values, int accuracy) {
+ float[] v;
+ synchronized (this) {
+ // remove the array from the pool
+ v = mValuesPool;
+ mValuesPool = null;
+ }
+
+ if (v != null) {
+ v[0] = values[0];
+ v[1] = values[1];
+ v[2] = values[2];
+ v[3] = values[3];
+ v[4] = values[4];
+ v[5] = values[5];
+ } else {
+ // the pool was empty, we need to dup the array
+ v = values.clone();
+ }
+
+ Message msg = Message.obtain();
+ msg.what = sensor;
+ msg.obj = v;
+ msg.arg1 = accuracy;
+ mHandler.sendMessage(msg);
+ }
+
+ private final Handler mHandler = new Handler(mLooper) {
+ @Override public void handleMessage(Message msg) {
+ if (msg.arg1 >= 0) {
+ try {
+ mListener.onAccuracyChanged(msg.what, msg.arg1);
+ } catch (AbstractMethodError e) {
+ // old app that doesn't implement this method
+ // just ignore it.
+ }
+ }
+ mListener.onSensorChanged(msg.what, (float[])msg.obj);
+ synchronized (this) {
+ // put back the array into the pool
+ if (mValuesPool == null) {
+ mValuesPool = (float[])msg.obj;
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * {@hide}
+ */
+ public SensorManager(Looper mainLooper) {
+ mSensorService = ISensorService.Stub.asInterface(
+ ServiceManager.getService(Context.SENSOR_SERVICE));
+
+ sWindowManager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService("window"));
+
+ if (sWindowManager != null) {
+ // if it's null we're running in the system process
+ // which won't get the rotated values
+ try {
+ sWindowManager.watchRotation(this);
+ } catch (RemoteException e) {
+ }
+ }
+
+ mLooper = mainLooper;
+ }
+
+ /** @return available sensors */
+ public int getSensors() {
+ return _sensors_data_get_sensors();
+ }
+
+ /**
+ * Registers a listener for given sensors.
+ *
+ * @param listener sensor listener object
+ * @param sensors a bit masks of the sensors to register to
+ *
+ * @return true if the sensor is supported and successfully enabled
+ */
+ public boolean registerListener(SensorListener listener, int sensors) {
+ return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
+ }
+
+ /**
+ * Registers a listener for given sensors.
+ *
+ * @param listener sensor listener object
+ * @param sensors a bit masks of the sensors to register to
+ * @param rate rate of events. This is only a hint to the system. events
+ * may be received faster or slower than the specified rate. Usually events
+ * are received faster.
+ *
+ * @return true if the sensor is supported and successfully enabled
+ */
+ public boolean registerListener(SensorListener listener, int sensors, int rate) {
+ boolean result;
+
+ int delay = -1;
+ switch (rate) {
+ case SENSOR_DELAY_FASTEST:
+ delay = 0;
+ break;
+ case SENSOR_DELAY_GAME:
+ delay = 20;
+ break;
+ case SENSOR_DELAY_UI:
+ delay = 60;
+ break;
+ case SENSOR_DELAY_NORMAL:
+ delay = 200;
+ break;
+ default:
+ return false;
+ }
+
+ try {
+ synchronized (sListeners) {
+ ListenerDelegate l = null;
+ for (ListenerDelegate i : sListeners) {
+ if (i.mListener == listener) {
+ l = i;
+ break;
+ }
+ }
+
+ if (l == null) {
+ l = new ListenerDelegate(listener, sensors);
+ result = mSensorService.enableSensor(l, sensors, delay);
+ if (result) {
+ sListeners.add(l);
+ sListeners.notify();
+ }
+ if (!sListeners.isEmpty()) {
+ sSensorThread.startLocked(mSensorService);
+ }
+ } else {
+ result = mSensorService.enableSensor(l, sensors, delay);
+ if (result) {
+ l.addSensors(sensors);
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in registerListener: ", e);
+ result = false;
+ }
+ return result;
+ }
+
+ /**
+ * Unregisters a listener for the sensors with which it is registered.
+ *
+ * @param listener a SensorListener object
+ * @param sensors a bit masks of the sensors to unregister from
+ */
+ public void unregisterListener(SensorListener listener, int sensors) {
+ try {
+ synchronized (sListeners) {
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate l = sListeners.get(i);
+ if (l.mListener == listener) {
+ // disable these sensors
+ mSensorService.enableSensor(l, sensors, SENSOR_DISABLE);
+ // if we have no more sensors enabled on this listener,
+ // take it off the list.
+ if (l.removeSensors(sensors) == 0)
+ sListeners.remove(i);
+ break;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in unregisterListener: ", e);
+ }
+ }
+
+ /**
+ * Unregisters a listener for all sensors.
+ *
+ * @param listener a SensorListener object
+ */
+ public void unregisterListener(SensorListener listener) {
+ unregisterListener(listener, SENSOR_ALL);
+ }
+
+
+ /**
+ * Helper function to convert the specified sensor's data to the windows's
+ * coordinate space from the device's coordinate space.
+ */
+
+ private static void mapSensorDataToWindow(int sensor, float[] values, int orientation) {
+ final float x = values[DATA_X];
+ final float y = values[DATA_Y];
+ final float z = values[DATA_Z];
+ // copy the raw raw values...
+ values[RAW_DATA_X] = x;
+ values[RAW_DATA_Y] = y;
+ values[RAW_DATA_Z] = z;
+ // TODO: add support for 180 and 270 orientations
+ if (orientation == Surface.ROTATION_90) {
+ switch (sensor) {
+ case SENSOR_ACCELEROMETER:
+ case SENSOR_MAGNETIC_FIELD:
+ values[DATA_X] =-y;
+ values[DATA_Y] = x;
+ values[DATA_Z] = z;
+ break;
+ case SENSOR_ORIENTATION:
+ case SENSOR_ORIENTATION_RAW:
+ values[DATA_X] = x + ((x < 270) ? 90 : -270);
+ values[DATA_Y] = z;
+ values[DATA_Z] = y;
+ break;
+ }
+ }
+ }
+
+
+ private static native int _sensors_data_open(FileDescriptor fd);
+ private static native int _sensors_data_close();
+ // returns the sensor's status in the top 4 bits of "res".
+ private static native int _sensors_data_poll(float[] values, int sensors);
+ private static native int _sensors_data_get_sensors();
+
+ /** {@hide} */
+ public void onRotationChanged(int rotation) {
+ synchronized(sListeners) {
+ sRotation = rotation;
+ }
+ }
+
+ private static int getRotation() {
+ synchronized(sListeners) {
+ return sRotation;
+ }
+ }
+}
+
diff --git a/core/java/android/hardware/package.html b/core/java/android/hardware/package.html
new file mode 100644
index 0000000..06788a6
--- /dev/null
+++ b/core/java/android/hardware/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Provides support for hardware devices that may not be present on every Android device.
+</BODY>
+</HTML>