Android中的声音部分之我的见解

Android9.2.2中的声音部分之我的见解

——一个初级开发者的见解

开言:本文是基于我这些天对Android的学习,并综合了网络上的各位高人们的见解,加上自己对系统的认识,写出了这篇文章。可能存在不足,如果在你的工作学习中发现我的不足之处,还请指正,联系Q617338623

Android系统中声音,主要是通过一个叫做ALSAALSAAdvanced Linux Sound Architecture,高级Linux声音架构的简称,它在Linux操作系统上提供了音频和MIDIMusical Instrument Digital Interface,音乐设备数字化接口)的支持。)来与硬件进行打交道,这部分我们一般不需要改动。相关文件可见/hardware/alsa_sound中,这之中主要进行音频音道,还有波形,甚至还有线路音量等这些东西,这个中的东西产生出的结果就类似于我们双击windows系统的右下角小喇叭时打开的那些一样,他们就是实现这部分功能的,因此我们一般不需要动他们,除非你是搞驱动或者进行与语音设备有关工作的。大部分我也看不懂。如果需要,每个文件都很重要,如果不需要,那么他们都不重要。

ALSA高级一点的就是系统框架层提供的一些以Audio(音频)打头的文件了,这部分文件与ALSA框架层合作非常紧密,他的下面就是ALSA。同时,他的上面就是我们平时使用的各种音量。如你看电影时所使用的音量。简单点说就是你看电影时,假设你的音量是12,那么这个数值首先通过你的电影播放器传递给了Audio这些文件,有这些文件进行初步处理后(如转化为ALSA可以识别的数值类型等),再传后ALSAALSA仅能处理这些符合规则的数据。这部分Audio打头的文件主要位于:frameworks/base/media/java/android/media中。在这个文件夹下包含有很多的各种关于声音处理的文件,重要文件主要是AudioManager.javaAudioServices.javaAudioSystem.java。仔细看完这些文件,相信你会有很大的收获。(个人一点小技巧:虽然鄙人的英语四六级都只考了一次,但是我在看这些文件的时候,还是用有道词典的屏幕取词的功能对那些自己不熟悉的词语直接进行翻译,猜测其意思,能加快你理解他们的速度。)同样,在这里我也会为你稍微的解释一下这些文件中的内容以及音频调节的基本方法,以此来帮助你的理解。

我们先来初步认识一下Android中的声音,对于一个设备,尤其是这种复杂的手持设备而言,声音是区别不同程序的一个重要方法,通俗点讲就是你听到来电铃声绝对不会认为是你的手机突然莫名其妙自己开始播放音乐了吧,但是对于硬件而言,放音乐和放铃声有差别么?没有,但是他们的含义一样么?肯定不一样,所以Android系统为声音进行了分类,他划分为   STREAM_VOICE_CALL   STREAM_SYSTEM   STREAM_RING  STREAM_MUSIC STREAM_ALARM  STREAM_NOTIFICATION STREAM_BLUETOOTH_SCO   STREAM_SYSTEM_ENFORCED   STREAM_DTMF  STREAM_TTS这十种类型,分别是语音(就是通话时声音),系统声音,铃声,音乐,警报,注意(或者叫提醒)等等(后面几个我只是大概知道是和什么有关的,具体我也不知道名称)。这每一种类型都是一种流(声音就像是水流一样,呵呵很诗意)。其次,他还为这些不同类型的声音水流定义了他们的流量,呵呵就是音量了,定义在一个叫做DEFAULT_STREAM_VOLUME的数组中,这是一个默认的音量大小数组,换句话说就是如果你的应用程序没有对这十种类型中的某一种在自己的程序中进行音量大小定义的话,他们就会使用这个默认数组中的声音音量大小。所以如果你要对声音进行调整,首先你要明白你要调整的声音是属于什么类型的,然后在看他们的音量。然后再往下看,下面似乎是一些mode,怎么理解呢?这个是模式。你用过手机么?手机有静音,我们的Android就是为手机开发的,所以当然也要有静音(RINGER_MODE_SILENT)了,手机有震动,我们的Android当然也有震动(RINGER_MODE_VIBRATE)了,当然还有正常模式(RINGER_MODE_NORMAL)了,其次很有与此相关的很多可能会用到的东西,如标记(flag)调整度(adjust)等。不过这些都不重要了。下面我们看文件。

