• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server;
18 
19 import android.app.Service;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.graphics.Canvas;
23 import android.graphics.Paint;
24 import android.graphics.PixelFormat;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.Message;
28 import android.view.Gravity;
29 import android.view.View;
30 import android.view.WindowManager;
31 import android.view.WindowManagerImpl;
32 
33 public class LoadAverageService extends Service {
34     private View mView;
35 
36     private static final class Stats extends ProcessStats {
37         String mLoadText;
38         int mLoadWidth;
39 
40         private final Paint mPaint;
41 
Stats(Paint paint)42         Stats(Paint paint) {
43             super(false);
44             mPaint = paint;
45         }
46 
47         @Override
onLoadChanged(float load1, float load5, float load15)48         public void onLoadChanged(float load1, float load5, float load15) {
49             mLoadText = load1 + " / " + load5 + " / " + load15;
50             mLoadWidth = (int)mPaint.measureText(mLoadText);
51         }
52 
53         @Override
onMeasureProcessName(String name)54         public int onMeasureProcessName(String name) {
55             return (int)mPaint.measureText(name);
56         }
57     }
58 
59     private class LoadView extends View {
60         private Handler mHandler = new Handler() {
61             @Override
62             public void handleMessage(Message msg) {
63                 if (msg.what == 1) {
64                     mStats.update();
65                     updateDisplay();
66                     Message m = obtainMessage(1);
67                     sendMessageDelayed(m, 2000);
68                 }
69             }
70         };
71 
72         private final Stats mStats;
73 
74         private Paint mLoadPaint;
75         private Paint mAddedPaint;
76         private Paint mRemovedPaint;
77         private Paint mShadowPaint;
78         private Paint mShadow2Paint;
79         private Paint mIrqPaint;
80         private Paint mSystemPaint;
81         private Paint mUserPaint;
82         private float mAscent;
83         private int mFH;
84 
85         private int mNeededWidth;
86         private int mNeededHeight;
87 
LoadView(Context c)88         LoadView(Context c) {
89             super(c);
90 
91             setPadding(4, 4, 4, 4);
92             //setBackgroundResource(com.android.internal.R.drawable.load_average_background);
93 
94             mLoadPaint = new Paint();
95             mLoadPaint.setAntiAlias(true);
96             mLoadPaint.setTextSize(10);
97             mLoadPaint.setARGB(255, 255, 255, 255);
98 
99             mAddedPaint = new Paint();
100             mAddedPaint.setAntiAlias(true);
101             mAddedPaint.setTextSize(10);
102             mAddedPaint.setARGB(255, 128, 255, 128);
103 
104             mRemovedPaint = new Paint();
105             mRemovedPaint.setAntiAlias(true);
106             mRemovedPaint.setStrikeThruText(true);
107             mRemovedPaint.setTextSize(10);
108             mRemovedPaint.setARGB(255, 255, 128, 128);
109 
110             mShadowPaint = new Paint();
111             mShadowPaint.setAntiAlias(true);
112             mShadowPaint.setTextSize(10);
113             //mShadowPaint.setFakeBoldText(true);
114             mShadowPaint.setARGB(192, 0, 0, 0);
115             mLoadPaint.setShadowLayer(4, 0, 0, 0xff000000);
116 
117             mShadow2Paint = new Paint();
118             mShadow2Paint.setAntiAlias(true);
119             mShadow2Paint.setTextSize(10);
120             //mShadow2Paint.setFakeBoldText(true);
121             mShadow2Paint.setARGB(192, 0, 0, 0);
122             mLoadPaint.setShadowLayer(2, 0, 0, 0xff000000);
123 
124             mIrqPaint = new Paint();
125             mIrqPaint.setARGB(0x80, 0, 0, 0xff);
126             mIrqPaint.setShadowLayer(2, 0, 0, 0xff000000);
127             mSystemPaint = new Paint();
128             mSystemPaint.setARGB(0x80, 0xff, 0, 0);
129             mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
130             mUserPaint = new Paint();
131             mUserPaint.setARGB(0x80, 0, 0xff, 0);
132             mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
133 
134             mAscent = mLoadPaint.ascent();
135             float descent = mLoadPaint.descent();
136             mFH = (int)(descent - mAscent + .5f);
137 
138             mStats = new Stats(mLoadPaint);
139             mStats.init();
140             updateDisplay();
141         }
142 
143         @Override
onAttachedToWindow()144         protected void onAttachedToWindow() {
145             super.onAttachedToWindow();
146             mHandler.sendEmptyMessage(1);
147         }
148 
149         @Override
onDetachedFromWindow()150         protected void onDetachedFromWindow() {
151             super.onDetachedFromWindow();
152             mHandler.removeMessages(1);
153         }
154 
155         @Override
onMeasure(int widthMeasureSpect, int heightMeasureSpec)156         protected void onMeasure(int widthMeasureSpect, int heightMeasureSpec) {
157             setMeasuredDimension(mNeededWidth, mNeededHeight);
158         }
159 
160         @Override
onDraw(Canvas canvas)161         public void onDraw(Canvas canvas) {
162             super.onDraw(canvas);
163             final int W = getWidth();
164 
165             final Stats stats = mStats;
166             final int userTime = stats.getLastUserTime();
167             final int systemTime = stats.getLastSystemTime();
168             final int iowaitTime = stats.getLastIoWaitTime();
169             final int irqTime = stats.getLastIrqTime();
170             final int softIrqTime = stats.getLastSoftIrqTime();
171             final int idleTime = stats.getLastIdleTime();
172 
173             final int totalTime = userTime+systemTime+iowaitTime+irqTime+softIrqTime+idleTime;
174             if (totalTime == 0) {
175                 return;
176             }
177             int userW = (userTime*W)/totalTime;
178             int systemW = (systemTime*W)/totalTime;
179             int irqW = ((iowaitTime+irqTime+softIrqTime)*W)/totalTime;
180 
181             int x = W - mPaddingRight;
182             int top = mPaddingTop + 2;
183             int bottom = mPaddingTop + mFH - 2;
184 
185             if (irqW > 0) {
186                 canvas.drawRect(x-irqW, top, x, bottom, mIrqPaint);
187                 x -= irqW;
188             }
189             if (systemW > 0) {
190                 canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
191                 x -= systemW;
192             }
193             if (userW > 0) {
194                 canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
195                 x -= userW;
196             }
197 
198             int y = mPaddingTop - (int)mAscent;
199             canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth-1,
200                     y-1, mShadowPaint);
201             canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth-1,
202                     y+1, mShadowPaint);
203             canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth+1,
204                     y-1, mShadow2Paint);
205             canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth+1,
206                     y+1, mShadow2Paint);
207             canvas.drawText(stats.mLoadText, W-mPaddingRight-stats.mLoadWidth,
208                     y, mLoadPaint);
209 
210             int N = stats.countWorkingStats();
211             for (int i=0; i<N; i++) {
212                 Stats.Stats st = stats.getWorkingStats(i);
213                 y += mFH;
214                 top += mFH;
215                 bottom += mFH;
216 
217                 userW = (st.rel_utime*W)/totalTime;
218                 systemW = (st.rel_stime*W)/totalTime;
219                 x = W - mPaddingRight;
220                 if (systemW > 0) {
221                     canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
222                     x -= systemW;
223                 }
224                 if (userW > 0) {
225                     canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
226                     x -= userW;
227                 }
228 
229                 canvas.drawText(st.name, W-mPaddingRight-st.nameWidth-1,
230                         y-1, mShadowPaint);
231                 canvas.drawText(st.name, W-mPaddingRight-st.nameWidth-1,
232                         y+1, mShadowPaint);
233                 canvas.drawText(st.name, W-mPaddingRight-st.nameWidth+1,
234                         y-1, mShadow2Paint);
235                 canvas.drawText(st.name, W-mPaddingRight-st.nameWidth+1,
236                         y+1, mShadow2Paint);
237                 Paint p = mLoadPaint;
238                 if (st.added) p = mAddedPaint;
239                 if (st.removed) p = mRemovedPaint;
240                 canvas.drawText(st.name, W-mPaddingRight-st.nameWidth, y, p);
241             }
242         }
243 
updateDisplay()244         void updateDisplay() {
245             final Stats stats = mStats;
246             final int NW = stats.countWorkingStats();
247 
248             int maxWidth = stats.mLoadWidth;
249             for (int i=0; i<NW; i++) {
250                 Stats.Stats st = stats.getWorkingStats(i);
251                 if (st.nameWidth > maxWidth) {
252                     maxWidth = st.nameWidth;
253                 }
254             }
255 
256             int neededWidth = mPaddingLeft + mPaddingRight + maxWidth;
257             int neededHeight = mPaddingTop + mPaddingBottom + (mFH*(1+NW));
258             if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
259                 mNeededWidth = neededWidth;
260                 mNeededHeight = neededHeight;
261                 requestLayout();
262             } else {
263                 invalidate();
264             }
265         }
266     }
267 
268     @Override
onCreate()269     public void onCreate() {
270         super.onCreate();
271         mView = new LoadView(this);
272         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
273             WindowManager.LayoutParams.WRAP_CONTENT,
274             WindowManager.LayoutParams.WRAP_CONTENT,
275             WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
276             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
277             WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
278             PixelFormat.TRANSLUCENT);
279         params.gravity = Gravity.RIGHT | Gravity.TOP;
280         params.setTitle("Load Average");
281         WindowManagerImpl wm = (WindowManagerImpl)getSystemService(WINDOW_SERVICE);
282         wm.addView(mView, params);
283     }
284 
285     @Override
onDestroy()286     public void onDestroy() {
287         super.onDestroy();
288         ((WindowManagerImpl)getSystemService(WINDOW_SERVICE)).removeView(mView);
289         mView = null;
290     }
291 
292     @Override
onBind(Intent intent)293     public IBinder onBind(Intent intent) {
294         return null;
295     }
296 
297 }
298