blob: 2b45ad1b6cd9d68ab0a6692dda583841becdc95d [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
Dianne Hackborn45ce8642011-07-14 16:10:16 -070017package com.android.systemui;
18
19import com.android.internal.os.ProcessStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
21import android.app.Service;
22import android.content.Context;
23import android.content.Intent;
24import android.graphics.Canvas;
25import android.graphics.Paint;
26import android.graphics.PixelFormat;
27import android.os.Handler;
28import android.os.IBinder;
29import android.os.Message;
30import android.view.Gravity;
31import android.view.View;
32import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34public class LoadAverageService extends Service {
35 private View mView;
36
37 private static final class Stats extends ProcessStats {
38 String mLoadText;
39 int mLoadWidth;
40
41 private final Paint mPaint;
42
43 Stats(Paint paint) {
44 super(false);
45 mPaint = paint;
46 }
47
48 @Override
49 public void onLoadChanged(float load1, float load5, float load15) {
50 mLoadText = load1 + " / " + load5 + " / " + load15;
51 mLoadWidth = (int)mPaint.measureText(mLoadText);
52 }
53
54 @Override
55 public int onMeasureProcessName(String name) {
56 return (int)mPaint.measureText(name);
57 }
58 }
59
60 private class LoadView extends View {
61 private Handler mHandler = new Handler() {
62 @Override
63 public void handleMessage(Message msg) {
64 if (msg.what == 1) {
65 mStats.update();
66 updateDisplay();
67 Message m = obtainMessage(1);
68 sendMessageDelayed(m, 2000);
69 }
70 }
71 };
72
73 private final Stats mStats;
74
75 private Paint mLoadPaint;
76 private Paint mAddedPaint;
77 private Paint mRemovedPaint;
78 private Paint mShadowPaint;
79 private Paint mShadow2Paint;
80 private Paint mIrqPaint;
81 private Paint mSystemPaint;
82 private Paint mUserPaint;
83 private float mAscent;
84 private int mFH;
85
86 private int mNeededWidth;
87 private int mNeededHeight;
88
89 LoadView(Context c) {
90 super(c);
91
92 setPadding(4, 4, 4, 4);
93 //setBackgroundResource(com.android.internal.R.drawable.load_average_background);
94
Dianne Hackbornce86ba82011-07-13 19:33:41 -070095 // Need to scale text size by density... but we won't do it
96 // linearly, because with higher dps it is nice to squeeze the
97 // text a bit to fit more of it. And with lower dps, trying to
98 // go much smaller will result in unreadable text.
99 int textSize = 10;
100 float density = c.getResources().getDisplayMetrics().density;
101 if (density < 1) {
102 textSize = 9;
103 } else {
104 textSize = (int)(10*density);
105 if (textSize < 10) {
106 textSize = 10;
107 }
108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 mLoadPaint = new Paint();
110 mLoadPaint.setAntiAlias(true);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700111 mLoadPaint.setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 mLoadPaint.setARGB(255, 255, 255, 255);
113
114 mAddedPaint = new Paint();
115 mAddedPaint.setAntiAlias(true);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700116 mAddedPaint.setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 mAddedPaint.setARGB(255, 128, 255, 128);
118
119 mRemovedPaint = new Paint();
120 mRemovedPaint.setAntiAlias(true);
121 mRemovedPaint.setStrikeThruText(true);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700122 mRemovedPaint.setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 mRemovedPaint.setARGB(255, 255, 128, 128);
124
125 mShadowPaint = new Paint();
126 mShadowPaint.setAntiAlias(true);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700127 mShadowPaint.setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 //mShadowPaint.setFakeBoldText(true);
129 mShadowPaint.setARGB(192, 0, 0, 0);
130 mLoadPaint.setShadowLayer(4, 0, 0, 0xff000000);
131
132 mShadow2Paint = new Paint();
133 mShadow2Paint.setAntiAlias(true);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700134 mShadow2Paint.setTextSize(textSize);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 //mShadow2Paint.setFakeBoldText(true);
136 mShadow2Paint.setARGB(192, 0, 0, 0);
137 mLoadPaint.setShadowLayer(2, 0, 0, 0xff000000);
138
139 mIrqPaint = new Paint();
140 mIrqPaint.setARGB(0x80, 0, 0, 0xff);
141 mIrqPaint.setShadowLayer(2, 0, 0, 0xff000000);
142 mSystemPaint = new Paint();
143 mSystemPaint.setARGB(0x80, 0xff, 0, 0);
144 mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
145 mUserPaint = new Paint();
146 mUserPaint.setARGB(0x80, 0, 0xff, 0);
147 mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
148
149 mAscent = mLoadPaint.ascent();
150 float descent = mLoadPaint.descent();
151 mFH = (int)(descent - mAscent + .5f);
152
153 mStats = new Stats(mLoadPaint);
154 mStats.init();
155 updateDisplay();
156 }
157
158 @Override
159 protected void onAttachedToWindow() {
160 super.onAttachedToWindow();
161 mHandler.sendEmptyMessage(1);
162 }
163
164 @Override
165 protected void onDetachedFromWindow() {
166 super.onDetachedFromWindow();
167 mHandler.removeMessages(1);
168 }
169
170 @Override
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700171 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
172 setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
173 resolveSize(mNeededHeight, heightMeasureSpec));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 }
175
176 @Override
177 public void onDraw(Canvas canvas) {
178 super.onDraw(canvas);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700179 final int W = mNeededWidth;
180 final int RIGHT = getWidth()-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181
182 final Stats stats = mStats;
183 final int userTime = stats.getLastUserTime();
184 final int systemTime = stats.getLastSystemTime();
185 final int iowaitTime = stats.getLastIoWaitTime();
186 final int irqTime = stats.getLastIrqTime();
187 final int softIrqTime = stats.getLastSoftIrqTime();
188 final int idleTime = stats.getLastIdleTime();
189
190 final int totalTime = userTime+systemTime+iowaitTime+irqTime+softIrqTime+idleTime;
191 if (totalTime == 0) {
192 return;
193 }
194 int userW = (userTime*W)/totalTime;
195 int systemW = (systemTime*W)/totalTime;
196 int irqW = ((iowaitTime+irqTime+softIrqTime)*W)/totalTime;
197
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700198 int x = RIGHT - mPaddingRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 int top = mPaddingTop + 2;
200 int bottom = mPaddingTop + mFH - 2;
201
202 if (irqW > 0) {
203 canvas.drawRect(x-irqW, top, x, bottom, mIrqPaint);
204 x -= irqW;
205 }
206 if (systemW > 0) {
207 canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
208 x -= systemW;
209 }
210 if (userW > 0) {
211 canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
212 x -= userW;
213 }
214
215 int y = mPaddingTop - (int)mAscent;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700216 canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 y-1, mShadowPaint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700218 canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 y+1, mShadowPaint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700220 canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 y-1, mShadow2Paint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700222 canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 y+1, mShadow2Paint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700224 canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 y, mLoadPaint);
226
227 int N = stats.countWorkingStats();
228 for (int i=0; i<N; i++) {
229 Stats.Stats st = stats.getWorkingStats(i);
230 y += mFH;
231 top += mFH;
232 bottom += mFH;
233
234 userW = (st.rel_utime*W)/totalTime;
235 systemW = (st.rel_stime*W)/totalTime;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700236 x = RIGHT - mPaddingRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 if (systemW > 0) {
238 canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
239 x -= systemW;
240 }
241 if (userW > 0) {
242 canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
243 x -= userW;
244 }
245
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700246 canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 y-1, mShadowPaint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700248 canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 y+1, mShadowPaint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700250 canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 y-1, mShadow2Paint);
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700252 canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 y+1, mShadow2Paint);
254 Paint p = mLoadPaint;
255 if (st.added) p = mAddedPaint;
256 if (st.removed) p = mRemovedPaint;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700257 canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth, y, p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
259 }
260
261 void updateDisplay() {
262 final Stats stats = mStats;
263 final int NW = stats.countWorkingStats();
264
265 int maxWidth = stats.mLoadWidth;
266 for (int i=0; i<NW; i++) {
267 Stats.Stats st = stats.getWorkingStats(i);
268 if (st.nameWidth > maxWidth) {
269 maxWidth = st.nameWidth;
270 }
271 }
272
273 int neededWidth = mPaddingLeft + mPaddingRight + maxWidth;
274 int neededHeight = mPaddingTop + mPaddingBottom + (mFH*(1+NW));
275 if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
276 mNeededWidth = neededWidth;
277 mNeededHeight = neededHeight;
278 requestLayout();
279 } else {
280 invalidate();
281 }
282 }
283 }
284
285 @Override
286 public void onCreate() {
287 super.onCreate();
288 mView = new LoadView(this);
289 WindowManager.LayoutParams params = new WindowManager.LayoutParams(
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700290 WindowManager.LayoutParams.MATCH_PARENT,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 WindowManager.LayoutParams.WRAP_CONTENT,
Jeff Brown3b2b3542010-10-15 00:54:27 -0700292 WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
294 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
295 PixelFormat.TRANSLUCENT);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700296 params.gravity = Gravity.END | Gravity.TOP;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 params.setTitle("Load Average");
Dianne Hackborn2ed99462011-07-01 19:02:52 -0700298 WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 wm.addView(mView, params);
300 }
301
302 @Override
303 public void onDestroy() {
304 super.onDestroy();
Dianne Hackborn2ed99462011-07-01 19:02:52 -0700305 ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 mView = null;
307 }
308
309 @Override
310 public IBinder onBind(Intent intent) {
311 return null;
312 }
313
314}