AudioManager.java文件:这个文件中,我们会发现,他简直就是一个类似于c/c++中的.h文件,他里面主要就是定义了各种各样的类型,数据,and so on。重要的是他里面下面定义了很多函数,不过仔细一看这些函数,你就会发现他们都没有实现,都只是简单的进行了一个声明,然后自己调用下自己,try一下,有错误了就抛出。别担心,别害怕,我们马上就知道他们都是在呢实现的了。这个文件很重要,很值得你以后仔细看(注意不是现在),因为这个文件中定义的所有的函数都是带有注释的,在注释中,主要介绍了这些函数的功能,参数,返回值,被使用到的地方等等。这些很重要,因为一会你看到他们的实现的时候,你可能会不知道他们什么用,这时候,你就可以来这里查找了。

AudioServices.java文件:打开这个文件第一眼,你也会发现各种各样的定义,这些定义中有些会覆盖掉Manager文件中的定义,有些会作以补充,只要看看他们,结合硬件的具体你就很容易能搞明白他们每一个参数的大概含义,实在不行了结合着Manager文件中的相似或者相同的这个参数的说明看看就明白了。这个文件中最重要的是对Manager文件中的各种方法进行了实现。因此,如果你需要对声音的某一个过程进行席位调节的话,基本上就可以在这里找到对应的函数,在她们之中进行修改就可以了。

AudioSystem.java文件:嘻嘻,这个我也看不明白,我认为应该是系统定义文件,就是概括性的,内容也不多。看过去我也没有找到和我手头活计相关的,所以就略过了。

哦,对了,还有一个重要性的文件,就是位于和他们这三个文件平行的目录下,路径是/frameworks/base/media/libmedia/中,我在里面发现了一个很有趣的函数,叫做LogToLinear()对应的还有一个LinearToLog(),字面理解就是线性到对数和对数到线性,这个函数就完成了我们从声音的1234……131415这样的整数到声音分贝的一个转化。那么多文件怎么找到这个函数?因为我的是Linux环境,所以建议使用grep –r “/*name*/” .命令查找。为什么说这个有趣,看了下面的红色字体标出的描述,你就该明白了。

因为我们的喇叭放声是通过电平变化得到的,所以我们需要将一个电平转化为对应的声音分贝值,下面是从百科上得到的一个公式,差不多能帮助你的理解,当然这个公式正确性不高,不是说公式不正确,而是你要明白,因为声音的分贝算法并不是线性的(近似于log函数的),所以推知控制音量的电流应该也不是线性的,故而我们需要把线性的音量大小调整为非线性的电流,从而发出合理的声音。(注:我曾经把这个函数改为线性的输出,结果很悲剧,出来的声音就像是上台阶一样,每几个连续音量之间,声音大小没有改变,到了某一个又突然变化,然后又没有了改线,过几个后又突然变化。我叫他们台阶效应。)

利用功率关系所确定的电平可以称为功率电平(需要计量的功率值和功率为一毫瓦的零电平功率比较),用数学表达式描述就是: 

  Pm=10 lg(P/1)dBm 

其中:Pm代表功率电平。P代表需要计量的绝对功率值,单位为毫瓦,零电平功率为一毫瓦。dBm表示以一毫瓦为基准的功率电平的分贝值。

还忘记了一点,在Android系统中,对声音的调节是通过数学算法控制的,而不是通过硬件控制的,什么个意思呢?就是说在一些的设备中声音控制是可以通过硬件控制的,拆过收音机的朋友都知道,收音机的的音量控制就是一种典型的硬件控制,当然现在的硬件控制高明多了,但这不是咱们本文讨论的重点。个人感觉硬件控制和软件控制的差别就是在于那个转化函数是在什么地方实现的。

以上所述,都是得到一个音量后,系统在呢怎么实现的,下面我们谈谈系统怎么得到一个音量,貌似很简单的问题,真的,我们可以自己假设一个得到的音量的办法,比如,我们首先取得当前音量假如为9(别跟我说铃声音量只有7个单位),然后我们按下了增加音量的键,我总结了一下,系统一共提供三种增加音量的办法,第一种,按键,应该是侧面按键。第二种,在设置中的音量栏中有一个seekBar拖动条,直接拖动。第三种,主界面上面的状态栏中有一个加减按钮。不管用那种办法,先增加一个音量再说,我们点击一下加号或者向右拖动一小次,或者按下音量增加键一下。我们来猜想下系统应该是怎么工作的。

