Software Developer’s Guide for Sensors on Intel Atom based Android* Tablets

Abstract

This guide provides application developers with an introduction to the Android* Sensor framework and discusses how to use some of the generally available sensors in greater detail that are available on a typical Intel® Atom™ processor-based tablet. Among the sensors discussed are motion, position and environment sensors. Even though GPS is not strictly defined as a sensor, this guide discusses GPS-based location services.

1 Sensors on Intel® Atom™ Based Android* Tablets

The tablets based on Intel® Atom™ processor-based SoCs can support a wide range of hardware sensors. These sensors are used to detect the motion and position changes, and report the ambient environment parameters. The following block diagram shows a possible sensor configuration on a typical Intel Atom processor-based Android* tablet:


Figure 1-1 Sensors on an Intel® Atom™ SoC-based tablet

Based on the data they report, we can categorize tablet sensors into the following classes and types:

Table 1 1 Sensor types supported by the Android platform

CategorySensorDescriptionUsage
Motion Sensors Accelerometer (TYPE_ACCELEROMETER) Measures the device’s accelerations in m/s2 Motion detection
Gyroscope (TYPE_GYROSCOPE) Measures a device’s rates of rotation Rotation detection
Position Sensors Magnetometer (TYPE_MAGNETIC_FIELD) Measures the Earth geomagnetic field strengths in µT Compass
Proximity (TYPE_PROXIMITY) Measures the proximity of an object in cm Nearby object detection
GPS (not a type of android.hardware.Sensor) Gets the accurate geo- locations of the device Accurate geo-location detection
Environment Sensors ALS (TYPE_LIGHT) Measures the ambient light level in lx Automatic screen brightness control

2 Android* Sensor Framework

2.1 Overview

The Android* sensor framework provides mechanisms to access the sensors and sensor data, with the exception of the GPS, which is accessed through the Android* location services. We will discuss this later in this Guide. The Sensor framework is part of the android.hardware package. The following table lists the main classes and interfaces which the sensor framework consists of:

Table 2 1 The Android platform sensor framework

NameTypeDescription
SensorManager Class Used to create an instance of the sensor service. Provides various methods for accessing sensors, registering and unregistering sensor event listeners, etc.
Sensor Class Used to create an instance of a specific sensor.
SensorEvent Class Used by the system to publish sensor data. It includes the raw sensor data values, the sensor type, the data accuracy, and a timestamp.
SensorEventListener Class Provides callback methods to receive notifications from the SensorManager when the sensor data or the sensor accuracy has changed.

2.2 Obtaining Sensor Configuration

What sensors are available on the device is solely decided by the device manufacturer. You can use sensor framework to discover the available sensors at run time by invoking the SensorManager getSensorList() method with a parameter ‘Sensor.TYPE_ALL’. The following code displays a list of available sensors and the vendor, power, and accuracy information of each sensor on a fragment:

Code Example 2-1 A fragment which displays the list of sensors (**)

2.3 Sensor Coordinate System

The sensor framework reports sensor data using a standard 3-axis coordinate system, in which the X, Y, and Z are represented by the values[0], values[1], and values[2] in the SensorEvent object, respectively.

Some sensors return only a single value, for examples, the light sensor, the temperature sensor, and the proximity sensor. For these sensors only values[0] in the SensorEvent object is used.

Other sensors report data in the standard 3-axis sensor coordinate system. The following is a list of such sensors:

  • Accelerometer
  • Gravity sensor
  • Gyroscope
  • Geomagnetic field sensor

The 3-axis sensor coordinate system is defined relative to the screen of the device in its natural (default) orientation. Usually for tablets, the natural orientation is landscape, while for phones, the default orientation is portrait. When a device is held in its natural orientation, the X axis is horizontal and points to the right, the Y axis is vertical and points up, and the Z axis points outside of the screen (front) face. The following diagram shows the sensor coordinate system for a tablet:


Figure 2-1 The sensor coordinate system

The most important point regarding the sensor coordinate system is that the sensor’s coordinate system never changes when the device moves, or the device changes its orientation.

2.4 Monitoring Sensor Events

The sensor framework reports sensor data with the SensorEvent objects. A class can monitor a specific sensor’s data by implementing the SensorEventListener interface and registering with the SensorManager for the specific sensor. The sensor framework informs the class about the changes in the sensor states through the following two SensorEventListener callback methods implemented by the class:

onAccuracyChanged()

and

onSensorChanged()

The following code implements the SensorDialog used in the SensorInfoFragment example we discussed in Section 2.2.

package com.intel.deviceinfo;
 
import android.app.Dialog;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;
 
