1. 程式人生 > >Android從Hal到framework層新增自定義Sensor

Android從Hal到framework層新增自定義Sensor

近來在android原始碼中添加了一套sensor,做如下分享:

軟體版本:Android4.4

硬體平臺:MTK

之前寫過有關Sensor的博文,大家有興趣可以看一下,在此不在講具體sensor的工作機制,只分享從hardware到framework如何新增一款系統原本不支援的sensor type。

驅動層面不再贅述,本文大體分為三個大部分,第一部分為Hal層改動;第二部分為framework層修改;第三部分為簡單的app獲取該sensor的資料。

第一部分:Hal層。

MTK平臺hardware層程式碼在mediatek/hardware/sensor/目錄,

首先是將第三方的sensor hal層cpp和標頭檔案等放置該目錄,並修改Android.mk,新增相關的cpp,如果有相關的.a庫的依賴關係,則需要LOCAL_WHOLE_STATIC_LIBRARIES := libpah8002motion_s這樣去指定依賴關係,後邊的檔案就是.a檔案的名稱。

其次,修改nusensors.cpp檔案

diff --git a/mediatek/hardware/sensor/nusensors.cpp b/mediatek/hardware/sensor/nusensors.cpp
index c894616..ba2dd03 100644
--- a/mediatek/hardware/sensor/nusensors.cpp
+++ b/mediatek/hardware/sensor/nusensors.cpp
@@ -33,6 +33,7 @@
#include "Hwmsen.h"
#include "Acceleration.h"
#include "Magnetic.h"
+#include "PPGSensor.h"




/*****************************************************************************/
@@ -55,6 +56,7 @@ private:
//light,
//proximity,
//pressure,
+ heartrate,
numSensorDrivers,
numFds,
};
@@ -72,6 +74,8 @@ private:
//return light;
case ID_GYROSCOPE:
//return gyro;
+ case ID_HEART_RATE:
+ return heartrate;

case ID_PRESSURE:
break;
//return pressure;
@@ -95,6 +99,11 @@ sensors_poll_context_t::sensors_poll_context_t()
mPollFds[hwmsen].events = POLLIN;
mPollFds[hwmsen].revents = 0;

+ mSensors[heartrate] = new PPGSensor();
+ mPollFds[heartrate].fd = ((PPGSensor *)mSensors[heartrate])->mdata_fd;
+ mPollFds[heartrate].events = POLLIN;
+ mPollFds[heartrate].revents = 0;
+

開始新增heartrate型別sensor。

然後修改sensorList,

diff --git a/mediatek/hardware/sensor/hwmsen_chip_info.c b/mediatek/hardware/sensor/hwmsen_chip_info.c
index f997c76..1a25610 100644
--- a/mediatek/hardware/sensor/hwmsen_chip_info.c
+++ b/mediatek/hardware/sensor/hwmsen_chip_info.c
@@ -144,6 +144,23 @@
#endif
#endif

+#ifdef CUSTOM_KERNEL_HEART
+ #ifndef HEART_RATE
+ #define HEART_RATE "HEART_RATE"
+ #define HEART_RATE_VENDER "MTK"
+ #endif
+ #ifndef HEART_RATE_RANGE
+ #define HEART_RATE_RANGE 500.0f
+ #endif
+ #ifndef HEART_RATE_RESOLUTION
+ #define HEART_RATE_RESOLUTION 0.1f
+ #endif
+ #ifndef HEART_RATE_POWER
+ #define HEART_RATE_POWER 0.5f
+ #endif
+#endif
+
+

struct sensor_t sSensorList[MAX_NUM_SENSOR] =
@@ -256,5 +273,24 @@ struct sensor_t sSensorList[MAX_NUM_SENSOR] =
},
#endif

+#ifdef CUSTOM_KERNEL_HEART
+ {
+ .name = HEART_RATE,
+ .vendor = HEART_RATE_VENDER,
+ .version = 1,
+ .handle = ID_HEART_RATE,
+ .type = SENSOR_TYPE_HEART_RATE,
+ .maxRange = HEART_RATE_RANGE,//600.0f,
+ .resolution = HEART_RATE_RESOLUTION,//0.0016667f,
+ .power = HEART_RATE_POWER,//0.25f,
+ .minDelay = 0,
+ .fifoReservedEventCount = 0,
+ .fifoMaxEventCount = 0,
+ .reserved = {}
+ },
+#endif
+

};

修改sensor數目聯合體,