第一种可能工作办法:分门别类对待,就是系统将这三种的增加分别用一个办法实现,然后么,想到系统中还有那么多种的不同类型的音量,每种都要有三个实现,共计3*n,这个实现部分要么很多,要么很大,找,没找到,所以不是。

第二种办法,我没有想到,但我想到还是来看看代码吧,经过了数天的头晕目眩之后,总结出了点成果,为了让你看起来不在那么痛苦,我决定将我的这点成果直接给你。好好学习,天天向上哦。

还有什么可能的办法呢?我们来看看Android的系统结构。在Android中有几个很重要的东西,有些资料上面叫他们应用,我个人觉得还是叫概念比较好。什么概念或者应用呢?

第一个重要概念:avtivity,字面意思,活动。发挥你作为一个程序员的丰富想象力,活动,活着动,应该是现在执行的操作一类的东西吧?差不多吧,看看资料书,不用研究的太透彻,反正我是没有明白的那么深刻,我就是这样认为的,当前我们执行的操作就是一个活动,活动对于整个系统而言,就是当前的一个一个的页面,不管怎么样,我们总是处在某一个页面上,你永远不可能脱离了页面,就算是开机的时候,你什么也做不来,还有一个页面呢(当然那个跟antivity有点远了)!这个当前所处的页面就是一个活动,这个活动有自己的生命周期,有自己的个性(页面总不同吧)另外一个名字叫属性。

第二个重要概念:services,字面意思,服务。什么是服务?你打中国移动客服,他们会为你服务,只要中移动不倒闭,服务就不会停止,就是7*24的,而且不管你用不用。所以通用过来,系统中的服务我们可以理解为后台运行的一些进程(中移动客服是否曾经经常的主动给你打电话:先生,请问你需要服务么?),这些进程等待着特定的事件发生(你打了10086:给我查查话费),这时候,他们才能按照事件来进行相应处理(请挂机,话费信息稍后发送到你的手机)。一个典型的服务就是中断,随时等待,只要发生,就自动根据中断类型进入不同的中断服务子程序。稍稍和声音牵连下,音频Audio也是一种服务,有部分页面是需要发出声音的,有些却不需要,如你在看视频,那么AudioServices就需要忙起来了,反之,你只是在看电子书,这个服务就可以清闲了,当然你要有后台音乐,他就还是忙的。哦对了,因为音乐播放可以转入后台,就是你离开不了播放页面后,也依然播放,所以media也是一个服务。

第三个概念:broadcast,字面意思,广播,实际含义,还是广播,就是对整个系统的喊一遍,什么什么事情发生了。稍微扯一下,有广播,那么就一定有收听广播的人,这就是broadcastReceiver,他们根据广播出来的事件首先进行判断,看看自己能处理不能,是不是自己的事情,如果是了再进行自己的处理。请注意,事件是事先说好的,术语来说就是必须先注册,只有注册的事件才能被接收,未注册事件,可以广播,只是会报错的(好像不会导致系统崩溃,只是抛出一个异常)。

有了以上三个概念,我们就可以说说系统怎么调整声音,Android系统中,采用的办法就是广播,不管你按了什么还是拖动了什么,都会产生一个广播(可能好像貌似在音量调节界面上直接拖动声音不会产生广播,你可以自己分析 一下),如你按下了音量增加一次的按钮/键,对应的状态栏会产生一个音量增加的广播,然后呢,系统中的各种服务就监听这个广播。当然可以接收这个广播事件的主要就是AudioService这个服务,AudioService监听到这个事件之后,他开始做的事情是查找当前的正坐在活动的Activityof course,他也会顺便检查当前的是否有MediaService这样的可能会挤掉当前Activity的服务是否正在进行,如果进行着,那么就把流从默认的当前的类型置换为Service对应的音量类型(注意:这一步也会在这种特殊的Service启动的时发生,那么AudioService中音量类型就已经是Service对应的音量类型),因为后台此时的活动进程所提供的Service的优先级高于当前的Activity的优先级,但这也依旧不是固定死的,在特殊页面上,如音量调整页面,此时Activity的优先级又高于MediaService,(这取决于系统内部定义的一系列非常复杂的优先级常量,见于AudioManager.java,我是没有弄明白那么多的flag都是怎么牵扯的)Do not care,一般情况下都是activity 居多,因为service正常情况下启动时就会更改Volume_type。当没有Service优先于avtivity时,Audioservices他就可以根据当前活动决定是什么类型的音量,然后调整到对应的音量类型上,再做音量加一次的操作。而且,在Android系统中,不支持音量的直接跳变,什么个意思呢?就是说,每次音量改变,只能是增加一,或者是减少一,你不能一次增减好几个幅度,你当前是7,你下一次只能调整为6或者8,而不能一次调整为……45910,……这些其他的音量。即使你使用进度条拖动,效果也是一样,不能瞬变。当音频服务完成了音量的调整之后,他也一样会发出一个通知,他为什么要发出通知呢?很简单,因为音量在有些情况下的调整可能会涉及状态的调整,这种状态的调整就又涉及到其他的譬如某些功能是否开启等,所以必须通知。