public class SensorDialog extends Dialog implements SensorEventListener {
    Sensor mSensor;
    TextView mDataTxt;
    private SensorManager mSensorManager;
     
 
    public SensorDialog(Context ctx, Sensor sensor) {
        this(ctx);
        mSensor = sensor;
    }
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDataTxt = (TextView) findViewById(R.id.sensorDataTxt);
        mDataTxt.setText("...");
        setTitle(mSensor.getName());
    }
     
    @Override
    protected void onStart() {
        super.onStart();
        mSensorManager.registerListener(this, mSensor,  SensorManager.SENSOR_DELAY_FASTEST);
    }
         
    @Override
    protected void onStop() {
        super.onStop();
        mSensorManager.unregisterListener(this, mSensor);
    }
 
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
 
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() != mSensor.getType()) {
            return;
        }
        StringBuilder dataStrBuilder = new StringBuilder();
        if ((event.sensor.getType() == Sensor.TYPE_LIGHT)||
            (event.sensor.getType() == Sensor.TYPE_TEMPERATURE)) {
            dataStrBuilder.append(String.format("Data: %.3fn", event.values[0]));
        }
        else{         
            dataStrBuilder.append( 
                String.format("Data: %.3f, %.3f, %.3fn", 
                event.values[0], event.values[1], event.values[2] ));
        }
        mDataTxt.setText(dataStrBuilder.toString());
    }
}

Code Example 2-2 A dialog which shows the sensor values (**)

2.5 Motion Sensors

Motion sensors are used to monitor device movement, such as shake, rotate, swing, or tilt. The accelerometer and gyroscope are two motion sensors available on many tablet and phone devices.

Motion sensors report data using the sensor coordinate system, with 3 values in the SensorEvent object: values[0], values[1], and values[2] represent values for the X, Y, and Z axes, respectively.

To understand the motion sensors and apply the data in an application, we need apply some physics formulas related to force, mass, acceleration, Newton’s Laws of Motion, and relationship between several of these entities in time. To learn more about these formulas and relationships, you may refer to physics textbooks or public domain sources.

2.5.1 Accelerometer

The accelerometer measures the acceleration applied on the device.

Table 2-2 The accelerometer

SensorTypeSensorEvent Data (m/s2)Description
Accelerometer TYPE_ACCELEROMETER values[0]
values[1]
values[2]
Acceleration along the x-axis
Acceleration along the y-axis
Acceleration along the z-axis

The concept for the accelerometer is derived from Newton’s second law of motion:

a = F / m

The acceleration of an object is the result of the net external force applied to the object. The external forces include the one that applied to all objects on Earth, the gravity. It is proportional to the net force F applied to the object and inversely proportional to the object’s mass m.

In our code, instead of directly using the above equation, we usually care about the result of the acceleration during a period of time on the device’s speed and position. The following equation describes the relationship of an object’s velocity v1, its original velocity v0, the acceleration a, and the time t:

v1 = v0 + at

To calculate the object’s position displacement s, we use the following equation:

s = v0t + (1/2)at2

In many cases we start with the condition v0 is 0 (before the device starts moving), which simplifies the equation as:

s = at2/2

Because of the gravity, the gravitational acceleration, which is represented with the symbol g, is applied to any object on Earth. Regardless of the object’s mass, g only depends on the latitude of the object’s location with a value in the range of 9.78 to 9.82 (m/s2). We adopt a conventional standard value for g:

g = 9.80665 (m/s2)

Because the accelerometer returns the values using a multi-dimensional device coordinate system, in our code we can calculate the distances along the x, y, and z axes using the following equations:

Sx = AxT2/2

Sy = AyT2/2

Sz = AzT2/2

Where Sx, Sy, and Sz are the displacements on the x-axis, y-axis, and z-axis, respectively, and Ax, Ay, and Az are the accelerations on the x-axis, y-axis, and z-axis, respectively. T is the time of the measurement period.

The following code shows how to instantiate an accelerometer:

public class SensorDialog extends Dialog implements SensorEventListener {
    …   
    private Sensor mSensor;
    private SensorManager mSensorManager;
     
    public SensorDialog(Context context) {
        super(context);
        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    …
}

Code Example 2-3 Instantiation of an accelerometer (**)

Sometimes we don’t use all three dimension data values. Sometimes we may also need to take the device’s orientation into consideration. For example, when we develop a “Labyrinth maze” application, we only use the x-axis and the y-axis gravitational acceleration to calculate the ball’s moving directions and distances based on the orientation of the device. The following code fragment outlines the logic:

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
        return;
    } 
