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同包的文件中引用了。

這可以從安卓應用程序的入口說起(參考

https://blog.csdn.net/shifuhetudi/article/details/52089562

)
在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);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章