一个例子是状态栏,我们点了状态栏中的音量加一次,状态栏就会发出一个volume_up的广播,然后AudioService收到这个广播后,就来检查当前活动,如果有Media,那么就将音量类型是music的音量加一,如果是默认,就将ring音量加一,该调整状态的就调整状态(如音量没有了等零了,就将状态改为震动)。完了之后广播出去,突然状态栏监听到了,那么就看看是不是涉及图标变化,音量减为零自动增加一个震动图标,updateIcon。这样音量加减就算是真正完成了。

下面是我从网络上找到的部分相关的介绍,可能部分内容也和我的一样,对错参半,对你,都只是参考,要有自己的理解把握。

首先,我们对这些文档提供者表示感谢!很多我抓下来的时候也没有标明出处,所以我也不了解是否可以这样转载。如果你看到属于你的东西了,并且不希望被这样推出来,你可以跟我联系(联系方式见文章首页),我及时拿下。其次,如果你是一名阅读者,不管他们所述的是对还是错,请你还有我都对他们的奉献表示感激。谢谢这些文档的原始作者。

第一个个参考:

音量调整分为两步:先查看模式(Ring mode)是否需要调整,如果不需要调整模式,当前模式一定是正常模式(Normal mode),那就需要调整音量。 

调整模式通过调用checkForRingerModeChange(oldIndex, direction);实现,调整音量通过调用streamState.adjustIndex(direction)实现。具体代码参考/framework/base/media/java/Android/media/AudioService.java中的public void adjustStreamVolume(int streamType, int direction, int flags)方法。

该方法先检查模式是否需要调整,再进行音量调整。调整完毕后,做了两件事:

1、通过mVolumePanel.postVolumeChanged(streamType, flags);向用户显示改变结果。

2、通过sendVolumeUpdate(streamType);广播音量有改变的系统事件。

改变音量这个功能与用户界面有关的有两个部分,分别是/framework/base/core/java/Android/view/VolumePanel.java/framework/base/services/java/com/android/server/status/StatusBarPolicy.java

VolumePanel主要负责向用户显示一个Toast,告诉用户目前的模式(Ring Mode)和音量大小。每次AudioService通过向post一系列MessageVolumePanel,来驱动Toast的显示。

StatusBarPolicy主要负责在静音模式(silent mode)和振动模式(vibrate mode)下在状态栏(status bar)的右方显示一个代表相应意义的图标。

系统启动后,StatusBarPolicy会注册一个Receiver,它可以接收很多种广播,其中就有AudioService在完成每一次的模式和音量更新时发出的两个广播事件AudioManager.RINGER_MODE_CHANGED_ACTIONAudioManager.VIBRATE_SETTING_CHANGED_ACTION

接收到这两个事件时,StatusBarPolicy就会调用updateVolume()来更新状态栏上的图标。

第二个参考:

首先上层java调用

XXXPlayer

AudioManager audiomanage = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

audiomanager就是我们定义的控制系统声音的对象,(如果context报错,可将其改成XXXPlayer.this

audiomanager.SetStreamVolume(AA,BB,CC),是我们可以直接使用的AudioManager的成员函数,3个参数表示的意思:AA:有内置的常量,可以在AudioManager里面查到相关的定义,我们在此用 AudioManager.STREAM_MUSIC, BB:自己设置音量的值,CC:也是一些标示量,我在此设置为0

1.AudioManager.java

public void setStreamVolume(int streamType, int index, int flags);上层接口

   1)调用IAudioService service = getService(); 当程序开启时会获得service,调用此来获得

2.ServiceManager.java 

public static IBinder getService(String name)获取audio服务

3.AudioService.java 