float accelX, accelY;
…
//detect the current rotation currentRotation from its “natural orientation”
//using the WindowManager
    switch (currentRotation) {
        case Surface.ROTATION_0:
            accelX = event.values[0];
            accelY = event.values[1];
            break;
        case Surface.ROTATION_90:
            accelX = -event.values[0];
            accelY = event.values[1];
            break;
        case Surface.ROTATION_180:
            accelX = -event.values[0];
            accelY = -event.values[1];
            break;
        case Surface.ROTATION_270:
            accelX = event.values[0];
            accelY = -event.values[1];
            break;
    }
    //calculate the ball’s moving distances along x, and y using accelX, accelY and the time delta
        …
    }
}

Code Example 2-4 Considering the device orientation when using the accelerometer data in a Maze game (**)

2.5.2 Gyroscope

The gyroscope (also called gyro) measures the device’s rate of rotation around the x, y, and z axis. The gyroscope data values can be positive or negative. By looking at the origin from a position along the positive half of the axis, if the rotation is counter-clockwise around the axis, the value is positive; if the rotation around the axis is clockwise, the value is negative. We can also determine the direction of a gyroscope value using the “right-hand rule”:


Figure 2-2 Using the “right hand rule” to decide the positive rotation direction

Table 2-3 The gyroscope

SensorTypeSensorEvent Data (rad/s)Description
Gyroscope TYPE_GYROSCOPE values[0]
values[1]
values[2]
Rotation rate around the x-axis
Rotation rate around the y-axis
Rotation rate around the z-axis

The following code shows how to instantiate a gyroscope:

public class SensorDialog extends Dialog implements SensorEventListener {
    …   
    private Sensor mGyro;
    private SensorManager mSensorManager;
     
    public SensorDialog(Context context) {
        super(context);
        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        mGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    …
}

Code Example 2 5 Instantiation of a gyroscope (**)

2.6 Position Sensors

Many Android tablets support two position sensors: the magnetometer and the proximity sensor. The magnetometer measures the strengths of the Earth magnetic field along the x, y, and z axis, while the proximity sensor detects the distance of the device from another object.

2.6.1 Magnetometer

The most important usage of the magnetometer is used by the Android* system to implement the compass.

SensorTypeSensorEvent Data (µT)Description
Magnetometer TYPE_MAGNETIC_FIELD values[0]
values[1]
values[2]
Earth magnetic field strength along the x-axis
Earth magnetic field strength along the y-axis
Earth magnetic field strength along the z-axis

The following example shows how to instantiate a magnetometer:

public class SensorDialog extends Dialog implements SensorEventListener {
    …   
    private Sensor mMagnetometer;
    private SensorManager mSensorManager;
     
    public SensorDialog(Context context) {
        super(context);
        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    …
}

Code Example 2 6 instantiation of a magnetometer (**)

2.6.2 Proximity

The proximity sensor provides the distance between the device and another object. The device can use it to detect if the device is being held close to the user, thus determine if the user is making or receiving phone calls.

SensorTypeSensorEvent DataDescription
Proximity TYPE_PROXIMITY values[0] Distance from an object in cm. Some proximity sensors only report a Boolean value to indicate if the object is close enough.

The following code shows how to instantiate a proximity sensor:

public class SensorDialog extends Dialog implements SensorEventListener {
    …   
    private Sensor mProximity;
    private SensorManager mSensorManager;
     
    public SensorDialog(Context context) {
        super(context);
        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
        mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
    …
}

Code Example 2 7 instantiation of a proximity sensor (**)

2.7 Environment Sensors

The environment sensors detect and report the device’s ambient environment parameters, such as the light, temperature, pressure, or humidity. The availability of a specific sensor is solely determined by the device manufacturer. The ambient light sensor (ALS) is available on many Android* tablets.

2.7.1 Ambient Light Sensor (ALS))

The ambient light sensor is used by the system to detect the illumination of the surrounding environment and automatically adjust the screen brightness accordingly.

SensorTypeSensorEvent Data(lx)Description
ALS TYPE_LIGHT values[0] The illumination around the device

The following code shows how to instantiate the ALS:

…   
private Sensor mALS;
private SensorManager mSensorManager;
 
…   
    mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
    mALS = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
…

Code Example 2-8 instantiation of an ambient light sensor (**)

2.8 Sensors Performance and Optimization Guidelines

To use sensors in your applications, you should follow the following best practices:

