一. 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);
}