blob: 74a9270b5e9a5a4693458ad7f86d7324882897ae [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
17#define LOG_TAG "CPUGauge"
18
19#include <stdint.h>
20#include <limits.h>
21#include <sys/types.h>
22#include <math.h>
23
24#include <utils/threads.h>
25#include <utils/Errors.h>
26#include <utils/Log.h>
27
28#include <ui/PixelFormat.h>
29#include <ui/Rect.h>
30#include <ui/Region.h>
31#include <ui/DisplayInfo.h>
32#include <ui/ISurfaceComposer.h>
33#include <ui/ISurfaceFlingerClient.h>
34
35#include <pixelflinger/pixelflinger.h>
36
37#include "CPUGauge.h"
38
39namespace android {
40
41CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer,
42 nsecs_t interval,
43 int clock,
44 int refclock)
45 : Thread(false),
46 mInterval(interval), mClock(clock), mRefClock(refclock),
47 mReferenceTime(0),
48 mReferenceWorkingTime(0), mCpuUsage(0),
49 mRefIdleTime(0), mIdleTime(0)
50{
51 mFd = fopen("/proc/stat", "r");
52 setvbuf(mFd, NULL, _IONBF, 0);
53
54 mSession = SurfaceComposerClient::clientForConnection(
55 composer->createConnection()->asBinder());
56}
57
58CPUGauge::~CPUGauge()
59{
60 fclose(mFd);
61}
62
63const sp<SurfaceComposerClient>& CPUGauge::session() const
64{
65 return mSession;
66}
67
68void CPUGauge::onFirstRef()
69{
70 run("CPU Gauge");
71}
72
73status_t CPUGauge::readyToRun()
74{
75 LOGI("Starting CPU gauge...");
76 return NO_ERROR;
77}
78
79bool CPUGauge::threadLoop()
80{
81 DisplayInfo dinfo;
82 session()->getDisplayInfo(0, &dinfo);
83 sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE));
84 session()->openTransaction();
85 s->setLayer(INT_MAX);
86 session()->closeTransaction();
87
88 static const GGLfixed colors[4][4] = {
89 { 0x00000, 0x10000, 0x00000, 0x10000 },
90 { 0x10000, 0x10000, 0x00000, 0x10000 },
91 { 0x10000, 0x00000, 0x00000, 0x10000 },
92 { 0x00000, 0x00000, 0x00000, 0x10000 },
93 };
94
95 GGLContext* gl;
96 gglInit(&gl);
97 gl->activeTexture(gl, 0);
98 gl->disable(gl, GGL_TEXTURE_2D);
99 gl->disable(gl, GGL_BLEND);
100
101 const int w = dinfo.w;
102
103 while(!exitPending())
104 {
105 mLock.lock();
106 const float cpuUsage = this->cpuUsage();
107 const float totalCpuUsage = 1.0f - idle();
108 mLock.unlock();
109
110 Surface::SurfaceInfo info;
111 s->lock(&info);
112 GGLSurface fb;
113 fb.version = sizeof(GGLSurface);
114 fb.width = info.w;
115 fb.height = info.h;
116 fb.stride = info.w;
117 fb.format = info.format;
118 fb.data = (GGLubyte*)info.bits;
119
120 gl->colorBuffer(gl, &fb);
121 gl->color4xv(gl, colors[3]);
122 gl->recti(gl, 0, 0, w, 4);
123 gl->color4xv(gl, colors[2]); // red
124 gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2);
125 gl->color4xv(gl, colors[0]); // green
126 gl->recti(gl, 0, 2, int(cpuUsage*w), 4);
127
128 s->unlockAndPost();
129
130 usleep(ns2us(mInterval));
131 }
132
133 gglUninit(gl);
134 return false;
135}
136
137void CPUGauge::sample()
138{
139 if (mLock.tryLock() == NO_ERROR) {
140 const nsecs_t now = systemTime(mRefClock);
141 const nsecs_t referenceTime = now-mReferenceTime;
142 if (referenceTime >= mInterval) {
143 const float reftime = 1.0f / referenceTime;
144 const nsecs_t nowWorkingTime = systemTime(mClock);
145
146 char buf[256];
147 fgets(buf, 256, mFd);
148 rewind(mFd);
149 char *str = buf+5;
150 char const * const usermode = strsep(&str, " "); (void)usermode;
151 char const * const usernice = strsep(&str, " "); (void)usernice;
152 char const * const systemmode = strsep(&str, " ");(void)systemmode;
153 char const * const idle = strsep(&str, " ");
154 const nsecs_t nowIdleTime = atoi(idle) * 10000000LL;
155 mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime;
156 mRefIdleTime = nowIdleTime;
157
158 const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime;
159 const float newCpuUsage = float(workingTime) * reftime;
160 if (mCpuUsage != newCpuUsage) {
161 mCpuUsage = newCpuUsage;
162 mReferenceWorkingTime = nowWorkingTime;
163 mReferenceTime = now;
164 }
165 }
166 mLock.unlock();
167 }
168}
169
170
171}; // namespace android