  • Always check the specific sensor’s availability before using it
    Android* platform does not require the inclusion or exclusion of a specific sensor on the device. The sensor configuration is solely decided by the device manufacturer. Before using a sensor in your application, always first check if it is actually available.
  • Always unregister the sensor listeners
    If the activity which implements the sensor listener is becoming invisible, or the dialog is stopping, unregister the sensor listener. It can be done via the activity’s onPause() method, or in the dialog’s onStop() method. Otherwise, the sensor will continue acquiring data and as a result drain the battery.
  • Don’t block the onSensorChanged() method
    The onSensorChanged() method is frequently called by the system to report the sensor data. There should be as little logic inside this method as possible. Complicated calculations with the sensor data should be moved outside of this method.
  • Always test your sensor applications on real devices
    All sensors described in this section are hardware sensors. The Android Emulator may not be good enough to simulate the sensor’s functions and performance.

3 GPS and Location

GPS (Global Positioning System) is a satellite-based system which provides accurate geo-location information around the world. GPS is available on many Android* tablets. In many perspectives GPS behaves like a position sensor. It can provide accurate location data available for the applications running on the device. On Android* platform, GPS is not directly managed by the sensor framework. Instead, the Android* location service accesses and transfers GPS data to an application through the location listener callbacks.

3.1 Android* Location Services

SensorTypeDescription
LocationManager Class Used to access location services. Provides various methods for requesting periodic location updates for an application, or sending proximity alerts
LocationProvider Abstract class The abstract super class for location providers
Location Class Used by the location providers to encapsulate geographical data
LocationListener Interface Used to receive location notifications from the LocationManager

3.2 Obtaining GPS Location Updates

Similar to the mechanism of using the sensor framework to access sensor data, the application implements several callback methods defined in the LocationListener interface to receive GPS location updates. The LocationManager sends GPS update notifications to the application through these callbacks (the “Don’t call us, we will call you” rule).

To access GPS location data in the application, you need to request the fine location access permission in your Android* manifest file:

< manifest … >
…
    < uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
…  
< /manifest >

Code Example 3-1 Requesting the fine location access permission in the manifest file (**)

The following example code shows how to get GPS updates and display the latitude and longitude coordinates on a dialog text view:

package com.intel.deviceinfo;
 
import android.app.Dialog;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
 
public class GpsDialog extends Dialog implements LocationListener {
    TextView mDataTxt;
    private LocationManager mLocationManager;
     
    public GpsDialog(Context context) {
        super(context);
        mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
           mDataTxt = (TextView) findViewById(R.id.sensorDataTxt);
          mDataTxt.setText("...");
         
        setTitle("Gps Data");
    }
     
    @Override
    protected void onStart() {
        super.onStart();
        mLocationManager.requestLocationUpdates(
            LocationManager.GPS_PROVIDER, 0, 0, this);
    }
         
    @Override
    protected void onStop() {
        super.onStop();
        mLocationManager.removeUpdates(this);
        }
 
    @Override
    public void onStatusChanged(String provider, int status, 
        Bundle extras) {
    }
 
    @Override
    public void onProviderEnabled(String provider) {
    }
 
    @Override
    public void onProviderDisabled(String provider) {
    }
 
    @Override
    public void onLocationChanged(Location location) {
        StringBuilder dataStrBuilder = new StringBuilder();
        dataStrBuilder.append(String.format("Latitude: %.3f,   Logitude%.3fn", location.getLatitude(), location.getLongitude()));
        mDataTxt.setText(dataStrBuilder.toString());
         
    }
}

Code Example 3 2 A dialog which displays the GPS location data (**)

3.3 GPS and Location Performance and Optimization Guidelines

GPS provides most accurate location information on the device. On the other hand, as a hardware feature, it consumes extra energy. It also takes time for the GPS to get the first location fix. Here are some guidelines you should follow when developing GPS and location aware applications:

  • Consider all available location providers
    Besides the GPS_PROVIDER, there is also NETWORK_PROVIDER. If your applications only need the coarse location data, you may consider using the NETWORK_PROVIDER.
  • Use the cached locations
    It takes time for the GPS to get the first location fix. When your application is waiting for the GPS to get an accurate location update, you can first use the locations provided by the LocationManager’s getlastKnownLocation() method to perform part of the works.
  • Minimize the frequency and duration of location update requests
    You should request the location update only when needed, and promptly de-register from the location manager once you no longer need location updates.

4 Summary

Android* platform provides APIs for the developers to access the device’s built-in sensors. These sensors are capable of providing raw data about the device’s current motion, position, and ambient environment conditions with high precision and accuracy. In developing sensor applications, you should follow the best practices to improve the performance and power efficiency.

Acknowledgements

The author thanks his colleague Nathan Totura, who provided the source code used in this Guide’s examples.

About the Author

Miao Wei is a software engineer with the Software and Services Group of Intel Corporation.

Notices

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.

The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.

Copies of documents which have an order number and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-4725, or go
to: http://www.intel.com/design/literature.htm

Intel, and the Intel logo are trademarks of Intel Corporation in the U.S. and other countries.

*Other names and brands may be claimed as the property of others

**This sample source code is released under the Intel Sample Source Code License Agreement

Copyright© 2012 Intel Corporation. All rights reserved.

如需更全面地了解编译器优化,请参阅优化注意事项