android感測器資料流程
一. 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);
}