diff options
Diffstat (limited to 'libs/surfaceflinger/CPUGauge.cpp')
-rw-r--r-- | libs/surfaceflinger/CPUGauge.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp new file mode 100644 index 0000000..74a9270 --- /dev/null +++ b/libs/surfaceflinger/CPUGauge.cpp @@ -0,0 +1,171 @@ +/* + * 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. + */ + +#define LOG_TAG "CPUGauge" + +#include <stdint.h> +#include <limits.h> +#include <sys/types.h> +#include <math.h> + +#include <utils/threads.h> +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/PixelFormat.h> +#include <ui/Rect.h> +#include <ui/Region.h> +#include <ui/DisplayInfo.h> +#include <ui/ISurfaceComposer.h> +#include <ui/ISurfaceFlingerClient.h> + +#include <pixelflinger/pixelflinger.h> + +#include "CPUGauge.h" + +namespace android { + +CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer, + nsecs_t interval, + int clock, + int refclock) + : Thread(false), + mInterval(interval), mClock(clock), mRefClock(refclock), + mReferenceTime(0), + mReferenceWorkingTime(0), mCpuUsage(0), + mRefIdleTime(0), mIdleTime(0) +{ + mFd = fopen("/proc/stat", "r"); + setvbuf(mFd, NULL, _IONBF, 0); + + mSession = SurfaceComposerClient::clientForConnection( + composer->createConnection()->asBinder()); +} + +CPUGauge::~CPUGauge() +{ + fclose(mFd); +} + +const sp<SurfaceComposerClient>& CPUGauge::session() const +{ + return mSession; +} + +void CPUGauge::onFirstRef() +{ + run("CPU Gauge"); +} + +status_t CPUGauge::readyToRun() +{ + LOGI("Starting CPU gauge..."); + return NO_ERROR; +} + +bool CPUGauge::threadLoop() +{ + DisplayInfo dinfo; + session()->getDisplayInfo(0, &dinfo); + sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE)); + session()->openTransaction(); + s->setLayer(INT_MAX); + session()->closeTransaction(); + + static const GGLfixed colors[4][4] = { + { 0x00000, 0x10000, 0x00000, 0x10000 }, + { 0x10000, 0x10000, 0x00000, 0x10000 }, + { 0x10000, 0x00000, 0x00000, 0x10000 }, + { 0x00000, 0x00000, 0x00000, 0x10000 }, + }; + + GGLContext* gl; + gglInit(&gl); + gl->activeTexture(gl, 0); + gl->disable(gl, GGL_TEXTURE_2D); + gl->disable(gl, GGL_BLEND); + + const int w = dinfo.w; + + while(!exitPending()) + { + mLock.lock(); + const float cpuUsage = this->cpuUsage(); + const float totalCpuUsage = 1.0f - idle(); + mLock.unlock(); + + Surface::SurfaceInfo info; + s->lock(&info); + GGLSurface fb; + fb.version = sizeof(GGLSurface); + fb.width = info.w; + fb.height = info.h; + fb.stride = info.w; + fb.format = info.format; + fb.data = (GGLubyte*)info.bits; + + gl->colorBuffer(gl, &fb); + gl->color4xv(gl, colors[3]); + gl->recti(gl, 0, 0, w, 4); + gl->color4xv(gl, colors[2]); // red + gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2); + gl->color4xv(gl, colors[0]); // green + gl->recti(gl, 0, 2, int(cpuUsage*w), 4); + + s->unlockAndPost(); + + usleep(ns2us(mInterval)); + } + + gglUninit(gl); + return false; +} + +void CPUGauge::sample() +{ + if (mLock.tryLock() == NO_ERROR) { + const nsecs_t now = systemTime(mRefClock); + const nsecs_t referenceTime = now-mReferenceTime; + if (referenceTime >= mInterval) { + const float reftime = 1.0f / referenceTime; + const nsecs_t nowWorkingTime = systemTime(mClock); + + char buf[256]; + fgets(buf, 256, mFd); + rewind(mFd); + char *str = buf+5; + char const * const usermode = strsep(&str, " "); (void)usermode; + char const * const usernice = strsep(&str, " "); (void)usernice; + char const * const systemmode = strsep(&str, " ");(void)systemmode; + char const * const idle = strsep(&str, " "); + const nsecs_t nowIdleTime = atoi(idle) * 10000000LL; + mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime; + mRefIdleTime = nowIdleTime; + + const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime; + const float newCpuUsage = float(workingTime) * reftime; + if (mCpuUsage != newCpuUsage) { + mCpuUsage = newCpuUsage; + mReferenceWorkingTime = nowWorkingTime; + mReferenceTime = now; + } + } + mLock.unlock(); + } +} + + +}; // namespace android |