一. android传感器有哪些?
在frameworks/base/core/java/android/hardware/Sensor.java中定义了android系统所能支持的传感器,例如
public static final int TYPE_ACCELEROMETER = 1;
public static final String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
public static final int TYPE_MAGNETIC_FIELD = 2;
public static final String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
public static final int TYPE_ORIENTATION = 3;
public static final String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
public static final int TYPE_GYROSCOPE = 4;
public static final String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
public static final int TYPE_LIGHT = 5;
public static final String STRING_TYPE_LIGHT = "android.sensor.light";
public static final int TYPE_PRESSURE = 6;
public static final String STRING_TYPE_PRESSURE = "android.sensor.pressure";
public static final int TYPE_TEMPERATURE = 7;
public static final String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
public static final int TYPE_PROXIMITY = 8;
public static final String STRING_TYPE_PROXIMITY = "android.sensor.proximity";
public static final int TYPE_GRAVITY = 9;
public static final String STRING_TYPE_GRAVITY = "android.sensor.gravity";
public static final int TYPE_LINEAR_ACCELERATION = 10;
public static final String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
public static final int TYPE_ROTATION_VECTOR = 11;
public static final String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
public static final int TYPE_RELATIVE_HUMIDITY = 12;
public static final String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
public static final int TYPE_AMBIENT_TEMPERATURE = 13;
public static final String STRING_TYPE_AMBIENT_TEMPERATURE ="android.sensor.ambient_temperature";
public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;
public static final String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
public static final int TYPE_GAME_ROTATION_VECTOR = 15;
public static final String STRING_TYPE_GAME_ROTATION_VECTOR ="android.sensor.game_rotation_vector";
public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16;
public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
public static final int TYPE_SIGNIFICANT_MOTION = 17;
public static final String STRING_TYPE_SIGNIFICANT_MOTION ="android.sensor.significant_motion";
public static final int TYPE_STEP_DETECTOR = 18;
public static final String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
public static final int TYPE_STEP_COUNTER = 19;
public static final String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
public static final String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR =
"android.sensor.geomagnetic_rotation_vector";
public static final int TYPE_HEART_RATE = 21;
public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
public static final int TYPE_TILT_DETECTOR = 22;
public static final String SENSOR_STRING_TYPE_TILT_DETECTOR =
"android.sensor.tilt_detector";
public static final int TYPE_WAKE_GESTURE = 23;
public static final String STRING_TYPE_WAKE_GESTURE = "android.sensor.wake_gesture";
public static final int TYPE_GLANCE_GESTURE = 24;
public static final String STRING_TYPE_GLANCE_GESTURE = "android.sensor.glance_gesture";
public static final int TYPE_PICK_UP_GESTURE = 25;
public static final String STRING_TYPE_PICK_UP_GESTURE = "android.sensor.pick_up_gesture";
public static final int TYPE_WRIST_TILT_GESTURE = 26;
public static final String STRING_TYPE_WRIST_TILT_GESTURE = "android.sensor.wrist_tilt_gesture";
public static final int TYPE_DEVICE_ORIENTATION = 27;
public static final String STRING_TYPE_DEVICE_ORIENTATION = "android.sensor.device_orientation";
public static final int TYPE_POSE_6DOF = 28;
public static final String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
public static final int TYPE_STATIONARY_DETECT = 29;
public static final String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
public static final int TYPE_MOTION_DETECT = 30;
public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
public static final int TYPE_HEART_BEAT = 31;
public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
public static final int TYPE_DYNAMIC_SENSOR_META = 32;
public static final String STRING_TYPE_DYNAMIC_SENSOR_META =
"android.sensor.dynamic_sensor_meta";
可以看出,android目前支持的传感器有32种,通常所说的加速器、重力感应器、磁场感应器、方向感应器(水平竖直)陀螺仪、距离感应、心率、心跳、光感、温度等传感器都包含在内。这里罗列出来的传感器包含一些虚拟传感器,虚拟传感器通常是一个或多个物理传感器在算法的基础上虚拟化出来的。随着传感器种类的丰富,以后估计会支持更多传感器。
二、android传感器的开发过程
android .java源码经过编译后生成.class文件,.class文件是字节码文件,字节码文件是平台虚拟机能够识别运行的文件,但android的基于linux内核实现,驱动也是运行在内核空间的,应用层通过系统调用来调用内核空间,但linux内核提供的系统调用入口,是java代码不能直接调用的,必须经过C库中的系统调用来实现,也就是说java需要调用C、C++的代码,jni层实现了java调用c c++代码。
基于android平台做传感器的应用程序开发,软件层次自顶向下可以分为四层,java层,jni层,HAL层,驱动层。
我们从最上层说起。创建一个active实例展示传感器的数据。
public class MainActivity extends Activity
implements SensorEventListener
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取水平仪的主组件
show = (MyView) findViewById(R.id.show);
// 获取传感器管理服务
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
}
@Override
public void onResume()
{
super.onResume();
// 为系统的方向传感器注册监听器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
}
.......
}
在onCreate函数中,通过getSystemService获取传感器管理器的实例。
那么getSystemService的执行过程是怎样的呢?
onCreate
–>(SensorManager)getSystemService(SENSOR_SERVICE);
–>frameworks\base\core\java\android\app\Activity.java中的getSystemService
—>android\content\ContextThemeWrapper.java中的getSystemService
在ContextThemeWrapper.java中getSystemService的实现如下:
@Override
public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
}
return mInflater;
}
return getBaseContext().getSystemService(name);
}
发现调用的是android\content\Context.java中的getSystemService。进入Context.java查看源码
//file android\content\Context.java
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) {
// Because subclasses may override getSystemService(String) we cannot
// perform a lookup by class alone. We must first map the class to its
// service name then invoke the string-based method.
String serviceName = getSystemServiceName(serviceClass);
return serviceName != null ? (T)getSystemService(serviceName) : null;
}
public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass);
先通过getSystemServiceName获取服务名字,然后调用了泛类参数serviceClass的getSystemService返回结果。
那么抽象函数getSystemServiceName和serviceClass分别在哪里实现的呢?
先列出相关类的关系:
public class MainActivity extends Activity
public class Activity extends ContextThemeWrapper
public class ContextThemeWrapper extends ContextWrapper
public class ContextWrapper extends Context
public abstract class Context
不妨先从这几个类当中找一下getSystemServiceName函数的实现。
在content\ContextWrapper.java中找到了getSystemServiceName实现。
//content\ContextWrapper.java
public class ContextWrapper extends Context{
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return mBase.getSystemServiceName(serviceClass);
}
@Override
public Object getSystemService(String name) {
return mBase.getSystemService(name);
}
}
可以看出在onCreate函数中调用的getSystemService最终其实还是context中的getSystemService,依然没有找到getSystemService的具体实现。
在网上查了资料说是android/app/ContextImpl.java中实现Context.java中的所有方法,那么刚才的getSystemService就在ContextImpl.java中实现了。但看了代码没有找到import ContextImpl.java的地方,这说明有可能是在跟ContextImpl同包的文件中引用了。
这可以从安卓应用程序的入口说起(参考
)
在ActivityThread中,通过传入主线程对象创建了一个系统的ContextImpl,刚才的getSystemService正是在ContextImpl.java中的getSystemService。
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
// frameworks\base\core\java\android\app\SystemServiceRegistry.java
// This information is never changed once static initialization has completed.
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
static{
.......
registerService(Context.SENSOR_SERVICE, SensorManager.class,
new CachedServiceFetcher<SensorManager>() {
@Override
public SensorManager createService(ContextImpl ctx) {
return new SystemSensorManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler().getLooper());
}});
}
static abstract class StaticServiceFetcher<T> implements ServiceFetcher<T> {
private T mCachedInstance;
@Override
public final T getService(ContextImpl unused) {
synchronized (StaticServiceFetcher.this) {
if (mCachedInstance == null) {// 如果service不存在,
//则调用createService就是我们上面在registerservice时重载的createService方法,里面就是new 了一个
SystemSensorManager mCachedInstance = createService();
}
return mCachedInstance;
}
}
public abstract T createService();
}
在SystemServiceRegistry.java的内部类StaticServiceFetcher中实现了getService方法,并且声明了一个createService抽象函数,所以继承SystemServiceRegistry的子类需要实现createService的方法。
而在registerService SENSOR_SERVICE的时候,实现了一个createService,其实就是调用了new SystemSensorManager,而SystemSensorManager的构造函数里面就调用了JNI的函数。
从网上找到一张调用关系图,如下
那么问题来了,SystemSensorManager是怎样直接就能调用frameworks\base\core\jni\android_hardware_SensorManager.cpp里面的nativeClassInit呢?
这跟vm映射原理、jni环境的导入有关系。
//frameworks\base\core\jni\android_hardware_SensorManager.cpp
static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit",
"()V",
(void*)nativeClassInit },
{"nativeCreate",
"(Ljava/lang/String;)J",
(void*)nativeCreate },
{"nativeGetSensorAtIndex",
"(JLandroid/hardware/Sensor;I)Z",
(void*)nativeGetSensorAtIndex },
{"nativeGetDynamicSensors",
"(JLjava/util/List;)V",
(void*)nativeGetDynamicSensors },
{"nativeIsDataInjectionEnabled",
"(J)Z",
(void*)nativeIsDataInjectionEnabled},
};
int register_android_hardware_SensorManager(JNIEnv *env)
{
RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
"android/hardware/SystemSensorManager$BaseEventQueue");
gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
return 0;
}
//register_android_hardware_SensorManager在什么时候执行呢?
//core/jni/AndroidRuntime.cpp
core/jni/AndroidRuntime.cpp:91:extern int register_android_hardware_SensorManager(JNIEnv *env);
core/jni/AndroidRuntime.cpp:1373: REG_JNI(register_android_hardware_SensorManager),
1265 static const RegJNIRec gRegJNI[] = {
1266 REG_JNI(register_android_util_SeempLog),
1267 REG_JNI(register_com_android_internal_os_RuntimeInit),
1268 REG_JNI(register_android_os_SystemClock),
1269 REG_JNI(register_android_util_EventLog),
1270 REG_JNI(register_android_util_Log),
1271 REG_JNI(register_android_util_MemoryIntArray),
1272 REG_JNI(register_android_util_PathParser),
1273 REG_JNI(register_android_app_admin_SecurityLog),
1274 REG_JNI(register_android_content_AssetManager),
1275 REG_JNI(register_android_content_StringBlock),
1276 REG_JNI(register_android_content_XmlBlock),
1277 REG_JNI(register_android_text_AndroidCharacter),
1278 REG_JNI(register_android_text_StaticLayout),
1279 REG_JNI(register_android_text_AndroidBidi),
1280 REG_JNI(register_android_view_InputDevice),
1281 REG_JNI(register_android_view_KeyCharacterMap),
1282 REG_JNI(register_android_os_Process),
1283 REG_JNI(register_android_os_SystemProperties),
1284 REG_JNI(register_android_os_Binder),
.......
1372 REG_JNI(register_android_hardware_Radio),
1373 REG_JNI(register_android_hardware_SensorManager),
1374 REG_JNI(register_android_hardware_SerialPort),
1375 REG_JNI(register_android_hardware_SoundTrigger),
1376 REG_JNI(register_android_hardware_UsbDevice),
1377 REG_JNI(register_android_hardware_UsbDeviceConnection),
1378 REG_JNI(register_android_hardware_UsbRequest),
}
1420 * Register android native functions with the VM.
1421 */
1422 /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
1423 {
1424 ATRACE_NAME("RegisterAndroidNatives");
1425 /*
1426 * This hook causes all future threads created in this process to be
1427 * attached to the JavaVM. (This needs to go away in favor of JNI
1428 * Attach calls.)
1429 */
1430 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
1431
1432 ALOGV("--- registering native functions ---\n");
1433
1434 /*
1435 * Every "register" function calls one or more things that return
1436 * a local reference (e.g. FindClass). Because we haven't really
1437 * started the VM yet, they're all getting stored in the base frame
1438 * and never released. Use Push/Pop to manage the storage.
1439 */
1440 env->PushLocalFrame(200);
1441
1442 if (register_jni_procs(**gRegJNI**, NELEM(gRegJNI), env) < 0) {
1443 env->PopLocalFrame(NULL);
1444 return -1;
1445 }
1446 env->PopLocalFrame(NULL);
1447
1448 //createJavaThread("fubar", quickTest, (void*) "hello");
1449
1450 return 0;
1451 }
上面的starg函数,由app:main,
app_main.cpp的main()方法最终调用了AndroidRuntime的start()方法.start函数完成了下面的功能。
1. jni_invocation.Init()方法初始化jni接口
2. startVm()方法创建虚拟机
3. startReg()方法注册Android方法
4. CallStaticVoidMethod()方法打开ZygoteInit类的main方法。完成从c/c++到java代码。
// 在startReg中引入了native方法。
看了上面的分析后,SystemSensorManager调用了nativeCreate 和 nativeGetSensorAtIndex,为java层填充了各个sensor的实例。
现在捋一下getSystemService调用过程。
Oncreate
—>mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
—>Context.java getSystemService
—>COntextImpl.java getSystemService,这里得到的是在register SENSOR_SERVICE的时候已经SystemSensorManager
而register SENSOR_SERVICE的过程是:
SystemSensorManager.java—>android_hardware_SensorManager.cpp,填充了各个sensor的实例。
拿到了SystemSensorManager实例后,就可以使用mSensorManager.registerListener监听指定类型的sensor。
public boolean registerListener(SensorEventListener listener, Sensor sensor,
int samplingPeriodUs) {
return registerListener(listener, sensor, samplingPeriodUs, null);
}