欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      Ubuntu 11.10編譯Android源碼錯(cuò)誤[范文大全]

      時(shí)間:2019-05-13 23:25:26下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫寫幫文庫(kù)小編為你整理了多篇相關(guān)的《Ubuntu 11.10編譯Android源碼錯(cuò)誤》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫(kù)還可以找到更多《Ubuntu 11.10編譯Android源碼錯(cuò)誤》。

      第一篇:Ubuntu 11.10編譯Android源碼錯(cuò)誤

      Ubuntu 11.10編譯Android源碼錯(cuò)誤

      問(wèn)題1:

      frameworks/base/libs/utils/RefBase.cpp: 在成員函數(shù)

      ‘void android::RefBase::weakref_type::trackMe(bool, bool)’中:

      frameworks/base/libs/utils/RefBase.cpp:483:67: 錯(cuò)誤: 將

      ‘constandroid::RefBase::weakref_impl’作為

      ‘voidandroid::RefBase::weakref_impl::trackMe(bool, bool)’的‘this’實(shí)參時(shí)丟棄了類型限定[-fpermissive]

      make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] 錯(cuò)誤 1 原因:Ubuntu 11.10的gcc 4.6版本太高了,android編譯需要gcc 4.4

      解決辦法:更換gcc、g++版本4.6為4.4

      sudo apt-get install gcc-4.4

      sudo apt-get install g++-4.4

      sudo rm-rf /usr/bin/gcc /usr/bin/g++

      sudo ln-s /usr/bin/gcc-4.4 /usr/bin/gcc

      sudo ln-s /usr/bin/g++-4.4 /usr/bin/g++

      問(wèn)題2:

      g++: 錯(cuò)誤: –fpermissive:沒(méi)有那個(gè)文件或目錄

      make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] 錯(cuò)誤 1 解決辦法:sudoapt-get install g++-4.4-multilib

      經(jīng)過(guò)此操作編譯可順利進(jìn)行。

      第二篇:Android源碼編譯整理總結(jié)

      1.必要的軟件環(huán)境

      sudo apt-get install build-essential sudo apt-get install make sudo apt-get install gcc sudo apt-get install g++ sudo apt-get install libc6-dev sudo apt-get install patch sudo apt-get install texinfo sudo apt-get install libncurses-dev sudo apt-get install git-core gnupg sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl sudo apt-get install ncurses-dev sudo apt-get install zlib1g-dev sudo apt-get install valgrind sudo apt-get install python2.5

      筆者發(fā)現(xiàn)這里已經(jīng)比較全來(lái),不過(guò)還有一些應(yīng)該是linux系統(tǒng)自帶的,如果缺少就按照提示install一下

      安裝java環(huán)境,這里有必要說(shuō)一下,大家裝環(huán)境的時(shí)候很多人會(huì)一起裝,不過(guò)筆者建議java和其他的分開,因?yàn)檠bjava很可能會(huì)失敗,從而導(dǎo)致其他的也fail sudo apt-get install sun-java6-jdk

      這里就說(shuō)到上面說(shuō)很多人會(huì)安裝java失敗的問(wèn)題,筆者也是從網(wǎng)上找的解決辦法現(xiàn)在一起整理出來(lái):

      ubuntu10.04 lucid 去掉了sun-java6-jre,sun-java6-jdk的源,所以如果是直接apt-get install 提示是

      現(xiàn)在沒(méi)有可用的軟件包 sun-java6-jdk,但是它被其它的軟件包引用了。

      這可能意味著這個(gè)缺失的軟件包可能已被廢棄,或者只能在其他發(fā)布源中找到

      E: 軟件包 sun-java6-jdk 還沒(méi)有可供安裝的候選者

      解決辦法(選擇一個(gè)即可):

      1、系統(tǒng)->系統(tǒng)管理->軟件源->“其它軟件”下添加一個(gè) deb http://archive.canonical.com/ lucid partner

      之后,再執(zhí)行apt-get install 如果是下載java5就添加deb http://us.archive.ubuntu.com/ubuntu/ jaunty multiverse”

      2、自己從sun網(wǎng)站下載相應(yīng)的Jre,JDK安裝即可

      3、從新立德軟件管理器中search openJDK,用openJDK代替

      注: 官方文檔說(shuō)如果用sun-java6-jdk可出問(wèn)題,得要用sun-java5-jdk。經(jīng)測(cè)試發(fā)現(xiàn),如果僅僅make(make不包括make sdk),用sun-java6-jdk是沒(méi)有問(wèn)題的。而make sdk,就會(huì)有問(wèn)題,嚴(yán)格來(lái)說(shuō)是在make doc出問(wèn)題,它需要的javadoc版本為1.5。

      因此,我們安裝完sun-java6-jdk后最好再安裝sun-java5-jdk,或者 只安裝sun-java5-jdk。這里sun-java6-jdk和sun-java5-jdk都安裝,并只修改javadoc.1.gz和 javadoc。因?yàn)橹挥羞@兩個(gè)是make sdk用到的。這樣的話,除了javadoc工具是用1.5版本,其它均用1.6版本: sudo apt-get install sun-java5-jdk 修改javadoc的link cd /etc/alternatives sudo rm javadoc.1.gz

      sudo ln-s /usr/lib/jvm/java-1.5.0-sun/man/man1/javadoc.1.gz javadoc.1.gz sudo rm javadoc sudo ln-s /usr/lib/jvm/java-1.5.0-sun/bin/javadoc javadoc

      2、設(shè)置環(huán)境變量 vim ~/.bashrc 在.bashrc中新增或整合PATH變量,如下 #java 程序開發(fā)/運(yùn)行的一些環(huán)境變量 JAVA_HOME=/usr/lib/jvm/java-6-sun JRE_HOME=${JAVA_HOME}/jre export ANDROID_JAVA_HOME=$JAVA_HOME export CLASSPATH=.:${JAVA_HOME}/lib:$JRE_HOME/lib:$CLASSP ATH export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin export JAVA_HOME;export JRE_HOME;export CLASSPATH;HOME_BIN=~/bin/ export PATH=${PATH}:${JAVA_PATH}:${JRE_PATH}:${HOME_BIN};#echo $PATH;最后,同步這些變化: source ~/.bashr 3.安裝repo(用來(lái)更新android源碼)

      創(chuàng)建~/bin目錄,用來(lái)存放repo程序,如下: $ cd ~ $ mkdir bin 并加到環(huán)境變量PATH中,在第2步中已經(jīng)加入 下載repo腳本并使其可執(zhí)行:

      $ curl http://android.git.kernel.org/repo >~/bin/repo $ chmod a+x ~/bin/repo 4.初始化repo

      repo是android對(duì)git的一個(gè)封裝,簡(jiǎn)化了一些git的操作。創(chuàng)建工程目錄: $ mkdir android $ cd android repo初始化

      $ repo init-u git://android.git.kernel.org/platform/manifest.git 這里包含了android最新的源碼

      在此過(guò)程中需要輸入名字和email地址。初始化成功后,會(huì)顯示: repo initialized in /android 在~/android下會(huì)有一個(gè).repo的隱藏目錄。

      如果想拿某個(gè)branch而不是主線上的代碼,我們需要用-b參數(shù)制定branch名字,比如:

      repo init-u git://android.git.kernel.org/platform/manifest.git-b cupcake 這 里抓下來(lái)的分支是cupcake,網(wǎng)上關(guān)于編譯到文章大多是針對(duì)cupcake分支,是andoird 1.5版本,但是之前我沒(méi)有輸入后面的參數(shù),以致于下到的代碼是主線上的代碼,是android 2.1版本。兩者目錄結(jié)構(gòu)有一些差別,導(dǎo)致當(dāng)我按照網(wǎng)上的說(shuō)明步驟來(lái)執(zhí)行遇到錯(cuò)誤時(shí),不知道是版本不同的原因還是其他什么原因。因此很奇怪為什么網(wǎng)上的文 章都是說(shuō)cupcake的,而沒(méi)有怎么講主線的源代碼編譯。5.同步源代碼 $ repo sync 這一步要很久,要看個(gè)人的網(wǎng)絡(luò)速度

      6.編譯android源碼,并得到~/android/out目錄 $ cd ~/andoird

      $ make-j2 筆者的電腦是雙核所以是-j2,以此類推8核就可以-j8 這一過(guò)程很久,主要看機(jī)器的配置

      如果是cupcake,那么直接make的時(shí)候,會(huì)出現(xiàn)以下錯(cuò)誤:

      1.frameworks/policies/base/PolicyConfig.mk:22: *** No module defined for the given PRODUCT_POLICY(android.policy_phone).Stop.錯(cuò)誤。

      解決辦法:

      在build/tools/findleaves.sh中的第89行,這一句find “${@:0:$nargs}” $findargs-type f-name “$filename”-print |

      改為find “${@:1:$nargs-1}” $findargs-type f-name “$filename”-print |

      2.frameworks/base/tools/aidl/AST.cpp:10: error: 'fprintf' was not declared in this scope的錯(cuò)誤

      解決辦法:

      下載gcc-4.3和g++-4.3

      apt-get install gcc-4.3 g++-4.3

      因?yàn)閡buntu 9.10自帶到是gcc 4.4,因此需要重新下載gcc 4.3,最后設(shè)置gcc軟連接到gcc 4.3

      進(jìn)入/usr/bin cd /usr/bin

      建個(gè)軟連接

      ln-s gcc-4.3 gcc

      ln-s g++-4.3 g++

      然后進(jìn)入android目錄下,執(zhí)行make,就可以了。

      主線代碼則沒(méi)有此問(wèn)題 7.在模擬器上運(yùn)行編譯好的android

      編譯好android之后,emulator在~/android/out/host/linux-x86/bin 下,ramdisk.img,system.img和userdata.img則在~/android/out/target/product /generic下 $ cd ~/android/out/host/linux-x86/bin 增加環(huán)境變量 $ emacs ~/.bashrc 在.bashrc中新增環(huán)境變量,如下 #java 程序開發(fā)/運(yùn)行的一些環(huán)境變量

      export ANDROID_PRODUCT_OUT=~/android/out/target/product/g eneric ANDROID_PRODUCT_OUT_BIN=~/android/out/host/linux-x 86/bin export PATH=${PATH}:${ANDROID_PRODUCT_OUT_BIN}:${ANDROID_ PRODUCT_OUT};最后,同步這些變化: $ source ~/.bashrc $ cd ~/android/out/target/product/generic

      $ emulator-system system.img-data userdata.img-ramdisk ramdisk.img 最后進(jìn)入android桌面,就說(shuō)明成功了。8.編譯模塊

      android中的一個(gè)應(yīng)用程序可以單獨(dú)編譯,編譯后要重新生成system.img 在源碼目錄下執(zhí)行

      $.build/envsetup.sh(.后面有空格)就多出一些命令:

      -croot: Changes directory to the top of the tree.mm: Builds all of the modules in the current directory.cgrep: Greps on all local C/C++ files.resgrep: Greps on all local res/*.xml files.-godir: Go to the directory containing a file.可以加—help查看用法

      我們可以使用mmm來(lái)編譯指定目錄的模塊,如編譯聯(lián)系人: $ mmm packages/apps/Contacts/ 編完之后生成兩個(gè)文件: out/target/product/generic/data/app/ContactsTests.apk out/target/product/generic/system/app/Contacts.apk 可以使用 $ make snod 重新生成system.img,再運(yùn)行模擬器 9.編譯SDK

      直接執(zhí)行make是不包括make sdk的。make sdk用來(lái)生成SDK,這樣,我們就可以用與源碼同步的SDK來(lái)開發(fā)android了。

      a)修改/frameworks/base/include/utils/Asset.h ?UNCOMPRESS_DATA_MAX = 1 * 1024 * 1024? 改為 ?UNCOMPRESS_DATA_MAX = 2 * 1024 * 1024?

      原因是eclipse編譯工程需要大于1.3M的buffer;

      這一步,筆者編譯的是主線程的,在Asset.h文件里沒(méi)找到上面的常量,所以就沒(méi)做這一步,但是也成功了。b)編譯ADT。

      如果想用eclipse開發(fā)android應(yīng)用程序,最好是安裝ADT,這樣就可以在eclipse下創(chuàng)建android的工程。

      產(chǎn)生ADT eclipse plugins $ development/tools/eclipse/scripts/build_server.sh ~/adt/

      使用前建議設(shè)定一下ECLIPSE_HOME的環(huán)境變量,不然會(huì)以為沒(méi)有裝eclipse,然后幫你download下來(lái)。

      這里要非常注意,本人就曾經(jīng)卡在這里,始終編譯不過(guò)。一開始會(huì)提示eclipse的什么什么jar找不到,因此fail。這主要是因?yàn)槲业?ECLIPSE_HOME到環(huán)境變量設(shè)置錯(cuò)誤。我之前裝的eclipse只從新力得上面抓下來(lái)的,好像找不到eclipse所在到目錄是哪個(gè),結(jié)果就設(shè)置 了一個(gè)名為eclipse的文件夾作為環(huán)境變量。因此后來(lái)直接從eclipse的官網(wǎng)上下了一個(gè),以為這樣就可以。結(jié)果杯具的是下到是一個(gè)eclipse Galileo,到頭來(lái)還是提示eclipse什么什么文件找不到。最后實(shí)在沒(méi)法,索性把eclipse刪個(gè)干凈,讓程序自己去下eclipse,發(fā)現(xiàn)抓 的是eclipse ganymede。在此要鄭重說(shuō)明一下,自己去下的話應(yīng)該下載jee的ganymade,而不能是java 的ganymade,具體原因試試就知道了。

      主線代碼編譯ADT的時(shí)候方法相同,但是沒(méi)有development/tools/eclipse這個(gè)目錄,而是在/sdk/eclipse這個(gè)目錄 c)執(zhí)行make sdk。

      注意,這里需要的javadoc版本為1.5,所以你需要在步驟1中同時(shí)安裝sun-java5-jdk $ make sdk

      編譯很慢。編譯后生成的SDK存放在out/host/linux-x86/sdk/,此目錄下有android-sdk_eng.xxx_linux-x86.zip和android-sdk_eng.xxx_linux-x86目錄。android-sdk_eng.xxx_linux-x86就是 SDK目錄

      實(shí)際上,當(dāng)用mmm命令編譯模塊時(shí),一樣會(huì)把SDK的輸出文件清除,因此,最好把a(bǔ)ndroid-sdk_eng.xxx_linux-x86移出來(lái)

      此后的應(yīng)用開發(fā),就在該SDK上進(jìn)行,所以把7)對(duì)于~/.bashrc的修改注釋掉,增加如下一行:

      export PATH=${PATH}:~/android/out/host/linux-x86/sdk/andr oid-sdk_eng.xxx_linux-x86/tools 注意要把xxx換成真實(shí)的路徑;

      同樣筆者編譯的是主線程,所以編譯完之后,發(fā)現(xiàn)~/android/out/host/linux-x86/sdk/android-sdk_eng.x xx_linux-x86/目錄下有2個(gè)文件夾一個(gè)是tools一個(gè)是platform-tools,然后用eclipse指向這個(gè)目錄的時(shí)候會(huì)提示找不到ADB,這時(shí)候只要把platform-tools下的ADB拷貝到tools文件夾就OK了 d)關(guān)于環(huán)境變量、android工具的選擇 目前的android工具有:

      A、我們從網(wǎng)上下載的SDK,如果你下載過(guò)的話(tools下有許多android工具,lib/images下有img映像)

      B、我們用make sdk編譯出來(lái)的SDK(tools下也有許多android工具,lib/images下有img映像)

      C、我們用make編譯出來(lái)的out目錄(tools下也有許多android工具,lib/images下有img映像)

      那么我們應(yīng)該用那些工具和img呢?

      首先,我們一般不會(huì)用A選項(xiàng)的工具和img,因?yàn)橐话銇?lái)說(shuō)它比較舊,也源碼不同步。其次,也不會(huì)用C選項(xiàng)的工具和img,因?yàn)檫@些工具和img沒(méi)有經(jīng)過(guò) SDK的歸類處理,會(huì)有工具和配置找不到的情況;事實(shí)上,make sdk產(chǎn)生的很多工具和img,在make編譯出來(lái)out目錄的時(shí)候,已經(jīng)編譯產(chǎn)生了,make sdk只是做了copy而已。e)安裝、配置ADT

      ~/adt/android-eclipse/下的文件壓縮,然后從eclipse中install就行了,當(dāng)然還有其他方法 10.編譯linux內(nèi)核映像 a)準(zhǔn)備交叉編譯工具鏈

      android代碼樹中有一個(gè)prebuilt項(xiàng)目,包含了我們編譯內(nèi)核所需的交叉編譯工具。b)設(shè)定環(huán)境變量 $ emacs ~/.bashrc 增加如下兩行:

      export PATH=$PATH:~/android/prebuilt/linux-x86/toolchain/ arm-eabi-4.4.0/bin export ARCH=arm 保存后,同步變化: $ source ~/.bashrc c)獲得合適的內(nèi)核源代碼 $ cd ~/android 獲得內(nèi)核源代碼倉(cāng)庫(kù)

      $ git clone git://android.git.kernel.org/kernel/common.git kernel $ cd kernel $ git branch 顯示 * android-2.6.27

      說(shuō)明你現(xiàn)在在android-2.6.27這個(gè)分支上,也是kernel/common.git的默認(rèn)主分支。顯示所有head分支: $ git branch-a 顯示 * android-2.6.27 remotes/origin/HEAD-> origin/android-2.6.27 remotes/origin/android-2.6.25 remotes/origin/android-2.6.27 remotes/origin/android-2.6.29 remotes/origin/android-goldfish-2.6.27 remotes/origin/android-goldfish-2.6.29

      我們選取最新的android-goldfish-2.6.29,其中g(shù)oldfish是android的模擬器模擬的CPU。

      $ git checkout-b android-goldfish-2.6.29 origin/android-goldfish-2.6.29 $ git branch 顯示 android-2.6.27 * android-goldfish-2.6.29 我們已經(jīng)工作在android-goldfish-2.6.29分支上了。d)設(shè)定交叉編譯參數(shù)

      打開kernel目錄下的Makefile文件,把CROSS_COMPILE指向剛才下載的prebuilt中的arm-eabi編譯器

      CROSS_COMPILE ?= arm-eabi-把 LDFLAGS_BUILD_ID = $(patsubst-Wl$(comma)%,%, $(call ld-option,-Wl$(comma)build-id,))

      這一行注釋掉,并且添加一個(gè)空的LDFLAGS_BUILD_ID定義,如下: LDFLAGS_BUILD_ID = e)編譯內(nèi)核映像 $ cd ~/android/kernel $ make goldfish_defconfig $ make f)測(cè)試生成的內(nèi)核映像

      $ emulator-avd myavd-kernel ~/android/kernel/arch/arm/boot/zImage

      第三篇:android有關(guān)sensor的源碼總結(jié)

      android有關(guān)sensor的源碼總結(jié)

      雖然這篇文章寫得很差,因?yàn)橼s時(shí)間,所以就匆匆忙忙地寫出來(lái)自己作一個(gè)筆記。但是我想對(duì)大家應(yīng)該有一點(diǎn)幫助。

      1、有關(guān)sensor在Java應(yīng)用程序的編程(以注冊(cè)多個(gè)傳感器為例,這程序是我臨時(shí)弄出來(lái)的,可能有錯(cuò))

      package com.sensors.acc;

      import android.app.Activity;import android.os.Bundle;

      import android.util.Log;import android.widget.TextView;import android.hardware.SensorManager;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;

      public class acc extends Activity { float x, y, z;SensorManager sensormanager = null;Sensor accSensor = null;Sensor lightSensor = null;Sensor proximitySensor = null;TextView accTextView = null;/** Called when the activity is first created.*/ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.main);sensormanager =(SensorManager)getSystemService(SENSOR_SERVICE);accSensor = sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);lightSensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);proximitySensor = sensormanager.getDefaultSensor(Sensor.TYPE_PROXIMITY);accTextView =(TextView)findViewById(R.id.textview_name);}

      SensorEventListener lsn = new SensorEventListener(){ public void onSensorChanged(SensorEvent e){ if(e.sensor == accSensor){ Log.d(“sensor”, “found acc sensor”);x = e.values[SensorManager.DATA_X];y = e.values[SensorManager.DATA_Y];z = e.values[SensorManager.DATA_Z];accTextView.setText(“x = ” + x + “, ny = ” + y + “, nz = ” + z);} else if(e.sensor == lightSensor){ Log.d(“sensor”, “found light sensor”);accTextView.setText(“data is ” + e.values[0]);} else if(e.sensor == proximitySensor){ Log.d(“sensor”, “found proximity sensor”);accTextView.setText(“distance is ” + e.values[0]);} }

      public void onAccuracyChanged(Sensor s, int accuracy){ } };@Override protected void onResume(){ super.onResume();// register this class as a listener for the orientation and accelerometer sensors sensormanager.registerListener(lsn, accSensor, SensorManager.SENSOR_DELAY_NORMAL);sensormanager.registerListener(lsn, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);sensormanager.registerListener(lsn, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);// sensormanager.unregisterListener(lsn);} @Override protected void onStop(){ // unregister listener sensormanager.unregisterListener(lsn, accSensor);sensormanager.unregisterListener(lsn, lightSensor);sensormanager.unregisterListener(lsn, proximitySensor);super.onStop();} }

      在onCreate()函數(shù)中,調(diào)用getSystemService(SENSOR_SERVICE)初始化一個(gè)SensorManager實(shí)例,為什么要用getSystemService函數(shù),而不直接用new SensorManager呢?我們看此函數(shù)的實(shí)現(xiàn),在ApplicationContext.java中,if(SENSOR_SERVICE.equals(name)){ return getSensorManager();然后getSensorManager()的實(shí)現(xiàn)

      private SensorManager getSensorManager(){ synchronized(mSync){ if(mSensorManager == null){ mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());} } return mSensorManager;} 看到?jīng)]有?初始化SensorManager的時(shí)候需要mMainThread.getHandler().getLooper()這個(gè)參數(shù),之個(gè)應(yīng)該是用來(lái)傳遞消息用的,在SensorManager類的構(gòu)造函數(shù)中會(huì)把此參數(shù)傳給類成員mMainLooper。如果用new SensorManager()就需要另外獲取mainLooper參數(shù)傳遞進(jìn)去。

      2、在android中跟sensor有關(guān)的一些文件有SensorManager.java,位于frameworksbasecorejavaandroidhardware目錄下,SensorService.java,位于frameworksbaseservicesjavacomandroidserver目錄下,android_hardware_SensorManager.cpp,位于frameworksbasecorejni目錄下,與SensorManager.java相對(duì)應(yīng),com_android_server_SensorService.cpp,在frameworksbaseservicesjni目錄下,與SensorService.java相對(duì)應(yīng)。還有SystemServer.java文件,HardwareLibhardwareIncludeHardware目錄下的Sensor.h頭文件。另外我們需要根據(jù)Sensor.h實(shí)現(xiàn)自己的一個(gè)源文件,一般取名為sensors_xxx.c或者sensors_xxx.cpp。

      3、SensorManager類分析 有幾個(gè)函數(shù)比較重要,必須清晰理解它們的實(shí)現(xiàn),才能了解整個(gè)傳感器系統(tǒng)的實(shí)現(xiàn)。從而更好地去實(shí)現(xiàn)硬件抽象層的實(shí)現(xiàn)。幾個(gè)比較重要的函數(shù)有構(gòu)造函數(shù)SensorManager(), registerListener()和unregisterListener(),其中registerListener()和unregisterListener()有多個(gè),標(biāo)志為 @Deprecated的是過(guò)時(shí)的,就不要看了。(1)構(gòu)造函數(shù)SensorManager(Looper mainLooper)這個(gè)函數(shù)首先獲取得傳感器系統(tǒng)服務(wù),并賦給類成員mSensorService,mSensorService = ISensorService.Stub.asInterface(ServiceManager.getService(Context.SENSOR_SERVICE));這里我要說(shuō)一句,就是關(guān)于這個(gè)傳感器系統(tǒng)服務(wù),很多書上都說(shuō)用getSystemService()是獲得傳感器的系統(tǒng)服務(wù),而它返回的是SensorManager類型,所以以為整個(gè)系統(tǒng)都是使用同一個(gè)SensorManager類的實(shí)例,以為我們?cè)谌魏蔚胤绞褂玫腟ensorManager實(shí)例都是同一個(gè),它們的公共成員是共享的。但是經(jīng)過(guò)這兩天的分析,這種說(shuō)法是錯(cuò)誤的。其實(shí)每次調(diào)用getSystemService()函數(shù)時(shí)都初始化一個(gè)新的SensorManager實(shí)例,而這個(gè)SensorManager實(shí)例會(huì)在構(gòu)造函數(shù)里通過(guò)取得傳感器系統(tǒng)服務(wù)SensorService來(lái)實(shí)現(xiàn)對(duì)下層傳感器的一些控制。而這個(gè)SensorService才是系統(tǒng)的傳感器服務(wù),說(shuō)服務(wù),不如說(shuō)它只是SensorService類的一個(gè)實(shí)例罷了。它只在系統(tǒng)初始化時(shí)初始化一次。Android中的系統(tǒng)服務(wù)機(jī)制應(yīng)該跟傳感器的都差不多一個(gè)樣,都是由不同的Manager調(diào)用下層相同的Service。你可以列舉其它的Manager。那它是什么時(shí)候初始化呢?它是系統(tǒng)初始化在SystemServer進(jìn)程里創(chuàng)建的,SystemServer是一個(gè)管理很多系統(tǒng)服務(wù)的進(jìn)程,我們轉(zhuǎn)到SystemServer.的main函數(shù)里,可以看到一直到調(diào)用int2()函數(shù),它會(huì)創(chuàng)建一個(gè)ServerThread,最終調(diào)用AdbSettingsObserver類的run()函數(shù),在run()函數(shù)里有這么有一句

      // Sensor Service is needed by Window Manager, so this goes first Log.i(TAG, “Sensor Service”);ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));這里就創(chuàng)建SensorService實(shí)例了。在創(chuàng)建這個(gè)實(shí)例時(shí)會(huì)在SensorService構(gòu)造函數(shù)中調(diào)用jni函數(shù) public SensorService(Context context){ if(localLOGV)Log.d(TAG, “SensorService startup”);_sensors_control_init();} 我們看_sensors_control_init();對(duì)應(yīng)的為 static jint android_init(JNIEnv *env, jclass clazz){ sensors_module_t* module;if(hw_get_module(SENSORS_HARDWARE_MODULE_ID,(const hw_module_t**)&module)== 0){ if(sensors_control_open(&module->common, &sSensorDevice)== 0){ const struct sensor_t* list;int count = module->get_sensors_list(module, &list);return count;} } return 0;} 它主要調(diào)用了sensor.h中的sensors_control_open()static inline int sensors_control_open(const struct hw_module_t* module, struct sensors_control_device_t** device){ return module->methods->open(module, SENSORS_HARDWARE_CONTROL,(struct hw_device_t**)device);} 之后在系統(tǒng)任何地方使用的都是這個(gè)SensorService實(shí)例。最后run()函數(shù)調(diào)用Looper.loop();就進(jìn)行消息循環(huán)等待了,這就是SystemServer進(jìn)程的消息服務(wù)了。這才真正叫做系統(tǒng)服務(wù)嘛。

      我們繼續(xù)看SensorManager類的構(gòu)造函數(shù),取得SensorService后,nativeClassInit();這是一個(gè)jni函數(shù),SensorManager類調(diào)用的jni函數(shù)都在com_android_server_SensorService.cpp里,我們看這函數(shù) static void nativeClassInit(JNIEnv *_env, jclass _this){ jclass sensorClass = _env->FindClass(“android/hardware/Sensor”);SensorOffsets& sensorOffsets = gSensorOffsets;sensorOffsets.name = _env->GetFieldID(sensorClass, “mName”, “Ljava/lang/String;”);sensorOffsets.vendor = _env->GetFieldID(sensorClass, “mVendor”, “Ljava/lang/String;”);sensorOffsets.version = _env->GetFieldID(sensorClass, “mVersion”, “I”);sensorOffsets.handle = _env->GetFieldID(sensorClass, “mHandle”, “I”);sensorOffsets.type = _env->GetFieldID(sensorClass, “mType”, “I”);sensorOffsets.range = _env->GetFieldID(sensorClass, “mMaxRange”, “F”);sensorOffsets.resolution = _env->GetFieldID(sensorClass, “mResolution”,“F”);sensorOffsets.power = _env->GetFieldID(sensorClass, “mPower”, “F”);} 這個(gè)函數(shù)只是獲取和設(shè)置一些信息吧,我們不關(guān)心。接著 sensors_module_init();我們看這函數(shù) static jint sensors_module_init(JNIEnv *env, jclass clazz){ int err = 0;sensors_module_t const* module;err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,(const hw_module_t **)&module);if(err == 0)sSensorModule =(sensors_module_t*)module;return err;} 它獲取了sensor的模塊信息,并把它賦給sSensorModule全局變量,之后傳的modules參數(shù)都為這個(gè)。接著在構(gòu)造函數(shù)里

      final ArrayList fullList = sFullSensorsList;int i = 0;do { Sensor sensor = new Sensor();i = sensors_module_get_next_sensor(sensor, i);

      if(i>=0){ Log.d(TAG, “found sensor: ” + sensor.getName()+ “, handle=” + sensor.getHandle());sensor.setLegacyType(getLegacySensorType(sensor.getType()));fullList.add(sensor);sHandleToSensor.append(sensor.getHandle(), sensor);} } while(i>0);這里主要是通過(guò)jni函數(shù)sensors_module_get_next_sensor(sensor, i);獲取傳感器列表,并把它加入自己的fullList列表中。我們看sensors_module_get_next_sensor()函數(shù) static jint sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next){ if(sSensorModule == NULL)return 0;

      SensorOffsets& sensorOffsets = gSensorOffsets;const struct sensor_t* list;int count = sSensorModule->get_sensors_list(sSensorModule, &list);if(next >= count)return-1;

      list += next;

      jstring name = env->NewStringUTF(list->name);jstring vendor = env->NewStringUTF(list->vendor);env->SetObjectField(sensor, sensorOffsets.name, name);env->SetObjectField(sensor, sensorOffsets.vendor, vendor);env->SetIntField(sensor, sensorOffsets.version, list->version);env->SetIntField(sensor, sensorOffsets.handle, list->handle);env->SetIntField(sensor, sensorOffsets.type, list->type);env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);env->SetFloatField(sensor, sensorOffsets.power, list->power);next++;return next } 它主要是調(diào)用HAL層的get_sensors_list()函數(shù)取得傳感器列表信息。接著在sensorManger構(gòu)造函數(shù)最后

      sSensorThread = new SensorThread();創(chuàng)建一個(gè)SensorThread()線程。但并未運(yùn)行,但在SensorThread類的構(gòu)造函數(shù)里會(huì)執(zhí)行jni函數(shù) sensors_data_init();我們看此函數(shù)static jint sensors_data_init(JNIEnv *env, jclass clazz){ if(sSensorModule == NULL)return-1;int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);return err;} 它調(diào)用了HAL層的sensors_data_open函數(shù),而這個(gè)函數(shù)位于sensor.h中,它調(diào)用的是 static inline int sensors_data_open(const struct hw_module_t* module, struct sensors_data_device_t** device){ return module->methods->open(module, SENSORS_HARDWARE_DATA,(struct hw_device_t**)device);} Modules->methods->open函數(shù)。而在SensorThread類的析構(gòu)函數(shù)finalize()里會(huì)調(diào)用 sensors_data_uninit();static jint sensors_data_uninit(JNIEnv *env, jclass clazz){ int err = 0;if(sSensorDevice){ err = sensors_data_close(sSensorDevice);if(err == 0)sSensorDevice = 0;} return err;} 在sensor.h里

      static inline int sensors_data_close(struct sensors_data_device_t* device){ return device->common.close(&device->common);} 那什么時(shí)候sSensorThread線程會(huì)運(yùn)行呢?我們?cè)谙旅婵磖egisterListener()函數(shù)。

      (2)public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate){ return registerListener(listener, sensor, rate, null);} 它調(diào)用的是 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate, Handler handler)在這函數(shù)中,先驗(yàn)證rate,然后檢測(cè)注冊(cè)的listener在不在本類的sListeners列表中。for(ListenerDelegate i : sListeners){ if(i.getListener()== listener){ l = i;break;} } 如果不在就申請(qǐng)一個(gè)listener,并把它加入全局列表sListener中,并調(diào)用mSensorService的enableSensor()函數(shù)使能傳感器,這個(gè)enableSensor()函數(shù)最終會(huì)調(diào)用HAL層的active函數(shù)和set_delay()函數(shù),使用后然后判斷sListener列表是否為空,當(dāng)然,第一次為空時(shí)加入一個(gè)新的listener就不為空了,此時(shí)就執(zhí)行sSensorThread的startLocked運(yùn)行sSensorThread線程了

      l = new ListenerDelegate(listener, sensor, handler);result = mSensorService.enableSensor(l, name, handle, delay);if(result){ sListeners.add(l);sListeners.notify();} if(!sListeners.isEmpty()){ sSensorThread.startLocked(mSensorService);} 另一方面,如果注冊(cè)的listener在sListeners列表中,則先調(diào)用mSensorService的enableSensor()函數(shù)使能傳感器,然后把注冊(cè)的傳感器加入到已存在的listener中。result = mSensorService.enableSensor(l, name, handle, delay);if(result){ l.addSensor(sensor);} 接下來(lái)我們看看startLocked函數(shù),它在SensorThread中,void startLocked(ISensorService service){ try { if(mThread == null){ Bundle dataChannel = service.getDataChannel();mThread = new Thread(new SensorThreadRunnable(dataChannel), SensorThread.class.getName());mThread.start();} } catch(RemoteException e){ Log.e(TAG, “RemoteException in startLocked: ”, e);} } 第一次mThread為null,然后它調(diào)用了service.getDataChannel()函數(shù),此函數(shù)在SensorService類中,主要調(diào)用了jni函數(shù)_sensors_control_open(),public Bundle getDataChannel()throws RemoteException { // synchronize so we do not require sensor HAL to be thread-safe.synchronized(mListeners){ return _sensors_control_open();} } SensorService類中調(diào)用的jni函數(shù)主要都在com_android_server_SensorService.cpp文件 中,我們看一下這個(gè)函數(shù) static jobject android_open(JNIEnv *env, jclass clazz){ native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);if(!handle){ return NULL;}

      // new Bundle()jobject bundle = env->NewObject(gBundleOffsets.mClass, gBundleOffsets.mConstructor);

      if(handle->numFds > 0){ jobjectArray fdArray = env->NewObjectArray(handle->numFds, gParcelFileDescriptorOffsets.mClass, NULL);for(int i = 0;i < handle->numFds;i++){ // new FileDescriptor()jobject fd = env->NewObject(gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);// new ParcelFileDescriptor()jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fd);env->SetObjectArrayElement(fdArray, i, pfd);} // bundle.putParcelableArray(“fds”, fdArray);env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray, env->NewStringUTF(“fds”), fdArray);}

      if(handle->numInts > 0){ jintArray intArray = env->NewIntArray(handle->numInts);env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);// bundle.putIntArray(“ints”, intArray);env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray, env->NewStringUTF(“ints”), intArray);}

      // delete the file handle, but don't close any file descriptors native_handle_delete(handle);return bundle;} 它主要調(diào)用了HAL層的open_data_source()函數(shù)。取得一些文件描述符等信息。接下來(lái)SensorThread創(chuàng)建一個(gè)線程,調(diào)用start()就進(jìn)入SensorThreadRunnable類的run()函數(shù)了,所以我們接著去看run()函數(shù),它首先調(diào)用open()函數(shù) if(!open()){ return;} 在open()函數(shù)中調(diào)用了 jni函數(shù)sensors_data_open(fds, ints);static jint sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray){ jclass FileDescriptor = env->FindClass(“java/io/FileDescriptor”);jfieldID fieldOffset = env->GetFieldID(FileDescriptor, “descriptor”, “I”);int numFds =(fdArray ? env->GetArrayLength(fdArray): 0);int numInts =(intArray ? env->GetArrayLength(intArray): 0);native_handle_t* handle = native_handle_create(numFds, numInts);int offset = 0;

      for(int i = 0;i < numFds;i++){ jobject fdo = env->GetObjectArrayElement(fdArray, i);if(fdo){ handle->data[offset++] = env->GetIntField(fdo, fieldOffset);} else { handle->data[offset++] =-1;} } if(numInts > 0){ jint* ints = env->GetIntArrayElements(intArray, 0);for(int i = 0;i < numInts;i++){ handle->data[offset++] = ints[i];} env->ReleaseIntArrayElements(intArray, ints, 0);}

      // doesn't take ownership of the native handle return sSensorDevice->data_open(sSensorDevice, handle);} 這函數(shù)最終調(diào)用了HAL層的data_open(),之后run()函數(shù)就進(jìn)入一個(gè)while循環(huán)了。while(true){ // wait for an event final int sensor = sensors_data_poll(values, status, timestamp);

      int accuracy = status[0];synchronized(sListeners){ if(sensor ==-1 || sListeners.isEmpty()){ if(sensor ==-1){ // we lost the connection to the event stream.this happens // when the last listener is removed.Log.d(TAG, “_sensors_data_poll()failed, we bail out.”);}

      // we have no more listeners or polling failed, terminate the thread sensors_data_close();mThread = null;break;} final Sensor sensorObject = sHandleToSensor.get(sensor);if(sensorObject!= null){ // report the sensor event to all listeners that // care about it.final int size = sListeners.size();for(int i=0;i ListenerDelegate listener = sListeners.get(i);if(listener.hasSensor(sensorObject)){ // this is asynchronous(okay to call // with sListeners lock held).listener.onSensorChangedLocked(sensorObject, values, timestamp, accuracy);} } } } 它調(diào)用了jni函數(shù)sensors_data_poll()一直讀數(shù)據(jù)。static jint sensors_data_poll(JNIEnv *env, jclass clazz, jfloatArray values, jintArray status, jlongArray timestamp){ sensors_data_t data;int res = sSensorDevice->poll(sSensorDevice, &data);if(res >= 0){ jint accuracy = data.vector.status;env->SetFloatArrayRegion(values, 0, 3, data.vector.v);env->SetIntArrayRegion(status, 0, 1, &accuracy);env->SetLongArrayRegion(timestamp, 0, 1, &data.time);}

      return res;} 把傳感器得到的值都放在value數(shù)組中,根據(jù)返回的傳感器標(biāo)志sensor,把它分派給在sListener列表中所有的listener,如果listener中有監(jiān)聽這個(gè)sensor,就把它分派給這個(gè)listener,此時(shí)就會(huì)引起onSensorChange()了。

      好了,獲取傳感器數(shù)據(jù)主要是這樣一個(gè)途徑。最后我們?nèi)シ治鲆幌聈nregisterListener()函數(shù)。

      private void unregisterListener(Object listener){ if(listener == null){ return;} try { synchronized(sListeners){ final int size = sListeners.size();for(int i=0;i ListenerDelegate l = sListeners.get(i);if(l.getListener()== listener){ // disable all sensors for this listener for(Sensor sensor : l.getSensors()){ String name = sensor.getName();int handle = sensor.getHandle();mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);} sListeners.remove(i);break;} } } } catch(RemoteException e){ Log.e(TAG, “RemoteException in unregisterListener: ”, e);} } 不用想這個(gè)函數(shù)會(huì)做一些與registerListener相反的事情,至少差不多。它先在sListeners列表中找到這個(gè)listener,然后先調(diào)用enableSensor()函數(shù)禁止這個(gè)傳感器。我們跟蹤一下這函數(shù),在SensorService類中。synchronized(mListeners){ if(enable!=SENSOR_DISABLE &&!_sensors_control_activate(sensor, true)){ Log.w(TAG, “could not enable sensor ” + sensor);return false;}

      Listener l = null;int minDelay = enable;for(Listener listener : mListeners){ if(binder == listener.mToken){ l = listener;} if(minDelay > listener.mDelay)minDelay = listener.mDelay;}

      if(l == null && enable!=SENSOR_DISABLE){ l = new Listener(binder);binder.linkToDeath(l, 0);mListeners.add(l);mListeners.notify();}

      if(l == null){ // by construction, this means we're disabling a listener we // don't know about...Log.w(TAG, “l(fā)istener with binder ” + binder + “, doesn't exist(sensor=” + name + “, id=” + sensor + “)”);return false;}

      if(minDelay >= 0){ _sensors_control_set_delay(minDelay);}

      if(enable!= SENSOR_DISABLE){ l.addSensor(sensor, enable);} else { l.removeSensor(sensor);deactivateIfUnusedLocked(sensor);if(l.mSensors == 0){ mListeners.remove(l);binder.unlinkToDeath(l, 0);mListeners.notify();} }

      if(mListeners.size()== 0){ _sensors_control_wake();_sensors_control_close();} } return true;你們看到它的實(shí)現(xiàn)了吧。如果enable是true的話,就調(diào)用_sensors_control_activate(),如果是false的話,就調(diào)用deactivateIfUnusedLocked(),它們最終都會(huì)調(diào)用 HAL層的active()函數(shù)。最后,如果是禁止傳感器的話,如果mListeners為空了,它就會(huì)調(diào)用 _sensors_control_wake();_sensors_control_close();這兩個(gè)jni函數(shù),最終會(huì)調(diào)用HAL層的wake()和close_data_source()函數(shù)。當(dāng)調(diào)用wake()函數(shù)時(shí),會(huì)使SensorManager類線程的run()函數(shù)中的sensor_data_poll()函數(shù)立即返回,此時(shí)在run()函數(shù)中調(diào)用sensors_data_close();最終會(huì)調(diào)用HAL層的data_close()函數(shù)。至此,一個(gè)傳感器從初始到結(jié)束的流程就分析完了。

      所以在java使用一個(gè)傳感器在HAL層具體調(diào)用的函數(shù)流程為: 首先,sensors_control_open(),只在系統(tǒng)初始化時(shí)調(diào)用一次。用來(lái)初始化control_device結(jié)構(gòu)體。

      以下的是每次使用傳感器一般經(jīng)過(guò)的流程,注意,是一般而已,有些并不執(zhí)行(1)sensors_data_open(2)get_sensors_list(3)activate(4)set_delay(5)open_data_source(6)data_open(7)poll 一直讀數(shù)據(jù)。。。。。。退出時(shí)(8)activate(9)sensors_control_close(10)data_close

      當(dāng)然其它的細(xì)節(jié)你們可以繼續(xù)去研究。也可以在我博客里提出來(lái)大家交流和討論一下!發(fā)表于 @ 2010年04月15日 09:25:00 | 評(píng)論(15 AddFeedbackCountStack(“5487476”))| 編輯| 舉報(bào)| 收藏

      var CurrentEntryId = '5487476';var CurArticleTitle = '閱讀android有關(guān)sensor的源碼總結(jié)';var AllowComment = 'True';var AllowAnonymousComment = /^true$/i.test('False');匿名用戶 發(fā)表于Saturday, April 24, 2010 4:10:24 PM IP:舉報(bào)回復(fù)刪除挺好的,可是我有一點(diǎn)疑問(wèn)呢?匿名用戶 發(fā)表于Wednesday, May 05, 2010 10:44:44 AM IP:舉報(bào)回復(fù)刪除代碼中怎么沒(méi)有看到hal stub的東西???我想知道open等操作的具體實(shí)現(xiàn)(非kenne層)匿名用戶 發(fā)表于Thursday, May 06, 2010 11:42:40 PM IP:舉報(bào)回復(fù)刪除回復(fù) 匿名用戶: check sensors_device_open()in sensor.c 匿名用戶 發(fā)表于Friday, May 07, 2010 12:12:08 AM IP:舉報(bào)回復(fù)刪除我看了詳細(xì)代碼,講得很好。流程大概就是這樣了。估計(jì)你沒(méi)有hal層代碼,因?yàn)槟鞘切酒瑥S商提供或者自己寫的。很難寫。匿名用戶 發(fā)表于Saturday, May 08, 2010 12:04:55 AM IP:舉報(bào)回復(fù)刪除Hal usually has folling functions: 1.Sampling Device manager notifies sensor drivers via ioctl to refresh sensor data.Sensor drivers usually utialize i2c bus API functions(i.e.i2c_transfer())to fetch data.2.Reporting After sampling, sensor device drivers report sensor data through input device via input device API functions(i.e.input_report_xxx()and input_sync())3.in sensor_xxx.c or sensor_xxx.cpp, dev->device.poll = sensors_data_poll;sensors_data_poll()is a static function to pick sensor, poll and read sensor data.In Platform: 1.in android_hardware_SensorManager.cpp jni function sensors_data_poll()is provided for SensorManager.java to poll sensor data.sensors_data_poll()actually calls sensors_data_poll()in sensor_xxx.c /sensor_xxx.cpp.2.In SensorManager.java.registerListener()would call sSensorThread.startLocked().sSensorThread.startLocked()would create a new thread based on SensorThreadRunnable()that calls sensors_data_poll().3.In SensorThreadRunnable()listener.onSensorChangedLocked()is called to notify the Sensor event listener after polling sensor data.tigerhily 發(fā)表于Thursday, June 03, 2010 10:08:06 PM IP:舉報(bào)回復(fù)刪除jerry: 講得真好!頂一個(gè)。請(qǐng)問(wèn)你有HAL的具體實(shí)現(xiàn)嗎?我想?yún)⒖家幌?。或者講講sensors_data_open(3)activate(4)set_delay(5)open_data_source(6)data_open(7)poll 這些接口的具體實(shí)現(xiàn)!謝謝匿名用戶 發(fā)表于Saturday, June 05, 2010 12:15:03 AM IP:舉報(bào)回復(fù)刪除Tigerhily: 1.poll()is usually via input_event.Please get poll()reference from EventHup.cpp is you do not have sensor_xxx.c or sensor_xxx.cpp.input_event is device independent abstraction layer provided by the kernel.2.set_delay()starts from SensorManager.java, it calls native delay function in snesor_xxx.c or sensor_xxx.cpp.sensor_xxx.c or sensor_xxx.cpp calls ioctl to set delay value to sendor device driver.sensor device driver usually creates a miscdevice to accept ioctl command.3.Sensor device driver utilizes delay to adjust sampling rate and retrieves data via i2c bus and saves the data via input_event to let application pull sensor data.tigerhily 發(fā)表于Sunday, June 06, 2010 8:48:21 PM IP:舉報(bào)回復(fù)刪除回復(fù) 匿名用戶:hi jerry:Thanks for your help.Actually I don't have sensro_xxx.c and i am going to implement it.I will try and consult if needed.Thanks.lz_fine 發(fā)表于Tuesday, August 03, 2010 2:08:17 PM IP:舉報(bào)回復(fù)刪除你好,我現(xiàn)在也在做這塊,但是我遇到一個(gè)問(wèn)題,我在HAL層的sensor.c中control__activate()函數(shù)中打開設(shè)備文件/dev /sensor成功,并且能執(zhí)行ioctl操作,但是到了data__poll()函數(shù)中再執(zhí)行ioctl就失敗了,報(bào)告的錯(cuò)誤是Bad file number,errno是EBADF,看起來(lái)好像是這個(gè)fd被關(guān)閉了,這個(gè)怎么也想不通,因?yàn)榭雌饋?lái)SensorThread還在跑,而且在 sensor.c中也沒(méi)有執(zhí)行close操作,這種情況有沒(méi)有遇到過(guò)啊,能解釋一下嗎,感激不盡lz_fine 發(fā)表于Wednesday, August 04, 2010 3:55:43 PM IP:舉報(bào)回復(fù)刪除找到ioctl失敗的原因了,是在SensorManager.java中關(guān)閉fd的,不過(guò)正常情況下sensor.c中應(yīng)該先復(fù)制一個(gè)fd,因此加上一句復(fù)制fd的語(yǔ)句就可以了,終于搞定了,內(nèi)牛滿面啊iceskyang 發(fā)表于Thursday, August 05, 2010 11:02:16 AM IP:舉報(bào)回復(fù)刪除問(wèn)一下,如果加入后臺(tái)進(jìn)程用來(lái)輔助計(jì)算加速度磁場(chǎng)的值,那么這個(gè)進(jìn)程為什么會(huì)在一開機(jī)后就運(yùn)行的。我在int.rc中明明設(shè)置了disabled。

      第四篇:Android4.0編譯錯(cuò)誤記錄

      1.make: ***

      [out/host/linux-x86/obj/STATIC_LIBRARIES/libMesa_intermediates/src/glsl/linker.o] Error 1 解決方法: vim external/mesa3d/src/glsl/linker.cpp

      添加:

      #include

      2.make: ***

      [out/host/linux-x86/obj/EXECUTABLES/test-librsloader_intermediates/test-librsloader] Error 1 解決辦法:

      vim external/llvm/llvm-host-build.mk

      添加:

      LOCAL_LDLIBS :=-lpthread-ldl

      3.make: ***

      [out/host/linux-x86/obj/STATIC_LIBRARIES/libgtest_host_intermediates/gtest-all.o] Error 1 解決方法:

      vim external/gtest/include/gtest/internal/gtest-param-util.h

      添加:

      #include

      4.

      第五篇:32位Ubuntu 11.10下android2.3.7源碼下載與編譯小結(jié)

      32位Ubuntu 11.10下android2.3.7源碼下載與編譯小結(jié)

      1、我是在vmware下安裝ubuntu 11.10的,這個(gè)網(wǎng)上資料很多,不多說(shuō)了。我給ubuntu分了25g硬盤和1g內(nèi)存。

      2、請(qǐng)參照http://source.android.com/source。初始化編譯環(huán)境 檢查一下包是否安裝: Python 2.4-2.7 Git 1.5.4 或更高版本

      沒(méi)有話可以sudo apt-get install..安裝一下

      JDK 6 因?yàn)槭蔷幾gandroid2.3以上,如果編譯2.2以下需要JDK5 安裝JDK6:

      $ sudo add-apt-repository“deb http://archive.canonical.com/ lucid partner” $ sudo apt-get update $ sudo apt-get install sun-java6-jdk 如果下載速度不行,可以先把ubuntu的更新源改成網(wǎng)易的源,可參考:http://bolg.malu.me/html/2010/279.html。其他需要安裝的包:

      我安裝了如下包:官網(wǎng)上那是64位需要安裝的包,我是32位的有些不一樣。

      $ sudo apt-get install git-core gnupg flex bison gperf libsdl1.2-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev x11proto-core-dev libx11-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils

      3、下面開始下載源碼

      首先安裝repo(是一個(gè)便于git管理的工具)$ mkdir~/bin $ PATH=~/bin:$PATH $ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo $ chmod a+x~/bin/repo 初始化repo client $ mkdir android2.3.7 $ cd android2.3.7 初始化repo,我是使用的下面的地址,使用官網(wǎng)地址時(shí)出現(xiàn)了網(wǎng)絡(luò)錯(cuò)誤

      $ repo init-u http://android.googlesource.com/platform/manifest.git-b android-2.3.7_r1

      按照提示輸入用戶名和郵箱。接著 $ repo sync 開始同步源碼,根據(jù)你的網(wǎng)速,我的持續(xù)了50分鐘左右。

      還有一步驗(yàn)證git tags可參照官網(wǎng)。下完后就可以在剛才創(chuàng)建的android2.3.7文件夾下看見已下載的源碼。

      4、開始編譯 初始化:

      $ source build/envsetup.sh $ lunch full-eng 上面代表編譯的一個(gè)target,full是針對(duì)emulator編譯全部包括app、輸入法等,eng是指針對(duì)開發(fā)者編譯,有最高權(quán)限。具體可參見官網(wǎng)。

      接著就可以編譯了,在源碼目錄下直接make就行,需要一段時(shí)間。編譯過(guò)程中有幾個(gè)問(wèn)題需要指出一下: 問(wèn)題1:

      由于我們是32位系統(tǒng),所以有些文件需要修改一下:將./external/clearsilver/cgi/Android.mk./external/clearsilver/java-jni/Android.mk./external/clearsilver/util/Android.mk./external/clearsilver/cs/Android.mk 四個(gè)文件中的

      LOCAL_CFLAGS+=-m64 LOCAL_LDFLAGS+=-m64

      注釋掉,或者將“64”換成“32”

      LOCAL_CFLAGS+=-m32 LOCAL_LDFLAGS+=-m32

      然后,將./build/core/main.mk 中的

      ifneq(64,$(findstring64,$(build_arch)))

      改為:

      ifneq(i686,$(findstring i686,$(build_arch)))

      問(wèn)題2:

      frameworks/base/libs/utils/RefBase.cpp:483:67: android::RefBase::weakref_impl?

      as

      ?this?

      error:

      passing

      of

      ?const ?void

      argument android::RefBase::weakref_impl::trackMe(bool, bool)? discards qualifiers [-fpermissive] make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] error 1 如下解決:

      $ gedit frameworks/base/libs/utils/Android.mk 將下面一行

      LOCAL_CFLAGS+=-DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)改成

      LOCAL_CFLAGS+=-DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)–fpermissive 問(wèn)題3:

      :0:0: warning: “_FORTIFY_SOURCE” redefined [enabled by default]

      :0:0: note: this is the location of the previous definition cc1plus: all warnings being treated as errors make: *** [out/host/linux-x86/obj/EXECUTABLES/obbtool_intermediates/Main.o] Error 1 這是由于11.10的gcc

      版本過(guò)高造成的,可參考這篇文章修改:http://hi.baidu.com/designhouse/blog/item/fec5cdbf8d6a231618d81fc1.html。至此編譯完畢。

      make編譯的并不是所有內(nèi)容,不包含內(nèi)核和SDK。映像生成在out/target/product/generic

      下:android

      源碼編譯后得到system.img,ramdisk.img,userdata.img映像文件。其中,ramdisk.img是一個(gè)分區(qū)映像文件,在kernel啟動(dòng)時(shí),ramdisk被用來(lái)調(diào)用init,以及把真正的root file system mount起來(lái)。system.img包括了主要系統(tǒng),系統(tǒng)app等,會(huì)被掛載到/下,可對(duì)應(yīng)查看./system該目錄,可以發(fā)現(xiàn)在其下app/下有一些系統(tǒng)自帶的應(yīng)用程序。userdata.img包括了一些用戶數(shù)據(jù),被掛載到/data下,對(duì)應(yīng)可查看./data/目錄,emulator加載這3個(gè)映像文件。

      5、編譯SDK 編譯SDK可以得到與源碼同步的SDK,還會(huì)生成一些tools,在源碼根目錄下:

      $ sudo make PRODUCT-sdk-sdk 編譯生成的SDK在out/host/linux-x86/SDK下。之后如果在ubuntu下使用eclipse進(jìn)行開發(fā),可以使用你編譯的SDK。

      下面就在模擬器中運(yùn)行鏡像,建議切到root用戶下,首先配置幾個(gè)環(huán)境變量,將自己編譯的SDK設(shè)為優(yōu)先級(jí)最高,在源碼根目錄下執(zhí)行:

      $sudo update-alternatives

      --install/usr/bin/AndroidSDK

      AndroidSDK

      /home/zhaolin/AndroidSource_GB/out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86255 這樣會(huì)在/etc/alternatives下生成一個(gè)指向該SDK目錄的軟連接AndroidSDK,這個(gè)目錄主要存放一些系統(tǒng)默認(rèn)打開的程序的信息和配置。那么/usr/bin/AndroidSDK就指向這個(gè)軟連接。接著執(zhí)行:

      gedit~/.bashrc 在文件末尾添加:

      export ANDROID_SDK_HOME=/usr/bin/AndroidSDK export PATH=$ANDROID_SDK_HOME/tools:$PATH export ANDROID_PRODUCT_OUT=~/android2.3.7/out/target/product/generic 接著就可以執(zhí)行:

      $ emulator 運(yùn)行的就是你編譯的映像。執(zhí)行emulator 命令時(shí),如果不帶任何參數(shù),則Linux Kernel鏡像默認(rèn)使用~/Android/prebuilt/android-arm/kernel目錄下的kernel-qemu文件,而

      Android鏡像文件則默認(rèn)使用ANDROID_PRODUCT_OUT目錄下的system.img、userdata.img和ramdisk.img。模擬器運(yùn)行需要這四個(gè)文件,如果你編譯了內(nèi)核則可以使用自己的Kernel鏡像,可用于android移植等。

      6、單獨(dú)編譯模塊

      如果你不想編譯整個(gè)系統(tǒng),就想編譯某一個(gè)應(yīng)用程序,可以使用mmm命令,使用之前,在源碼目錄下先要執(zhí)行:

      $ build/envsetup.sh

      這樣會(huì)生成一些命令,有m即make、mm編譯當(dāng)前目錄下所有模塊、mmm編譯指定目錄下所有模塊。你可以把packages/apps/Music應(yīng)用的application name改成MyMusic(AndroidManifest.xml中),然后執(zhí)行:

      $ mmm packages/apps/Music 在out/target/product/generic/system/app中就可以看見Music.apk,然后執(zhí)行:

      $ make snod 重新生成system.img。

      下載Ubuntu 11.10編譯Android源碼錯(cuò)誤[范文大全]word格式文檔
      下載Ubuntu 11.10編譯Android源碼錯(cuò)誤[范文大全].doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