public void setStreamVolume(int streamType, int index, int flags)//服务接口

   1) private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible)//服务函数

   2) sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,streamState, 0) //Post message to set system volume (it in turn will post a message to persist)

3)AudioHandler::setSystemVolume(VolumeStreamState);//sendmsg(...)后执行函数

   4)调用AudioHandler::setStreamVolumeIndex(int stream, int index)

   5)AudioSystem.setStreamVolumeIndex(stream,index);//audioSystem接口

4.AudioSystem.java

   public static native int setStreamVolumeIndex(int stream, int index);

5. android_media_AudioSystem.cpp

   static int android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, jint index);

6.AudioSystem.cpp

status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index);

status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)(处理到这时,也可以直接走AudioFlinger路线,不经过策略) 

7.AudioPolicyService.cpp

   status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index);

8.AudioYusuPolicyManager.cpp

   status_t AudioYusuPolicyManager::setStreamVolumeIndex(AudioSystem::stream_type stream, int index);

1)记录音量index: mStreams[stream].mIndexCur = index

2)compute and apply stream volume on all outputs:

status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)

3)计算音量:float volume = computeVolume(stream, index, output, device);

9. AudioPolicyService.cpp

1)status_t AudioPolicyService::setStreamVolume( AudioSystem:: stream_type stream,float volume ,audio_io_handle_t output,int delayMs);

2)mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);

3)insertCommand_l(command, delayMs);

4) bool AudioPolicyService::AudioCommandThread::threadLoop();

10.AudioSystem.cpp

   status_t AudioSystem::setStreamVolume(int stream, float value, int output);

11.AudioFlinger.cpp

   1)status_t AudioFlinger::setStreamVolume(int stream, float value, int output);

2)AudioFlinger.cpp MixerThread::threadLoop() ;

3)AudioFlinger.cpp MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove) ;

12.AudioMixer.cpp 

process(void* output) 

补充1)在条用getService();获取服务的时候 ,实际调用的是ServiceManager.getService(context);

系统服务都是由serviceManager来管理的,要添加服务,可以调用serviceManager.AddService(context,service);

每添加一个service,都会有对应的唯一context, getService的时候就会根据context获得相应的服务,可查看ServiceManager.java, ServiceManager.h/cpp

补充2) AudioService 的接口在 IaudioService.aidl中定义。添加自定义功能时( 我们创建控制接口比如创建个音效处理的接口SetEffectVolume(XXX),可以参照SetStreamVolume(a,b,c))别忘了修改此处,否则,AudioManager 会出现cannot find symbol..错误!!!

补充3)编译的时候可能会在Audiomanager.java中调用自己写的接口时出错,此时先将该文件中的调用注释掉,执行 make update-api

执行完成后,将注释去掉,然后从新编译。。。

第三个参考:

调用详细路径如下:

文件 原型 

RingerVolumePreference.java onCheckedChanged(CompoundButton buttonView, boolean isChecked) 

AudioManager.java setStreamVolume(int streamType, int index, int flags) 

AudioService.java setStreamVolume(int streamType, int index, int flags) 

AudioSystem.java native setStreamVolumeIndex(int stream, int index); 

android_media_AudioSystem.cpp android_media_AudioSystem_setStreamVolumeIndex 

AudioSystem.cpp setStreamVolumeIndex(stream_type stream, int index) 

AudioPolicyService.cpp setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 

AudioPolicyManager.cpp setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 

AudioPolicyService.cpp setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0); 

AudioPolicyService.cpp AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs) 

AudioPolicyService.cpp AudioCommandThread::threadLoop() 

AudioSystem.cpp setStreamVolume(int stream, float value, int output) 

AudioFlinger.cpp setStreamVolume(int stream, float value, int output) 

AudioFlinger.cpp MixerThread::threadLoop() 

AudioFlinger.cpp MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove) 

AudioMixer.cpp process(void* output) 

详细步骤:

1.当按音量调节按钮时

会调用RingerVolumePreference::onCheckedChanged,见文件

packages/apps/Settings/res/layout/sound_and_display_settings.xml,

然后就会调用AudioManager::setStreamVolume,一路跟踪直至文件AudioPolicyManager.cpp中的函数setStreamVolumeIndex,它会调用checkAndSetVolume,进而调用mpClientInterface->setStreamVolume,这个mpClientInterface应该是由AudioPolicyService来实现的,所以调用AudioPolicyService.cpp中的setStreamVolume,一直往下看至AudioFlinger.cpp中的setStreamVolume,改变的值保存在数组mStreamTypes中。