diff --git a/mediatek/hardware/sensor/hwmsen_chip_info.h b/mediatek/hardware/sensor/hwmsen_chip_info.h
index e566955..5408969 100644
--- a/mediatek/hardware/sensor/hwmsen_chip_info.h
+++ b/mediatek/hardware/sensor/hwmsen_chip_info.h
@@ -46,7 +46,11 @@ typedef enum SENSOR_NUM_DEF
#ifdef CUSTOM_KERNEL_TEMPURATURE
TEMPURATURE_NUM,
#endif
-
+
+ #ifdef CUSTOM_KERNEL_HEARTRATE
+ HEARTRATE_NUM,
+ #endif
+

SENSORS_NUM

}SENSOR_NUM_DEF;

修改hardware/libhardware/include/hardware/sensors.h

新增型別巨集值:

#define SENSOR_TYPE_HEART_RATE (21)

sensors_event_t新增float heartrate資料。

注意此型別巨集值和framework層相關型別的移位數一致,即framework的該型別sensor移位

diff --git a/mediatek/kernel/include/linux/hwmsensor.h b/mediatek/kernel/include/linux/hwmsenso
r.h
index 55ae7d0..264218e 100755
--- a/mediatek/kernel/include/linux/hwmsensor.h
+++ b/mediatek/kernel/include/linux/hwmsensor.h
@@ -36,6 +36,7 @@
#define SENSOR_TYPE_GRAVITY 9
#define SENSOR_TYPE_LINEAR_ACCELERATION 10
#define SENSOR_TYPE_ROTATION_VECTOR 11
+#define SENSOR_TYPE_HEART_RATE 21


/*---------------------------------------------------------------------------*/
@@ -51,6 +52,8 @@
#define ID_LIGHT (ID_BASE+SENSOR_TYPE_LIGHT-1)
#define ID_PRESSURE (ID_BASE+SENSOR_TYPE_PRESSURE-1)
#define ID_TEMPRERATURE (ID_BASE+SENSOR_TYPE_TEMPERATURE-1)
+/* kongbo add */
+#define ID_HEART_RATE (ID_BASE+SENSOR_TYPE_HEART_RATE-1)

#define ID_SENSOR_MAX_HANDLE (ID_BASE+10)
#define ID_NONE (ID_BASE+16)

@@ -68,6 +71,8 @@
#define SENSOR_GRAVITY (1 << ID_GRAVITY)
#define SENSOR_LINEAR_ACCELERATION (1 << ID_LINEAR_ACCELERATION)
#define SENSOR_ROTATION_VECTOR (1 << ID_ROTATION_VECTOR)
+/* kongbo add */
+#define SENSOR_HEARTRATE (1 << ID_HEART_RATE)

/*----------------------------------------------------------------------------*/
#define HWM_INPUTDEV_NAME "hwmdata"
此處注意,ID_HEART_RATE即為上層SensorManager相關型別的位移值。

第二部分,framework層sensor的相關改動。

