虽然这篇文章写得很差,因为赶时间,所以就匆匆忙忙地写出来自己作一个笔记。但是我想对大家应该有一点帮助。
1
、有关
sensor
在
Java
应用程序的编程(以注册多个传感器为例,这程序是我临时弄出来的,可能有错)
package
com.sensors.acc;
import
android.app.Activity;
import
android.os.Bundle;
import
android.util.Log;
import
android.widget.TextView;
import
android.hardware.SensorManager;
import
android.hardware.Sensor;
import
android.hardware.SensorEvent;
import
android.hardware.SensorEventListener;
public
class
acc
extends
Activity {
float
x
,
y
,
z
;
SensorManager
sensormanager
=
null
;
Sensor
accSensor
=
null
;
Sensor
lightSensor
=
null
;
Sensor
proximitySensor
=
null
;
TextView
accTextView
=
null
;
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.
main
);
sensormanager
= (SensorManager)getSystemService(
SENSOR_SERVICE
);
accSensor
=
sensormanager
.getDefaultSensor(Sensor.
TYPE_ACCELEROMETER
);
lightSensor
=
sensormanager
.getDefaultSensor(Sensor.
TYPE_LIGHT
);
proximitySensor
=
sensormanager
.getDefaultSensor(Sensor.
TYPE_PROXIMITY
);
accTextView
= (TextView)findViewById(R.id.
textview_name
);
}
SensorEventListener
lsn
=
new
SensorEventListener() {
public
void
onSensorChanged(SensorEvent e) {
if
(e.
sensor
==
accSensor
) {
Log.
d
(
“sensor”
,
“found acc sensor”
);
x
= e.
values
[SensorManager.
DATA_X
];
y
= e.
values
[SensorManager.
DATA_Y
];
z
= e.
values
[SensorManager.
DATA_Z
];
accTextView
.setText(
“x = ”
+
x
+
“, /ny = ”
+
y
+
“, /nz = ”
+
z
);
}
else
if
(e.
sensor
==
lightSensor
) {
Log.
d
(
“sensor”
,
“found light sensor”
);
accTextView
.setText(
“data is ”
+ e.
values
[0]);
}
else
if
(e.
sensor
==
proximitySensor
) {
Log.
d
(
“sensor”
,
“found proximity sensor”
);
accTextView
.setText(
“distance is ”
+ e.
values
[0]);
}
//
Log.d(“sensor”, “found
acc
sensor”);
//
Log.d(“sensor”, “x = ” + x + “, y = ” + y + “, z = ” + z);
//
accTextView.setText(“x = ” + x + “, /
ny
= ” + y + “, /
nz
= ” + z);
}
public
void
onAccuracyChanged(Sensor s,
int
accuracy) {
}
};
@Override
protected
void
onResume() {
super
.onResume();
// register this class as a listener for the orientation and accelerometer sensors
sensormanager
.registerListener(
lsn
,
accSensor
, SensorManager.
SENSOR_DELAY_NORMAL
);
sensormanager
.registerListener(
lsn
,
lightSensor
, SensorManager.
SENSOR_DELAY_NORMAL
);
sensormanager
.registerListener(
lsn
,
proximitySensor
, SensorManager.
SENSOR_DELAY_NORMAL
);
//
sensormanager.unregisterListener(
lsn
);
}
@Override
protected
void
onStop() {
// unregister listener
sensormanager
.unregisterListener(
lsn, accSensor
);
sensormanager.unregisterListener(lsn, lightSensor);
sensormanager.unregisterListener(lsn, proximitySensor);
super
.onStop();
}
}
在
onCreate()
函数中,调用
getSystemService(
SENSOR_SERVICE
)
初始化一个
SensorManager
实例,为什么要用
getSystemService
函数,而不直接用
new SensorManager
呢?我们看此函数的实现,在
ApplicationContext.java
中,
if (SENSOR_SERVICE.equals(name)) {
return getSensorManager();
然后
getSensorManager()
的实现
private SensorManager getSensorManager() {
synchronized (mSync) {
if (mSensorManager == null) {
mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
}
}
return mSensorManager;
}
看到没有?初始化
SensorManager
的时候需要
mMainThread.getHandler().getLooper()
这个参数,之个应该是用来传递消息用的,在
SensorManager
类的构造函数中会把此参数传给类成员
mMainLooper
。如果用
new SensorManager()
就需要另外获取
mainLooper
参数传递进去。
2
、在
android
中跟
sensor
有关的一些文件有
SensorManager.java
,位于
frameworks/base/core/java/android/hardware
目录下,
SensorService.java
,位于
frameworks/base/services/java/com/android/server
目录下,
android_hardware_SensorManager.cpp
,位于
frameworks/base/core/jni/
目录下,与
SensorManager.java
相对应,
com_android_server_SensorService.cpp
,在
frameworks/base/services/jni/
目录下,与
SensorService.java
相对应。还有
SystemServer.java
文件,
Hardware/Libhardware/Include/Hardware
目录下的
Sensor.h
头文件。另外我们需要根据
Sensor.h
实现自己的一个源文件,一般取名为
sensors_xxx.c
或者
sensors_xxx.cpp
。
3
、
SensorManager
类分析
有几个函数比较重要,必须清晰理解它们的实现,才能了解整个传感器系统的实现。从而更好地去实现硬件抽象层的实现。几个比较重要的函数有构造函数
SensorManager(), registerListener()
和
unregisterListener()
,其中
registerListener()
和
unregisterListener()
有多个,标志为
@Deprecated
的是过时的,就不要看了。
(
1
)构造函数
SensorManager(Looper mainLooper)
这个函数首先获取得传感器系统服务,并赋给类成员
mSensorService
,
mSensorService = ISensorService.Stub.asInterface(
ServiceManager.getService(Context.SENSOR_SERVICE));
这里我要说一句,就是关于这个传感器系统服务,很多书上都说用
getSystemService()
是获得传感器的系统服务,而它返回的是
SensorManager
类型,所以以为整个系统都是使用同一个
SensorManager
类的实例,以为我们在任何地方使用的
SensorManager
实例都是同一个,它们的公共成员是共享的。但是经过这两天的分析,这种说法是错误的。其实每次调用
getSystemService()
函数时都初始化一个新的
SensorManager
实例,而这个
SensorManager
实例会在构造函数里通过取得传感器系统服务
SensorService
来实现对下层传感器的一些控制。而这个
SensorService
才是系统的传感器服务,说服务,不如说它只是
SensorService
类的一个实例罢了。它只在系统初始化时初始化一次。
Android
中的系统服务机制应该跟传感器的都差不多一个样,都是由不同的
Manager
调用下层相同的
Service
。你可以列举其它的
Manager
。那它是什么时候初始化呢?它是系统初始化在
SystemServer
进程里创建的,
SystemServer
是一个管理很多系统服务的进程,我们转到
SystemServer.
的
main
函数里,可以看到一直到调用
int2()
函数,它会创建一个
ServerThread
,最终调用
AdbSettingsObserver
类的
run()
函数,在
run()
函数里有这么有一句
// Sensor Service is needed by Window Manager, so this goes first
Log.i(TAG, “Sensor Service”);
ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));
这里就创建
SensorService
实例了。在创建这个实例时会在
SensorService
构造函数中调用
jni
函数
public SensorService(Context context) {
if (localLOGV) Log.d(TAG, “SensorService startup”);
_sensors_control_init();
}
我们看
_sensors_control_init();
对应的为
static jint
android_init(JNIEnv *env, jclass clazz)
{
sensors_module_t* module;
if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
if (sensors_control_open(&module->common, &sSensorDevice) == 0) {
const struct sensor_t* list;
int count = module->get_sensors_list(module, &list);
return count;
}
}
return 0;
}
它主要调用了
sensor.h
中的
sensors_control_open()
static inline int sensors_control_open(const struct hw_module_t* module,
struct sensors_control_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);
}
之后在系统任何地方使用的都是这个
SensorService
实例。最后
run()
函数调用
Looper.loop();
就进行消息循环等待了,这就是
SystemServer
进程的消息服务了。这才真正叫做系统服务嘛。
我们继续看
SensorManager
类的构造函数,取得
SensorService
后,
nativeClassInit();
这是一个
jni
函数,
SensorManager
类调用的
jni
函数都在
com_android_server_SensorService.cpp
里,我们看这函数
static void
nativeClassInit (JNIEnv *_env, jclass _this)
{
jclass sensorClass = _env->FindClass(“android/hardware/Sensor”);
SensorOffsets& sensorOffsets = gSensorOffsets;
sensorOffsets.name
= _env->GetFieldID(sensorClass, “mName”,
“Ljava/lang/String;”);
sensorOffsets.vendor
= _env->GetFieldID(sensorClass, “mVendor”,
“Ljava/lang/String;”);
sensorOffsets.version
= _env->GetFieldID(sensorClass, “mVersion”,
“I”);
sensorOffsets.handle
= _env->GetFieldID(sensorClass, “mHandle”,
“I”);
sensorOffsets.type
= _env->GetFieldID(sensorClass, “mType”,
“I”);
sensorOffsets.range
= _env->GetFieldID(sensorClass, “mMaxRange”,
“F”);
sensorOffsets.resolution
= _env->GetFieldID(sensorClass, “mResolution”,”F”);
sensorOffsets.power
= _env->GetFieldID(sensorClass, “mPower”,
“F”);
}
这个函数只是获取和设置一些信息吧,我们不关心。接着
sensors_module_init();
我们看这函数
static jint
sensors_module_init(JNIEnv *env, jclass clazz)
{
int err = 0;
sensors_module_t const* module;
err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
if (err == 0)
sSensorModule = (sensors_module_t*)module;
return err;
}
它获取了
sensor
的模块信息,并把它赋给
sSensorModule
全局变量,之后传的
modules
参数都为这个。
接着在构造函数里
final ArrayList<Sensor> fullList = sFullSensorsList;
int i = 0;
do {
Sensor sensor = new Sensor();
i = sensors_module_get_next_sensor(sensor, i);
if (i>=0) {
Log.d(TAG, “found sensor: ” + sensor.getName() +
“, handle=” + sensor.getHandle());
sensor.setLegacyType(getLegacySensorType(sensor.getType()));
fullList.add(sensor);
sHandleToSensor.append(sensor.getHandle(), sensor);
}
} while (i>0);
这里主要是通过
jni
函数
sensors_module_get_next_sensor(sensor, i);
获取传感器列表,并把它加入自己的
fullList
列表中。我们看
sensors_module_get_next_sensor()
函数
static jint
sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
{
if (sSensorModule == NULL)
return 0;
SensorOffsets& sensorOffsets = gSensorOffsets;
const struct sensor_t* list;
int count = sSensorModule->get_sensors_list(sSensorModule, &list);
if (next >= count)
return -1;
list += next;
jstring name = env->NewStringUTF(list->name);
jstring vendor = env->NewStringUTF(list->vendor);
env->SetObjectField(sensor, sensorOffsets.name,
name);
env->SetObjectField(sensor, sensorOffsets.vendor,
vendor);
env->SetIntField(sensor, sensorOffsets.version,
list->version);
env->SetIntField(sensor, sensorOffsets.handle,
list->handle);
env->SetIntField(sensor, sensorOffsets.type,
list->type);
env->SetFloatField(sensor, sensorOffsets.range,
list->maxRange);
env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
env->SetFloatField(sensor, sensorOffsets.power,
list->power);
next++;
return next<count ? next : 0;
}
它主要是调用
HAL
层的
get_sensors_list()
函数取得传感器列表信息。
接着在
sensorManger
构造函数最后
sSensorThread = new SensorThread();
创建一个
SensorThread()
线程。但并未运行,但在
SensorThread
类的构造函数里会执行
jni
函数
sensors_data_init();
我们看此函数
static jint
sensors_data_init(JNIEnv *env, jclass clazz)
{
if (sSensorModule == NULL)
return -1;
int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
return err;
}
它调用了
HAL
层的
sensors_data_open
函数,而这个函数位于
sensor.h
中,它调用的是
static inline int sensors_data_open(const struct hw_module_t* module,
struct sensors_data_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);
}
Modules->methods->open
函数。而在
SensorThread
类的析构函数
finalize()
里会调用
sensors_data_uninit();
static jint
sensors_data_uninit(JNIEnv *env, jclass clazz)
{
int err = 0;
if (sSensorDevice) {
err = sensors_data_close(sSensorDevice);
if (err == 0)
sSensorDevice = 0;
}
return err;
}
在
sensor.h
里
static inline int sensors_data_close(struct sensors_data_device_t* device) {
return device->common.close(&device->common);
}
那什么时候
sSensorThread
线程会运行呢?我们在下面看
registerListener()
函数。
(
2
)
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
return registerListener(listener, sensor, rate, null);
}
它调用的是
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
Handler handler)
在这函数中,先验证
rate
,然后检测注册的
listener
在不在本类的
sListeners
列表中。
for (ListenerDelegate i : sListeners) {
if (i.getListener() == listener) {
l = i;
break;
}
}
如果不在就申请一个
listener
,并把它加入全局列表
sListener
中,并调用
mSensorService
的
enableSensor()
函数使能传感器,这个
enableSensor()
函数最终会调用
HAL
层的
active
函数和
set_delay()
函数,使用后然后判断
sListener
列表是否为空,当然,第一次为空时加入一个新的
listener
就不为空了,此时就执行
sSensorThread
的
startLocked
运行
sSensorThread
线程了
l = new ListenerDelegate(listener, sensor, handler);
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
sListeners.add(l);
sListeners.notify();
}
if (!sListeners.isEmpty()) {
sSensorThread.startLocked(mSensorService);
}
另一方面,如果注册的
listener
在
sListeners
列表中,则先调用
mSensorService
的
enableSensor()
函数使能传感器,然后把注册的传感器加入到已存在的
listener
中。
result = mSensorService.enableSensor(l, name, handle, delay);
if (result) {
l.addSensor(sensor);
}
接下来我们看看
startLocked
函数,它在
SensorThread
中,
void startLocked(ISensorService service) {
try {
if (mThread == null) {
Bundle dataChannel = service.getDataChannel();
mThread = new Thread(new SensorThreadRunnable(dataChannel),
SensorThread.class.getName());
mThread.start();
}
} catch (RemoteException e) {
Log.e(TAG, “RemoteException in startLocked: “, e);
}
}
第一次
mThread
为
null
,然后它调用了
service.getDataChannel()
函数,此函数在
SensorService
类中,主要调用了
jni
函数
_sensors_control_open()
,
public Bundle getDataChannel() throws RemoteException {
// synchronize so we do not require sensor HAL to be thread-safe.
synchronized(mListeners) {
return _sensors_control_open();
}
}
SensorService
类中调用的
jni
函数主要都在
com_android_server_SensorService.cpp
文件
中,我们看一下这个函数
static jobject
android_open(JNIEnv *env, jclass clazz)
{
native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
if (!handle) {
return NULL;
}
// new Bundle()
jobject bundle = env->NewObject(
gBundleOffsets.mClass,
gBundleOffsets.mConstructor);
if (handle->numFds > 0) {
jobjectArray fdArray = env->NewObjectArray(handle->numFds,
gParcelFileDescriptorOffsets.mClass, NULL);
for (int i = 0; i < handle->numFds; i++) {
// new FileDescriptor()
jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
gFileDescriptorOffsets.mConstructor);
env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
// new ParcelFileDescriptor()
jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
gParcelFileDescriptorOffsets.mConstructor, fd);
env->SetObjectArrayElement(fdArray, i, pfd);
}
// bundle.putParcelableArray(“fds”, fdArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
env->NewStringUTF(“fds”), fdArray);
}
if (handle->numInts > 0) {
jintArray intArray = env->NewIntArray(handle->numInts);
env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
// bundle.putIntArray(“ints”, intArray);
env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
env->NewStringUTF(“ints”), intArray);
}
// delete the file handle, but don’t close any file descriptors
native_handle_delete(handle);
return bundle;
}
它主要调用了
HAL
层的
open_data_source()
函数。取得一些文件描述符等信息。
接下来
SensorThread
创建一个线程,调用
start()
就进入
SensorThreadRunnable
类的
run()
函数了,所以我们接着去看
run()
函数,它首先调用
open()
函数
if (!open()) {
return;
}
在
open()
函数中调用了
jni
函数
sensors_data_open(fds, ints);
static jint
sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
{
jclass FileDescriptor = env->FindClass(“java/io/FileDescriptor”);
jfieldID fieldOffset = env->GetFieldID(FileDescriptor, “descriptor”, “I”);
int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
native_handle_t* handle = native_handle_create(numFds, numInts);
int offset = 0;
for (int i = 0; i < numFds; i++) {
jobject fdo = env->GetObjectArrayElement(fdArray, i);
if (fdo) {
handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
} else {
handle->data[offset++] = -1;
}
}
if (numInts > 0) {
jint* ints = env->GetIntArrayElements(intArray, 0);
for (int i = 0; i < numInts; i++) {
handle->data[offset++] = ints[i];
}
env->ReleaseIntArrayElements(intArray, ints, 0);
}
// doesn’t take ownership of the native handle
return sSensorDevice->data_open(sSensorDevice, handle);
}
这函数最终调用了
HAL
层的
data_open()
,之后
run()
函数就进入一个
while
循环了。
while (true) {
// wait for an event
final int sensor = sensors_data_poll(values, status, timestamp);
int accuracy = status[0];
synchronized (sListeners) {
if (sensor == -1 || sListeners.isEmpty()) {
if (sensor == -1) {
// we lost the connection to the event stream. this happens
// when the last listener is removed.
Log.d(TAG, “_sensors_data_poll() failed, we bail out.”);
}
// we have no more listeners or polling failed, terminate the thread
sensors_data_close();
mThread = null;
break;
}
final Sensor sensorObject = sHandleToSensor.get(sensor);
if (sensorObject != null) {
// report the sensor event to all listeners that
// care about it.
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate listener = sListeners.get(i);
if (listener.hasSensor(sensorObject)) {
// this is asynchronous (okay to call
// with sListeners lock held).
listener.onSensorChangedLocked(sensorObject,
values, timestamp, accuracy);
}
}
}
}
它调用了
jni
函数
sensors_data_poll()
一直读数据。
static jint
sensors_data_poll(JNIEnv *env, jclass clazz,
jfloatArray values, jintArray status, jlongArray timestamp)
{
sensors_data_t data;
int res = sSensorDevice->poll(sSensorDevice, &data);
if (res >= 0) {
jint accuracy = data.vector.status;
env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
env->SetIntArrayRegion(status, 0, 1, &accuracy);
env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
}
return res;
}
把传感器得到的值都放在
value
数组中,根据返回的传感器标志
sensor
,把它分派给在
sListener
列表中所有的
listener
,如果
listener
中有监听这个
sensor
,就把它分派给这个
listener
,此时就会引起
onSensorChange()
了。
好了,获取传感器数据主要是这样一个途径。最后我们去分析一下
unregisterListener()
函数。
private void unregisterListener(Object listener) {
if (listener == null) {
return;
}
try {
synchronized (sListeners) {
final int size = sListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate l = sListeners.get(i);
if (l.getListener() == listener) {
// disable all sensors for this listener
for (Sensor sensor : l.getSensors()) {
String name = sensor.getName();
int handle = sensor.getHandle();
mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
}
sListeners.remove(i);
break;
}
}
}
} catch (RemoteException e) {
Log.e(TAG, “RemoteException in unregisterListener: “, e);
}
}
不用想这个函数会做一些与
registerListener
相反的事情,至少差不多。它先在
sListeners
列表中找到这个
listener
,然后先调用
enableSensor()
函数禁止这个传感器。我们跟踪一下这函数,在
SensorService
类中。
synchronized(mListeners) {
if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {
Log.w(TAG, “could not enable sensor ” + sensor);
return false;
}
Listener l = null;
int minDelay = enable;
for (Listener listener : mListeners) {
if (binder == listener.mToken) {
l = listener;
}
if (minDelay > listener.mDelay)
minDelay = listener.mDelay;
}
if (l == null && enable!=SENSOR_DISABLE) {
l = new Listener(binder);
binder.linkToDeath(l, 0);
mListeners.add(l);
mListeners.notify();
}
if (l == null) {
// by construction, this means we’re disabling a listener we
// don’t know about…
Log.w(TAG, “listener with binder ” + binder +
“, doesn’t exist (sensor=” + name + “, id=” + sensor + “)”);
return false;
}
if (minDelay >= 0) {
_sensors_control_set_delay(minDelay);
}
if (enable != SENSOR_DISABLE) {
l.addSensor(sensor, enable);
} else {
l.removeSensor(sensor);
deactivateIfUnusedLocked(sensor);
if (l.mSensors == 0) {
mListeners.remove(l);
binder.unlinkToDeath(l, 0);
mListeners.notify();
}
}
if (mListeners.size() == 0) {
_sensors_control_wake();
_sensors_control_close();
}
}
return true;
你们看到它的实现了吧。如果
enable
是
true
的话,就调用
_sensors_control_activate()
,如果是
false
的话,就调用
deactivateIfUnusedLocked()
,它们最终都会调用
HAL
层的
active()
函数。最后,如果是禁止传感器的话,如果
mListeners
为空了,它就会调用
_sensors_control_wake();
_sensors_control_close();
这两个
jni
函数,最终会调用
HAL
层的
wake()
和
close_data_source()
函数。当调用
wake()
函数时,会使
SensorManager
类线程的
run()
函数中的
sensor_data_poll()
函数立即返回,此时在
run()
函数中调用
sensors_data_close();
最终会调用
HAL
层的
data_close()
函数。至此,一个传感器从初始到结束的流程就分析完了。
所以在
java
使用一个传感器在
HAL
层具体调用的函数流程为:
首先,
sensors_control_open()
,只在系统初始化时调用一次。用来初始化
control_device
结构体。
以下的是每次使用传感器一般经过的流程,注意,是一般而已,有些并不执行
(
1
)
sensors_data_open
(
2
)
get_sensors_list
(
3
)
activate
(
4
)
set_delay
(
5
)
open_data_source
(
6
)
data_open
(
7
)
poll
一直读数据。。。。。。。。。。。
退出时
(
8
)
activate
(
9
)
sensors_control_close
(
10
)
data_close
当然其它的细节你们可以继续去研究。也可以在我博客里提出来大家交流和讨论一下!