blob: 0d86429aaa5ccf6ecf311dfb3af0f3ccbf5f8d29 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package com.android.server;
18
19import android.app.Service;
20import android.content.Context;
21import android.content.Intent;
22import android.graphics.Canvas;
23import android.graphics.Paint;
24import android.graphics.PixelFormat;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.Message;
28import android.view.Gravity;
29import android.view.View;
30import android.view.WindowManager;
31import android.view.WindowManagerImpl;
32
33public 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
42 Stats(Paint paint) {
43 super(false);
44 mPaint = paint;
45 }
46
47 @Override
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
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
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
144 protected void onAttachedToWindow() {
145 super.onAttachedToWindow();
146 mHandler.sendEmptyMessage(1);
147 }
148
149 @Override
150 protected void onDetachedFromWindow() {
151 super.onDetachedFromWindow();
152 mHandler.removeMessages(1);
153 }
154
155 @Override
156 protected void onMeasure(int widthMeasureSpect, int heightMeasureSpec) {
157 setMeasuredDimension(mNeededWidth, mNeededHeight);
158 }
159
160 @Override
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
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
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
286 public void onDestroy() {
287 super.onDestroy();
288 ((WindowManagerImpl)getSystemService(WINDOW_SERVICE)).removeView(mView);
289 mView = null;
290 }
291
292 @Override
293 public IBinder onBind(Intent intent) {
294 return null;
295 }
296
297}