Home | History | Annotate | Download | only in server
      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 
     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_SECURE_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 }
    298