android4.4系统LoadAverageService服务分析
在前一段时间写的《android系统cpu资源相关查询》感觉还比较实用,上次没有对LoadAverageService做深入一点的分析,今天我们接着来看看。
首先看看大智慧低调的LoadAverageService的源代码小心翼翼的潜伏在android\frameworks\base\packages\SystemUI\src\com\android\systemui下面, 文件很小,也就12KB样子。放在systemui里面还是有好处的,被其他程序替代的可能性低一些,一般设备很少有人去替换systemui的,launcher被换的倒是大有人在,比较隐蔽,因为不常用也不用太显眼;
/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/edsam49原创,转载请注明出处,谢谢!
/*****************************************************************************************************/
LoadAverageService有两个重要的class,一个是CpuTracker,负责运行状态数据收集的,另外一个就是LoadView,从名字上也能看出是为了显示的,要显示成啥样,就在这里面了。
private static final class CpuTracker extends ProcessCpuTracker { }
private class LoadView extends View {}
我们从上面这中关系中可以看出ProcessCpuTracker是至关重要的,那么下面我们来看看它都提供了些什么。首先还是先了解一下linux特性,在系统运行时在/proc伪文件系统中会生成对应任务的PID相关运行信息,这个PID也是内核负责分配的,我们进入看看是个什么样子,如下图:
我们再进一级,比如PID是2121的进程,我们看看他的运行stat记录,如下图:
有了上面说的这些素材,ProcessCpuTracker就有活干了,我们先来看一下其中一个重要的接口getCpuTimeForPid(int pid),代码如下:
/** * Returns the total time (in clock ticks, or 1/100 sec) spent executing in * both user and system code. */ public long getCpuTimeForPid(int pid) { final String statFile = "/proc/" + pid + "/stat"; final long[] statsData = mSinglePidStatsData; if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT, null, statsData, null)) { long time = statsData[PROCESS_STAT_UTIME] + statsData[PROCESS_STAT_STIME]; return time; } return 0; }
我们不难看出他是去分析了/proc下面的每个PID对应的stat文件,关于stat的格式说明请参看一下http://www.net527.cn/a/caozuoxitong/Linux/2012/0823/24385.html这篇文章,写得很清楚了。从stat文件得到的信息真不少啊!要算出cpu占有率这些东西,肯定是要有计算时长的,一般默认也是用5秒钟做一个加权计算,可以看看这个任务两次采样时占的系统时间的差异,再根据cpu的总时间来算出百分比,算CPU总的使用率的话是分析/proc/stat文件即可;值得一提的就是/proc/loadavg,他里面算的是任务数,跟我们平时看的占有率不一样,我们还是更习惯看占有率。其实看到这里,我相信大多数码友都知道大概怎么来的了吧!
要实时不断的显示刷新出来,无法是有个任务隔一段时间去采样一下,计算出来结果update上去,再通过LoadView来显示。LoadView值得一提的就是它在任何应用界面上都可以显示,它是用的系统层,而不是activities层,始终高于activities。我们看看是怎么实现的,核心代码如下:
public void onCreate() { super.onCreate(); mView = new LoadView(this); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); params.gravity = Gravity.END | Gravity.TOP; params.setTitle("Load Average"); WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE); wm.addView(mView, params); }
用的是TYPE_SECURE_SYSTEM_OVERLAY这个参数来指定的,这个参数的介绍参考如下:
/** * Window type: secure system overlay windows, which need to be displayed * on top of everything else. These windows must not take input * focus, or they will interfere with the keyguard. * * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the * system itself is allowed to create these overlays. Applications cannot * obtain permission to create secure system overlays. * * In multiuser systems shows only on the owning user's window. * @hide */ public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
其实,通过以上的一些简单分析,梳理一下思路,我们就可以了解到它从下到上是怎么运作起来的。它山之石可以攻玉!为我所用,灵活使用,事半功倍!