另外,当播放音乐时,MixerThread::threadLoop()是一直在运行的,当检测到待播放的track时,就调用函数prepareTracks_l,这个函数里会计算左右声道的音量,并且设置到AudioMixer里,代码如下:

......

                float typeVolume = mStreamTypes[track->type()].volume;

                float v = mMasterVolume * typeVolume;

                float v_clamped = v * cblk->volume[0];

                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;

                left = int16_t(v_clamped);

                v_clamped = v * cblk->volume[1];

                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;

                right = int16_t(v_clamped);

......

                 mAudioMixer->setParameter(AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME0, left);

                 mAudioMixer->setParameter(AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME1, right);             

......

调用函数prepareTracks_l后,继续调用

mAudioMixer->process(curBuf);

从而综合处理音频数据

由上可见,android是利用软件来调节音量,仅仅设置一个硬件音量的最大值().

第四个参考:

核心提示:1. 说明android的后台运行在很多service,它们在系统启动时被SystemServer开启,android系统自带的Service原理与使用,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,硬件提供商按此文件的定义实现其功能hardware/libhardware/include

1. 说明

android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,ClipboardService提供剪切板功能,PackageManagerService提供软件包的安装移除及查看等等,应用程序可以通过系统提供的Manager接口来访问这些Service提供的数据,以下将说明他们的工具流程

2. 举例说明基本流程

android系统支持sensor(传感器)实例来说明框架层的servicemanager是如何配合工作的1) 什么是sensor

sensor是传感器比如控制横竖屏切换利用的就是重力传感器(gsensor), 还有accelerator sensor可取得x, y, z三个轴上的加速度(应用如平衡球小猴吃香蕉等)

2) 应用程序调用(以下为关键代码)

sensorManager=(SensorManager)getSystemService(context.SENSOR_SERVICE);

lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

sensorManager.registerListener(sensorListener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);

3) Manager

a) 提供给应用程序调用的接口,同实与Service交互,实现功能

frameworks/base/core/java/android/hardware/SensorManager.java

4) Service

a) 开机时就运行的管理Sensor的后台服务

frameworks/base/services/java/com/android/server/SensorService.java

b) snesor后台服务需要的JNI,通过它与系统级交互

frameworks/base/services/jni/com_android_server_SensorService.cpp

5) 系统层

a) 传感器的头文件,硬件提供商按此文件的定义实现其功能

hardware/libhardware/include/hardware/sensors.h

b) 传感器的系统层实现,与内核交互,此处通常是硬件提供商提供的

hareware/libsensors

6) 内核及硬件层

内核访问硬件,同时以设备文件等方式提供给上层控制接口和传感器数据

3. 系统层实现

1) frameworks/base/core/java/android/*Manager.java 对应用的接口

2) frameworks/base/core/jni/ 对应用的接口的JNI

3) frameworks/base/services/java/com/android/server/ 后台服务

核心提示:4) frameworks/base/services/jni/ JNI与系统层接口5) hardware/libhardware/include/ 系统层头文件6) hardware/libxxx 系统库支持7) 内核支持4. 应用程序如何使用1) 查看系统提供哪些服务find frameworks/base/cor

4) frameworks/base/services/jni/ JNI与系统层接口

5) hardware/libhardware/include/ 系统层头文件

6) hardware/libxxx 系统库支持

7) 内核支持

4. 应用程序如何使用

1) 查看系统提供哪些服务

find frameworks/base/core/java/android/ -name *Manager.java

此处可以看到调用系统提供服务的入口

2) 一般register listener,事件发生时都收到回调

5. 新建一个service(froyo为例)

1) 接口:接口供应用调用

frameworks/base/core/java/android/app/ContextImpl.java 加服务名与Manager对应

frameworks/base/core/java/android/content/Context.java 加服务名定义

2) Manager:提供服务对应的调用接口

frameworks/base/core/java/android/app/StartXXXXManager.java 实现调用接口

frameworks/base/core/java/android/app/IXXXXManager.aidl 定义调用接口

frameworks/base/Android.mk 加入aidl的编译

3) service:提供后台服务支持

frameworks/base/services/java/com/android/server/XXXXService.java 服务实现

frameworks/base/services/java/com/android/server/SystemServer.java 启动服务



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值