diff --git a/frameworks/base/api/current.txt b/frameworks/base/api/current.txt
index c9c697e..bd9be4c 100644
--- a/frameworks/base/api/current.txt
+++ b/frameworks/base/api/current.txt
@@ -10723,6 +10723,7 @@ package android.hardware {
method public java.lang.String getVendor();
method public int getVersion();
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
+ field public static final int TYPE_HEARTRATE = 21;
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
@@ -10830,6 +10831,7 @@ package android.hardware {
field public static final deprecated int RAW_DATA_Z = 5; // 0x5
field public static final deprecated int SENSOR_ACCELEROMETER = 2; // 0x2
field public static final deprecated int SENSOR_ALL = 127; // 0x7f
+ field public static final deprecated int SENSOR_HEARTRATE =1048576;
field public static final int SENSOR_DELAY_FASTEST = 0; // 0x0
field public static final int SENSOR_DELAY_GAME = 1; // 0x1
field public static final int SENSOR_DELAY_NORMAL = 3; // 0x3
diff --git a/frameworks/base/core/java/android/hardware/LegacySensorManager.java b/frameworks/base/core/java/android/hardware/LegacySensorManager.java
index f959093..c55841c 100644
--- a/frameworks/base/core/java/android/hardware/LegacySensorManager.java
+++ b/frameworks/base/core/java/android/hardware/LegacySensorManager.java
@@ -74,6 +74,9 @@ final class LegacySensorManager {
case Sensor.TYPE_ACCELEROMETER:
result |= SensorManager.SENSOR_ACCELEROMETER;
break;
+ case Sensor.TYPE_HEARTRATE:
+ result |= SensorManager.SENSOR_HEARTRATE;
+ break;

case Sensor.TYPE_MAGNETIC_FIELD:
result |= SensorManager.SENSOR_MAGNETIC_FIELD;
break;
@@ -101,6 +104,8 @@ final class LegacySensorManager {
Sensor.TYPE_ORIENTATION, listener, sensors, rate) || result;
result = registerLegacyListener(SensorManager.SENSOR_TEMPERATURE,
Sensor.TYPE_TEMPERATURE, listener, sensors, rate) || result;
+ result = registerLegacyListener(SensorManager.SENSOR_HEARTRATE,
+ Sensor.TYPE_HEARTRATE, listener, sensors, rate) || result;
return result;
}

@@ -155,6 +160,8 @@ final class LegacySensorManager {
listener, sensors);
unregisterLegacyListener(SensorManager.SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
listener, sensors);
+ unregisterLegacyListener(SensorManager.SENSOR_HEARTRATE, Sensor.TYPE_HEARTRATE,
+ listener, sensors);

}

private void unregisterLegacyListener(int legacyType, int type,
diff --git a/frameworks/base/core/java/android/hardware/Sensor.java b/frameworks/base/core/java/android/hardware/Sensor.java
index 89a5819..931c1d6 100644
--- a/frameworks/base/core/java/android/hardware/Sensor.java
+++ b/frameworks/base/core/java/android/hardware/Sensor.java
@@ -222,6 +222,11 @@ public final class Sensor {
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;

/**
+ * kongbo add for heartrate sensor
+ */
+ public static final int TYPE_HEARTRATE = 21;
+
+ /**

* A constant describing all sensor types.
*/
public static final int TYPE_ALL = -1;
diff --git a/frameworks/base/core/java/android/hardware/SensorManager.java b/frameworks/base/core/java/android/hardware/SensorManager.java
index b931313..28c34a2 100644
--- a/frameworks/base/core/java/android/hardware/SensorManager.java
+++ b/frameworks/base/core/java/android/hardware/SensorManager.java
@@ -163,6 +163,9 @@ public abstract class SensorManager {
@Deprecated
public static final int SENSOR_ORIENTATION_RAW = 1 << 7;

+ @Deprecated
+ public static final int SENSOR_HEARTRATE = 1 << 20; //此處移位數要與前文ha層定義的保持一致
+

/**
* A constant that includes all sensors
*
diff --git a/frameworks/native/include/android/sensor.h b/frameworks/native/include/android/sensor.h
index 129ea3e..5146946 100644
--- a/frameworks/native/include/android/sensor.h
+++ b/frameworks/native/include/android/sensor.h
@@ -59,7 +59,8 @@ enum {
ASENSOR_TYPE_MAGNETIC_FIELD = 2,
ASENSOR_TYPE_GYROSCOPE = 4,
ASENSOR_TYPE_LIGHT = 5,
+ ASENSOR_TYPE_HEART_RATE = 21    //此處也要跟hal層定義的型別值一致
};

/*
@@ -147,6 +148,7 @@ typedef struct ASensorEvent {
float distance;
float light;
float pressure;
+ float heartrate;
float relative_humidity;
AUncalibratedEvent uncalibrated_gyro;
AUncalibratedEvent uncalibrated_magnetic;
diff --git a/frameworks/native/include/gui/Sensor.h b/frameworks/native/include/gui/Sensor.h
index 0c81426..a704093 100644
--- a/frameworks/native/include/gui/Sensor.h
+++ b/frameworks/native/include/gui/Sensor.h
@@ -49,7 +49,8 @@ public:
TYPE_MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD,
TYPE_GYROSCOPE = ASENSOR_TYPE_GYROSCOPE,
TYPE_LIGHT = ASENSOR_TYPE_LIGHT,
+ TYPE_HEARTRATE = ASENSOR_TYPE_HEART_RATE
};

第三部分,application獲取所新增型別sensor的資料。

package com.example.kaka.heartrate;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.TextView;
import android.widget.Button;
import android.view.View;

public class MainActivity extends Activity implements View.OnClickListener {
    private SensorManager sm;
    private Sensor heartSensor;
    private TextView heartRate;
  private Button back;
    private final String TAG = "XINGSHI";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        heartRate = (TextView)findViewById(R.id.heartrate);

    back = (Button)findViewById(R.id.back);
        back.setOnClickListener(this);

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);
        heartSensor = sm.getDefaultSensor(Sensor.TYPE_HEARTRATE);
        //heartSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        sm.registerListener(new MySensorListener(), heartSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.back:
       this.finish();
           break;  
        default:  
           break;  
        }  
    }

    public class MySensorListener implements SensorEventListener {

        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }

        public void onSensorChanged(SensorEvent event) {
            float heart = event.values[0];
            Log.e(TAG,"======= get heartrate data: " + String.valueOf(heart) + " =======");
            heartRate.setText(String.valueOf(heart));
        }
    }

}


大功告成!!!