1. 程式人生 > >android感測器資料流程

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