1. 程式人生 > >Android工程模式下讀取硬體資訊

Android工程模式下讀取硬體資訊



    Android工程模式下需要一個方便的途徑去訪問底層的硬體資訊,以方便軟體和測試同事更加簡單的知道硬體資訊;Android 從底層本質上說是 Linux,因此可以把 Android 當作 Linux 來訪問,從而達到訪問系統資訊的目的;

一:proc 檔案系統

proc 檔案系統是Linux核心開發人員為了減少系統呼叫的複雜性而引入的一種特殊檔案系統。

有了這種檔案系統,使用者只需要像檢視文字檔案一樣就能夠讀取核心中的各種資料,給開發人員和系統管理員帶來很大的便利。

很多Linux常用命令都是依靠分析/proc目錄下的檔案來執行的,比如 ls,ps 等。

 1、讀取CPU和記憶體等資訊。

分析 /proc/cpuinfo 這個檔案,就能獲得 CPU資訊。

adb shell

# cat /proc/cpuinfo

 分析 /proc/meminfo ,就能獲得記憶體資訊

adb shell

# cat /proc/meminfo

adb shell

#cat proc/kmsg 抓取kernel丟擲的除錯資訊 

注:用 Android SDK 的 ActivityManager.getMemoryInfo(ActivityManager.MemoryInfo) 也能獲得當前可用記憶體的大小

你如果使用Linux,可以看到 /proc目錄還有很多檔案,你可以用 man proc 命令來學習 proc 檔案系統。

二:sysfs檔案系統

 linux 2.6 核心中引入了 sysfs 檔案系統,是使用者空間與核心空間進行互動的一個媒介。
比起古老的 proc 檔案系統,它是基於核心的資料結構,因此組織結構上更加嚴密。
它的設計使核心的資訊更易獲取,而且更加清晰。核心空間與使用者空間的對映關係如下表所示:

核心空間(internel) ——->使用者空間(externel)
核心物件(kernel objects) ——->目錄(directories)
物件屬性(object attributes) ——->普通檔案(regular files)
物件關係(object relationshiops) ——->符號連結(symbolic links)

先使用kobject_create_and_add() 建立目錄
再透過sysfs_create_group(example_kobj, &attr_group) 建立目錄下的屬性檔案組, 其中 attr_group 是我們自己定義的屬性相關檔案,

static int __init example_init(void)
{
int retval;

/*
* Create a simple kobject with the name of “kobject_example",* located under /sys/kernel/
** As this is a simple directory, no uevent will be sent to userspace. That is why this function should not be used for any type of dynamic kobjects,

 where the name and number are* not known ahead of time.
*/
example_kobj = kobject_create_and_add(“kobject_example", kernel_kobj);
if (!example_kobj)
return -ENOMEM;

/* Create the files associated with this kobject */
retval = sysfs_create_group(example_kobj, &attr_group);
if (retval)
kobject_put(example_kobj);

return retval;
}

通過它,我們描述了目錄裡具有的屬性檔案,以及各檔案的 show 和 store 函式。
對於本例來說,可用一個屬性陣列 attrs 描述這一屬性組 attr_group。

下面就舉一個獲取Android攝像頭ic的例子來說明這種方法的實現,我們在Android平臺中攝像頭驅動載入的probe階段建立相關的裝置檔案節點;
#ifdef CONFIG_GET_HARDWARE_IC_TYPE_SUPPORT
struct kobject *hwinfo_kobj;
 
static char main_buf[10];
static char sub_buf[10];

static ssize_t main_camera_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
       return sprintf(buf, "%s\n", main_buf);
       //printk("@fantasy --camera-- set main camera id %s!\n",&main_buf);
}

static ssize_t sub_camera_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
       return sprintf(buf, "%s\n", sub_buf);
      //printk("@fantasy --camera-- set sub camera id %s!\n",&sub_buf);
}

static struct kobj_attribute main_attr = {
    .attr = {
        .name = "main_camera",
        .mode = S_IRUGO,
    },
    .show = &main_camera_show,
};

