Sensor輸入子系統
採用了通用的Linux輸入框架,它通過/sys/class/input節點和用戶空間進行交互。
Evdev提供了一種訪問/dev/input/eventX輸入設備事件的通用方法。
系統開機啓動
init 是 zygote的父進程, 而system_server和其他所有的com.xxx結尾的應用程序都是從zygote fork 而來
#init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
SystemServer 啓動
系統啓動時SystemServer main() 調用android_server_systemserver_nativeInit()
public static void main(String[] args) {
/*
* In case the runtime switched since last boot (such as when
* the old runtime was removed in an OTA), set the system
* property so that it is in sync. We can't do this in
* libnativehelper's JniInvocation::Init code where we already
* had to fallback to a different runtime because it is
* running as root and we need to be the system user to set
* the property. http://b/11463182
*/
SystemProperties.set("persist.sys.dalvik.vm.lib",
VMRuntime.getRuntime().vmLibrary());
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it
// shortly.
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
nativeInit();
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
}
static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
}
systemReady
客戶端實例化PowerManagerService.java中systemReady,初始化SystemSensorManager
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
系統開機啓動的時候,會創建SystemSensorManager的實例,在其構造函數中,主要做:
初始化JNI:調用JNI函數nativeClassInit()進行初始化 (android_hardware_SensorManager.cpp)
獲取Sensor列表:調用JNI函數nativeGetNextSensor,對Sensor模塊進行初始化。
創建了native層SensorManager的實例。
public SystemSensorManager(Context context, Looper mainLooper) {
mMainLooper = mainLooper;
mContext = context;
mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
mGsensorDiscard = 0;
synchronized(sSensorModuleLock) {
if (!sSensorModuleInitialized) {
sSensorModuleInitialized = true;
nativeClassInit();
// initialize the sensor list
final ArrayList<Sensor> fullList = sFullSensorsList;
int i = 0;
do {
Sensor sensor = new Sensor();
i = nativeGetNextSensor(sensor, i);
if (i>=0) {
//Log.d(TAG, "found sensor: " + sensor.getName() +
// ", handle=" + sensor.getHandle());
fullList.add(sensor);
sHandleToSensor.append(sensor.getHandle(), sensor);
}
} while (i>0);
}
}
}
服務端實現
SensorService初始化
SensorService::onFirstRef()方法,在該方法中完成初始化工作。
1.創建SensorDevice實例
2.獲取Sensor列表
3.調用SensorDevice.getSensorList(),獲取Sensor模塊所有傳感器列表
4.爲每個傳感器註冊監聽器
SensorDevice是單例singleton
構造函數 SensorDevice::SensorDevice()
調用HAL層的hw_get_module()方法,加載Sensor模塊so文件
調用sensor.h的sensors_open方法打開設備
調用sensors_poll_device_t->activate()對Sensor模塊使能
在新的線程中讀取HAL層數據
SensorService實現了Thread類,當在onFirstRef中調用run方法後,將在新的線程中調用SensorService::threadLoop()方法
bool SensorService::threadLoop()
{
ALOGD("nuSensorService thread starting...");
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);//輪詢
APP客戶端 使用方法
SensorManager.java 從android4.1開始,把SensorManager定義爲一個抽象類,定義了一些主要的方法,該類主要是應用層直接使用的類,提供給應用層的接口)
SystemSensorManager.java (這是implement) 應用程序通過獲取其實例,並註冊監聽接 口,獲取sensor數據。
Activity實現了SensorEventListener接口。
在onCreate方法中,獲取SystemSensorManager,並獲取到加速傳感器的Sensor;
在onResume方法中調用SystemSensorManager,registerListenerImp
Sensor accSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.unregisterListener(this, accSensor);
//然後在當前Activity中實現以下的兩個函數
public void onSensorChanged(SensorEvent event)
public void onAccuracyChanged(Sensor sensor, int accuracy)
代碼和動態庫so
Framework部分:
frameworks/base/core/Java/Android/hardware/SensorManager.java
frameworks/base/core/jni/android_hardware_sensorManager.cpp
下面的代碼會生成到:libgui.so
frameworks/base/libs/gui/SensorManager.cpp
frameworks/base/libs/gui/SensorEventQueue.cpp
frameworks/base/libs/gui/SensorChannel.cpp
frameworks/base/libs/gui/Sensor.cpp
下面的代碼會生成:libsensorservice.so
frameworks/base/services/sensorservice/SensorService.cpp
frameworks/base/services/sensorservice/SensorDevice.cpp
HAL部分:這部分代碼最終會生成 sensor.default.so 到/system/lib/hw/
hardware/libhardware/include/hardware/Sensors.h
device/qcom/msm7627a/libsensors/Sensors.cpp
device/qcom/msm7627a/libsensors/SensorBase.h
device/qcom/msm7627a/libsensors/AccSensor.cpp
device/qcom/msm7627a/libsensors/ProximitySensor.cpp
device/qcom/msm7627a/libsensors/LightSensor.cpp
安卓的傳感器
安卓的傳感器又可以分爲基於硬件的和基於軟件的。基於硬件的傳感器往往是通過物理組件去實現的,他們通常是通過去測量特殊環境的屬性獲取數據,比如:重力加速度、地磁場強度或方位角度的變化。而基於軟件的傳感器並不依賴物理設備,儘管它們是模仿基於硬件的傳感器的。基於軟件的傳感器通常是通過一個或更多的硬件傳感器獲取數據,並且有時會調用虛擬傳感器或人工傳感器等等,線性加速度傳感器和重力傳感器就是基於軟件傳感器的例子。下面通過官方的一張圖看看安卓平臺支持的所有傳感器類型:
“`
TYPE_ACCELEROMETER
加速度傳感器,單位是m/s2,測量應用於設備X、Y、Z軸上的加速度
傳感器類型值(Sensor Type):1 (0x00000001)
TYPE_AMBIENT_TEMPERATURE
溫度傳感器,單位是℃
傳感器類型值(Sensor Type): 13 (0x0000000d)
TYPE_GAME_ROTATION_VECTOR
遊戲動作傳感器,不收電磁干擾影響
傳感器類型值(Sensor Type):15 (0x0000000f)
TYPE_GEOMAGNETIC_ROTATION_VECTOR
地磁旋轉矢量傳感器,提供手機的旋轉矢量,當手機處於休眠狀態時,仍可以記錄設備的方位
傳感器類型值(Sensor Type):20 (0x00000014)
TYPE_GRAVITY
重力傳感器,單位是m/s2,測量應用於設備X、Y、Z軸上的重力
傳感器類型值(Sensor Type):9 (0x00000009)
TYPE_GYROSCOPE
陀螺儀傳感器,單位是rad/s,測量設備x、y、z三軸的角加速度
傳感器類型值(Sensor Type):4 (0x00000004)
TYPE_GYROSCOPE_UNCALIBRATED
未校準陀螺儀傳感器,提供原始的,未校準、補償的陀螺儀數據,用於後期處理和融合定位數據
傳感器類型值(Sensor Type):16 (0x00000010)
TYPE_LIGHT
光線感應傳感器,單位lx,檢測周圍的光線強度
傳感器類型值(Sensor Type):5 (0x00000005)
TYPE_LINEAR_ACCELERATION
線性加速度傳感器,單位是m/s2,該傳感器是獲取加速度傳感器去除重力的影響得到的數據
傳感器類型值(Sensor Type):10 (0x0000000a)
TYPE_MAGNETIC_FIELD
磁力傳感器,單位是uT(微特斯拉),測量設備周圍三個物理軸(x,y,z)的磁場
傳感器類型值(Sensor Type):2 (0x00000002)
TYPE_MAGNETIC_FIELD_UNCALIBRATED
未校準磁力傳感器,提供原始的,未校準的磁場數據
傳感器類型值(Sensor Type):14 (0x0000000e)
TYPE_ORIENTATION
方向傳感器,測量設備圍繞三個物理軸(x,y,z)的旋轉角度
傳感器類型值(Sensor Type):3 (0x00000003)
TYPE_PRESSURE
壓力傳感器,單位是hPa(百帕斯卡),返回當前環境下的壓強
傳感器類型值(Sensor Type):6 (0x00000006)
TYPE_PROXIMITY
距離傳感器,單位是cm,用來測量某個對象到屏幕的距離
傳感器類型值(Sensor Type):8 (0x00000008)
TYPE_RELATIVE_HUMIDITY
溼度傳感器,單位是%,來測量周圍環境的相對溼度
傳感器類型值(Sensor Type):12 (0x0000000c)
TYPE_ROTATION_VECTOR
旋轉矢量傳感器,旋轉矢量代表設備的方向
傳感器類型值(Sensor Type):11 (0x0000000b)
TYPE_SIGNIFICANT_MOTION
特殊動作觸發傳感器
傳感器類型值(Sensor Type):17 (0x00000011)
TYPE_STEP_COUNTER
計步傳感器
傳感器類型值(Sensor Type):19 (0x00000013)
TYPE_STEP_DETECTOR
步行檢測傳感器,用戶每走一步就觸發一次事件
傳感器類型值(Sensor Type):18 (0x00000012)
TYPE_TEMPERATURE
溫度傳感器,目前已被TYPE_AMBIENT_TEMPERATURE替代
傳感器類型值(Sensor Type):7 (0x00000007)
“`