Move LoadAverageService to the SystemUI apk.
Change-Id: I442e264802d1e35cd7d27bae121ae75f932595b6
diff --git a/packages/SystemUI/src/com/android/systemui/BootReceiver.java b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
new file mode 100644
index 0000000..de005aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BootReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Performs a number of miscellaneous, non-system-critical actions
+ * after the system has finished booting.
+ */
+public class BootReceiver extends BroadcastReceiver {
+ private static final String TAG = "SystemUIBootReceiver";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ try {
+ // Start the load average overlay, if activated
+ ContentResolver res = context.getContentResolver();
+ if (Settings.System.getInt(res, Settings.System.SHOW_PROCESSES, 0) != 0) {
+ Intent loadavg = new Intent(context, com.android.systemui.LoadAverageService.class);
+ context.startService(loadavg);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Can't start load average service", e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/LoadAverageService.java b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
new file mode 100644
index 0000000..67dc3cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.internal.os.ProcessStats;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+
+public class LoadAverageService extends Service {
+ private View mView;
+
+ private static final class Stats extends ProcessStats {
+ String mLoadText;
+ int mLoadWidth;
+
+ private final Paint mPaint;
+
+ Stats(Paint paint) {
+ super(false);
+ mPaint = paint;
+ }
+
+ @Override
+ public void onLoadChanged(float load1, float load5, float load15) {
+ mLoadText = load1 + " / " + load5 + " / " + load15;
+ mLoadWidth = (int)mPaint.measureText(mLoadText);
+ }
+
+ @Override
+ public int onMeasureProcessName(String name) {
+ return (int)mPaint.measureText(name);
+ }
+ }
+
+ private class LoadView extends View {
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == 1) {
+ mStats.update();
+ updateDisplay();
+ Message m = obtainMessage(1);
+ sendMessageDelayed(m, 2000);
+ }
+ }
+ };
+
+ private final Stats mStats;
+
+ private Paint mLoadPaint;
+ private Paint mAddedPaint;
+ private Paint mRemovedPaint;
+ private Paint mShadowPaint;
+ private Paint mShadow2Paint;
+ private Paint mIrqPaint;
+ private Paint mSystemPaint;
+ private Paint mUserPaint;
+ private float mAscent;
+ private int mFH;
+
+ private int mNeededWidth;
+ private int mNeededHeight;
+
+ LoadView(Context c) {
+ super(c);
+
+ setPadding(4, 4, 4, 4);
+ //setBackgroundResource(com.android.internal.R.drawable.load_average_background);
+
+ // Need to scale text size by density... but we won't do it
+ // linearly, because with higher dps it is nice to squeeze the
+ // text a bit to fit more of it. And with lower dps, trying to
+ // go much smaller will result in unreadable text.
+ int textSize = 10;
+ float density = c.getResources().getDisplayMetrics().density;
+ if (density < 1) {
+ textSize = 9;
+ } else {
+ textSize = (int)(10*density);
+ if (textSize < 10) {
+ textSize = 10;
+ }
+ }
+ mLoadPaint = new Paint();
+ mLoadPaint.setAntiAlias(true);
+ mLoadPaint.setTextSize(textSize);
+ mLoadPaint.setARGB(255, 255, 255, 255);
+
+ mAddedPaint = new Paint();
+ mAddedPaint.setAntiAlias(true);
+ mAddedPaint.setTextSize(textSize);
+ mAddedPaint.setARGB(255, 128, 255, 128);
+
+ mRemovedPaint = new Paint();
+ mRemovedPaint.setAntiAlias(true);
+ mRemovedPaint.setStrikeThruText(true);
+ mRemovedPaint.setTextSize(textSize);
+ mRemovedPaint.setARGB(255, 255, 128, 128);
+
+ mShadowPaint = new Paint();
+ mShadowPaint.setAntiAlias(true);
+ mShadowPaint.setTextSize(textSize);
+ //mShadowPaint.setFakeBoldText(true);
+ mShadowPaint.setARGB(192, 0, 0, 0);
+ mLoadPaint.setShadowLayer(4, 0, 0, 0xff000000);
+
+ mShadow2Paint = new Paint();
+ mShadow2Paint.setAntiAlias(true);
+ mShadow2Paint.setTextSize(textSize);
+ //mShadow2Paint.setFakeBoldText(true);
+ mShadow2Paint.setARGB(192, 0, 0, 0);
+ mLoadPaint.setShadowLayer(2, 0, 0, 0xff000000);
+
+ mIrqPaint = new Paint();
+ mIrqPaint.setARGB(0x80, 0, 0, 0xff);
+ mIrqPaint.setShadowLayer(2, 0, 0, 0xff000000);
+ mSystemPaint = new Paint();
+ mSystemPaint.setARGB(0x80, 0xff, 0, 0);
+ mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
+ mUserPaint = new Paint();
+ mUserPaint.setARGB(0x80, 0, 0xff, 0);
+ mSystemPaint.setShadowLayer(2, 0, 0, 0xff000000);
+
+ mAscent = mLoadPaint.ascent();
+ float descent = mLoadPaint.descent();
+ mFH = (int)(descent - mAscent + .5f);
+
+ mStats = new Stats(mLoadPaint);
+ mStats.init();
+ updateDisplay();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mHandler.sendEmptyMessage(1);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mHandler.removeMessages(1);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
+ resolveSize(mNeededHeight, heightMeasureSpec));
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ final int W = mNeededWidth;
+ final int RIGHT = getWidth()-1;
+
+ final Stats stats = mStats;
+ final int userTime = stats.getLastUserTime();
+ final int systemTime = stats.getLastSystemTime();
+ final int iowaitTime = stats.getLastIoWaitTime();
+ final int irqTime = stats.getLastIrqTime();
+ final int softIrqTime = stats.getLastSoftIrqTime();
+ final int idleTime = stats.getLastIdleTime();
+
+ final int totalTime = userTime+systemTime+iowaitTime+irqTime+softIrqTime+idleTime;
+ if (totalTime == 0) {
+ return;
+ }
+ int userW = (userTime*W)/totalTime;
+ int systemW = (systemTime*W)/totalTime;
+ int irqW = ((iowaitTime+irqTime+softIrqTime)*W)/totalTime;
+
+ int x = RIGHT - mPaddingRight;
+ int top = mPaddingTop + 2;
+ int bottom = mPaddingTop + mFH - 2;
+
+ if (irqW > 0) {
+ canvas.drawRect(x-irqW, top, x, bottom, mIrqPaint);
+ x -= irqW;
+ }
+ if (systemW > 0) {
+ canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
+ x -= systemW;
+ }
+ if (userW > 0) {
+ canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
+ x -= userW;
+ }
+
+ int y = mPaddingTop - (int)mAscent;
+ canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
+ y-1, mShadowPaint);
+ canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth-1,
+ y+1, mShadowPaint);
+ canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
+ y-1, mShadow2Paint);
+ canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth+1,
+ y+1, mShadow2Paint);
+ canvas.drawText(stats.mLoadText, RIGHT-mPaddingRight-stats.mLoadWidth,
+ y, mLoadPaint);
+
+ int N = stats.countWorkingStats();
+ for (int i=0; i<N; i++) {
+ Stats.Stats st = stats.getWorkingStats(i);
+ y += mFH;
+ top += mFH;
+ bottom += mFH;
+
+ userW = (st.rel_utime*W)/totalTime;
+ systemW = (st.rel_stime*W)/totalTime;
+ x = RIGHT - mPaddingRight;
+ if (systemW > 0) {
+ canvas.drawRect(x-systemW, top, x, bottom, mSystemPaint);
+ x -= systemW;
+ }
+ if (userW > 0) {
+ canvas.drawRect(x-userW, top, x, bottom, mUserPaint);
+ x -= userW;
+ }
+
+ canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
+ y-1, mShadowPaint);
+ canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth-1,
+ y+1, mShadowPaint);
+ canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
+ y-1, mShadow2Paint);
+ canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth+1,
+ y+1, mShadow2Paint);
+ Paint p = mLoadPaint;
+ if (st.added) p = mAddedPaint;
+ if (st.removed) p = mRemovedPaint;
+ canvas.drawText(st.name, RIGHT-mPaddingRight-st.nameWidth, y, p);
+ }
+ }
+
+ void updateDisplay() {
+ final Stats stats = mStats;
+ final int NW = stats.countWorkingStats();
+
+ int maxWidth = stats.mLoadWidth;
+ for (int i=0; i<NW; i++) {
+ Stats.Stats st = stats.getWorkingStats(i);
+ if (st.nameWidth > maxWidth) {
+ maxWidth = st.nameWidth;
+ }
+ }
+
+ int neededWidth = mPaddingLeft + mPaddingRight + maxWidth;
+ int neededHeight = mPaddingTop + mPaddingBottom + (mFH*(1+NW));
+ if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
+ mNeededWidth = neededWidth;
+ mNeededHeight = neededHeight;
+ requestLayout();
+ } else {
+ invalidate();
+ }
+ }
+ }
+
+ @Override
+ 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.RIGHT | Gravity.TOP;
+ params.setTitle("Load Average");
+ WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
+ wm.addView(mView, params);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
+ mView = null;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+}