static struct kobj_attribute sub_attr = {
    .attr = {
        .name = "sub_camera",
        .mode = S_IRUGO,
    },
    .show = &sub_camera_show,
};

static struct attribute *camera_attrs[] = {
       &main_attr.attr,
       &sub_attr.attr,
       NULL
};

static struct attribute_group camera_attr_group = {
    .attrs = camera_attrs,
};

static void camera_get_ic_type_init(void)
{
    int ret;
    hwinfo_kobj = kobject_create_and_add("hw_info", NULL);   
    if (hwinfo_kobj)
        ret = sysfs_create_group(hwinfo_kobj,  &camera_attr_group);
    if (!hwinfo_kobj || ret)
        pr_err("failed to create hw info kobj\n");  
   
}

#endif //end of CONFIG_GET_HARDWARE_IC_TYPE_SUPPORT
  在攝像頭驅動identify的過程中給檔案節點賦值,
#ifdef CONFIG_GET_HARDWARE_IC_TYPE_SUPPORT

int Sensor_Set_MainID(SENSOR_INFO_T *sensor_info_p)
{
               int ret;
               //char main_buf[10] = {0};
               
               memcpy(main_buf, sensor_info_p->name, strlen(sensor_info_p->name));
               
               //ret = xioctl(g_fd_sensor, SENSOR_IO_SET_MAIN_ID, main_buf);
               printk("@fantasy --camera-- set main camera id %s!\n",sensor_info_p->name);
               
               return ret;
}

int Sensor_Set_SubID(SENSOR_INFO_T *sensor_info_p)
{
               int ret;
               //char sub_buf[10] = {0};
               
               memcpy(sub_buf, sensor_info_p->name, strlen(sensor_info_p->name));

               //ret = xioctl(g_fd_sensor, SENSOR_IO_SET_SUB_ID, sub_buf);
             printk("@fantasy --camera-- set  camera id %s!\n",sensor_info_p->name);

               return ret;
}
#endif


 然後在應用層讀取硬體引數的檔案節點:
        //Main Camera
    File MCamera_TYPE_FILE = new File("/sys/hw_info/main_camera");
    String MCamera_type_string = null;
              if (MCamera_TYPE_FILE.exists()) {
                            try {
                      FileReader command = new FileReader(MCamera_TYPE_FILE);
                      BufferedReader reader = new BufferedReader(command);
                                                       
                      MCamera_type_string = reader.readLine();
                      if(null ==  MCamera_type_string){
                                                       MCamera_type_string = "UNKNOWN";
                                               }
                                               
                                    command.close();
                      } catch (FileNotFoundException e1) {
                      // TODO Auto-generated catch block
                       e1.printStackTrace();
                      } catch (IOException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
                       }
                       }
                       else{
                               MCamera_type_string = "UNKNOWN";
                       }
               //Sub Camera    
               File SCamera_TYPE_FILE = new File("/sys/hw_info/sub_camera");
               String SCamera_type_string = null;
                       if (SCamera_TYPE_FILE.exists()) {
                               try {
                FileReader command = new FileReader(SCamera_TYPE_FILE);
                BufferedReader reader = new BufferedReader(command);
                                                       
                SCamera_type_string = reader.readLine();
                                               if(null ==  SCamera_type_string){
                                                       SCamera_type_string = "UNKNOWN";
                                               }
                                               
                command.close();
                   } catch (FileNotFoundException e1) {
                   // TODO Auto-generated catch block
                  e1.printStackTrace();
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                   e.printStackTrace();
                  }
                       }
                       else{
                               SCamera_type_string = "UNKNOWN";
                     }       
                       

  就可以正常的顯示硬體資訊了!

三 在HAL層讀取硬體資訊,通過JNI介面實現讀取

   當然我們還可以通過HAL層的程式碼來實現對底層硬體資訊的讀取,應用層通過JNI介面來訪問這些資料,同樣也可以實現對底層硬體資訊的讀取!具體的操作程式碼,各位網友可以自己參考Android的開發框架,嘗試寫出來看看!