CPU Info Overlay Tweaks + Perf. Tweaks

Change-Id: I20c87526f30124d9b059b46dc71d2388cf8d19ce
Signed-off-by: MOVZX <movzx@yahoo.com>
This commit is contained in:
2025-12-29 08:44:53 +07:00
parent 328c575818
commit 8cd8b9c9ef
6 changed files with 218 additions and 59 deletions

View File

@@ -480,6 +480,17 @@ public class Process {
*/
public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;
/**
* Real-time priority used for critical UI tasks
* This gets converted to be lined into the SCHED_RR queue.
* Applications can not normally change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
* @hide
*/
public static final int THREAD_PRIORITY_REALTIME = -21;
/**
* Minimum increment to make a priority more favorable.
*/

View File

@@ -1462,19 +1462,19 @@ static const JNINativeMethod gMethods[] = {
{"native_start", "()V", (void *)android_media_AudioTrack_start},
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
{"native_flush", "!()V", (void *)android_media_AudioTrack_flush},
{"native_setup",
"(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[ILandroid/os/Parcel;"
"JZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
{"native_write_byte", "([BIIIZ)I", (void *)android_media_AudioTrack_writeArray<jbyteArray>},
{"native_write_native_bytes", "(Ljava/nio/ByteBuffer;IIIZ)I",
{"native_write_byte", "!([BIIIZ)I", (void *)android_media_AudioTrack_writeArray<jbyteArray>},
{"native_write_native_bytes", "!(Ljava/nio/ByteBuffer;IIIZ)I",
(void *)android_media_AudioTrack_write_native_bytes},
{"native_write_short", "([SIIIZ)I",
{"native_write_short", "!([SIIIZ)I",
(void *)android_media_AudioTrack_writeArray<jshortArray>},
{"native_write_float", "([FIIIZ)I",
{"native_write_float", "!([FIIIZ)I",
(void *)android_media_AudioTrack_writeArray<jfloatArray>},
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
{"native_get_buffer_size_frames", "()I",

View File

@@ -6,7 +6,7 @@
<resources>
<!-- Charging info current divider, if needed -->
<integer name="config_currentInfoDivider" translatable="false">1000</integer>
<!-- The location of the devices physical tri state switch
0: Left side
1: Right side -->
@@ -17,6 +17,8 @@
<!-- The CPU temperature sensor path, defaults to empty -->
<string name="config_cpuTempSensor" translatable="false">/sys/class/thermal/thermal_zone0/temp</string>
<string name="config_gpuTempSensor" translatable="false">/sys/class/kgsl/kgsl-3d0/temp</string>
<string name="config_batteryTempSensor" translatable="false">/sys/class/power_supply/battery/temp</string>
<!-- The CPU temperature divider, if needed -->
<integer name="config_cpuTempDivider" translatable="false">1</integer>
@@ -25,7 +27,7 @@
<string name="config_displayCpus" translatable="false"></string>
<!-- FPSInfoService FPS node file path -->
<string name="config_fpsInfoSysNode" translatable="false">/sys/class/drm/sde-crtc-0/measured_fps</string>
<string name="config_fpsInfoSysNode" translatable="false">/sys/class/drm/card0-sde-crtc-0/measured_fps</string>
<!-- FPS measure interval in milliseconds, default 1000 -->
<integer name="config_fpsReadInterval">1000</integer>
@@ -35,7 +37,7 @@
<!-- Notification counter -->
<integer name="status_bar_notification_info_maxnum">999</integer>
<!-- Show 5G toggle in internet dialog when available -->
<bool name="config_supportsVONR">true</bool>
</resources>

View File

@@ -5,7 +5,7 @@
* 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
* 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,
@@ -25,12 +25,10 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
@@ -40,14 +38,8 @@ import com.android.systemui.res.R;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.StringBuffer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CPUInfoService extends Service {
private View mView;
@@ -57,17 +49,25 @@ public class CPUInfoService extends Service {
private String[] mCpu = null;
private String[] mCurrFreq = null;
private String[] mCurrGov = null;
private String[] mCurrLoad = null;
private int CPU_TEMP_DIVIDER = 1;
private String CPU_TEMP_SENSOR = "";
private String GPU_TEMP_SENSOR = "";
private String BATTERY_TEMP_SENSOR = "";
private String FPS_SENSOR = "";
private String DISPLAY_CPUS = "";
private boolean mCpuTempAvail;
private boolean mGpuTempAvail;
private boolean mBatTempAvail;
private boolean mFpsAvail;
private static final String NUM_OF_CPUS_PATH = "/sys/devices/system/cpu/present";
private static final String CURRENT_CPU = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
private static final String CPU_ROOT = "/sys/devices/system/cpu/cpu";
private static final String CPU_CUR_TAIL = "/cpufreq/scaling_cur_freq";
private static final String CPU_GOV_TAIL = "/cpufreq/scaling_governor";
private static final String GPU_FREQ_PATH = "/sys/class/kgsl/kgsl-3d0/clock_mhz";
private static final String GPU_LOAD_PATH = "/sys/class/kgsl/kgsl-3d0/gpu_busy_percentage";
private class CPUView extends View {
private Paint mOnlinePaint;
@@ -78,7 +78,12 @@ public class CPUInfoService extends Service {
private int mNeededWidth;
private int mNeededHeight;
private String mFps;
private String mCpuTemp;
private String mGpuTemp;
private String mBatTemp;
private String mGpuFreq;
private String mGpuLoad;
private boolean mDataAvail;
@@ -91,18 +96,25 @@ public class CPUInfoService extends Service {
String msgData = (String) msg.obj;
try {
String[] parts=msgData.split(";");
mCpuTemp=parts[0];
mFps = parts[0];
mCpuTemp = parts[1];
mGpuTemp = parts[2];
mBatTemp = parts[3];
mGpuFreq = parts[4];
mGpuLoad = parts[5];
String[] cpuParts=parts[1].split("\\|");
String[] cpuParts=parts[6].split("\\|");
for(int i=0; i<cpuParts.length; i++){
String cpuInfo=cpuParts[i];
String cpuInfoParts[]=cpuInfo.split(":");
if(cpuInfoParts.length==3){
if(cpuInfoParts.length==4){
mCurrFreq[i]=cpuInfoParts[1];
mCurrGov[i]=cpuInfoParts[2];
mCurrLoad[i]=cpuInfoParts[3];
} else {
mCurrFreq[i]="0";
mCurrGov[i]="";
mCurrLoad[i]="0%";
}
}
mDataAvail = true;
@@ -121,7 +133,7 @@ public class CPUInfoService extends Service {
setPadding(paddingPx, paddingPx, paddingPx, paddingPx);
setBackgroundColor(Color.argb(0x60, 0, 0, 0));
final int textSize = Math.round(12 * density);
final int textSize = Math.round(10 * density);
Typeface typeface = Typeface.create("monospace", Typeface.NORMAL);
@@ -148,11 +160,6 @@ public class CPUInfoService extends Service {
updateDisplay();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -165,19 +172,28 @@ public class CPUInfoService extends Service {
resolveSize(mNeededHeight, heightMeasureSpec));
}
private String getCPUInfoString(int i) {
String cpu=mCpu[i];
String freq=mCurrFreq[i];
String gov=mCurrGov[i];
return "cpu" + cpu + ": " + gov + " " + String.format("%8s", toMHz(freq));
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
private String getCpuTemp(String cpuTemp) {
if (CPU_TEMP_DIVIDER > 1) {
return String.format("%s",
Integer.parseInt(cpuTemp) / CPU_TEMP_DIVIDER);
} else {
return cpuTemp;
private String getCPUInfoString(int i) {
return "Core " + mCpu[i] + ": " + String.format("%3s", mCurrLoad[i]) + " " + mCurrGov[i] + " " + String.format("%8s", toMHz(mCurrFreq[i]));
}
private String getTemp(String rawTemp) {
try {
float temp = Float.parseFloat(rawTemp);
if (temp > 10000) {
return String.format("%.2f", temp / 1000.0f);
}
if (CPU_TEMP_DIVIDER > 1) {
return String.format("%.2f", temp / CPU_TEMP_DIVIDER);
} else {
return rawTemp;
}
} catch (NumberFormatException e) {
return "0";
}
}
@@ -188,33 +204,50 @@ public class CPUInfoService extends Service {
return;
}
final int W = mNeededWidth;
final int RIGHT = getWidth()-1;
int x = RIGHT - mPaddingRight;
int top = mPaddingTop + 2;
int bottom = mPaddingTop + mFH - 2;
int y = mPaddingTop - (int)mAscent;
if(mFpsAvail) {
canvas.drawText("FPS: " + mFps,
RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
y += mFH;
}
if(!mCpuTemp.equals("0")) {
canvas.drawText("Temp: " + getCpuTemp(mCpuTemp) + "°C",
canvas.drawText("CPU: " + getTemp(mCpuTemp) + " °C",
RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
y += mFH;
}
if(!mGpuTemp.equals("0")) {
canvas.drawText("GPU: " + getTemp(mGpuTemp) + " °C",
RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
y += mFH;
}
if(!mBatTemp.equals("0")) {
canvas.drawText("BAT: " + getTemp(mBatTemp) + " °C",
RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
y += mFH;
}
for(int i=0; i<mCurrFreq.length; i++){
String s=getCPUInfoString(i);
String freq=mCurrFreq[i];
if(!freq.equals("0")){
if(!mCurrFreq[i].equals("0")){
canvas.drawText(s, RIGHT-mPaddingRight-mMaxWidth,
y-1, mOnlinePaint);
} else {
canvas.drawText("cpu" + mCpu[i] + ": offline", RIGHT-mPaddingRight-mMaxWidth,
canvas.drawText("Core " + mCpu[i] + ": offline", RIGHT-mPaddingRight-mMaxWidth,
y-1, mOfflinePaint);
}
y += mFH;
}
if(!mGpuFreq.equals("0") || !mGpuLoad.equals("0%")) {
String gpuStats = "GPU: " + mGpuLoad + " " + mGpuFreq + " MHz";
canvas.drawText(gpuStats, RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
y += mFH;
}
}
void updateDisplay() {
@@ -223,8 +256,25 @@ public class CPUInfoService extends Service {
}
final int NW = mNumCpus;
int maxW = 0;
if(mFpsAvail) maxW = Math.max(maxW, (int)mOnlinePaint.measureText("FPS: " + mFps));
if(!mCpuTemp.equals("0")) maxW = Math.max(maxW, (int)mOnlinePaint.measureText("CPU: " + getTemp(mCpuTemp) + " °C"));
if(!mGpuTemp.equals("0")) maxW = Math.max(maxW, (int)mOnlinePaint.measureText("GPU: " + getTemp(mGpuTemp) + " °C"));
if(!mBatTemp.equals("0")) maxW = Math.max(maxW, (int)mOnlinePaint.measureText("BAT: " + getTemp(mBatTemp) + " °C"));
for(int i=0; i<mCurrFreq.length; i++){
String s = getCPUInfoString(i);
maxW = Math.max(maxW, (int)mOnlinePaint.measureText(s));
}
String gpuStats = "GPU: " + mGpuLoad + " " + mGpuFreq + " MHz";
maxW = Math.max(maxW, (int)mOnlinePaint.measureText(gpuStats));
mMaxWidth = maxW;
int neededWidth = mPaddingLeft + mPaddingRight + mMaxWidth;
int neededHeight = mPaddingTop + mPaddingBottom + (mFH*((mCpuTempAvail?1:0)+NW));
int numTempLines = (mFpsAvail?1:0) + (mCpuTempAvail?1:0) + (mGpuTempAvail?1:0) + (mBatTempAvail?1:0);
int neededHeight = mPaddingTop + mPaddingBottom + (mFH * (numTempLines + NW + 1));
if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
mNeededWidth = neededWidth;
mNeededHeight = neededHeight;
@@ -235,7 +285,11 @@ public class CPUInfoService extends Service {
}
private String toMHz(String mhzString) {
return new StringBuilder().append(Integer.valueOf(mhzString) / 1000).append(" MHz").toString();
try {
return new StringBuilder().append(Integer.valueOf(mhzString) / 1000).append(" MHz").toString();
} catch (Exception e) {
return "0 MHz";
}
}
public Handler getHandler(){
@@ -246,10 +300,14 @@ public class CPUInfoService extends Service {
protected class CurCPUThread extends Thread {
private boolean mInterrupt = false;
private Handler mHandler;
private long[] mLastTotal = null;
private long[] mLastIdle = null;
public CurCPUThread(Handler handler, int numCpus){
mHandler=handler;
mNumCpus = numCpus;
mLastTotal = new long[numCpus];
mLastIdle = new long[numCpus];
}
public void interrupt() {
@@ -262,9 +320,47 @@ public class CPUInfoService extends Service {
while (!mInterrupt) {
sleep(500);
StringBuffer sb=new StringBuffer();
String fpsVal = "0.0";
if (mFpsAvail) {
String rawFps = CPUInfoService.readOneLine(FPS_SENSOR);
if (rawFps != null) {
String trimmed = rawFps.trim();
if (trimmed.startsWith("fps:")) {
String[] parts = trimmed.split("\\s+");
if (parts.length >= 2) {
try {
float fpsFloat = Float.parseFloat(parts[1]);
fpsVal = String.format("%.1f", fpsFloat);
} catch (NumberFormatException e) {
// ignore
}
}
}
}
}
sb.append(fpsVal).append(";");
String cpuTemp = CPUInfoService.readOneLine(CPU_TEMP_SENSOR);
sb.append(cpuTemp == null ? "0" : cpuTemp);
sb.append(";");
sb.append(cpuTemp == null ? "0" : cpuTemp).append(";");
String gpuTemp = CPUInfoService.readOneLine(GPU_TEMP_SENSOR);
sb.append(gpuTemp == null ? "0" : gpuTemp).append(";");
String batTemp = CPUInfoService.readOneLine(BATTERY_TEMP_SENSOR);
sb.append(batTemp == null ? "0" : batTemp).append(";");
String gpuFreq = CPUInfoService.readOneLine(GPU_FREQ_PATH);
sb.append(gpuFreq == null ? "0" : gpuFreq).append(";");
String gpuLoadStr = "0%";
String gpuBusy = CPUInfoService.readOneLine(GPU_LOAD_PATH);
if (gpuBusy != null) {
gpuLoadStr = gpuBusy.replaceAll("[^0-9]", "") + "%";
}
sb.append(gpuLoadStr).append(";");
String[] cpuLoads = getCpuLoad();
for(int i=0; i<mNumCpus; i++) {
final String currCpu = mCpu[i];
@@ -272,13 +368,15 @@ public class CPUInfoService extends Service {
String currFreq = CPUInfoService.readOneLine(freqFile);
final String govFile=CPU_ROOT + mCpu[i] + CPU_GOV_TAIL;
String currGov = CPUInfoService.readOneLine(govFile);
String currLoad = (i < cpuLoads.length) ? cpuLoads[i] : "0%";
if(currFreq==null){
currFreq="0";
currGov="";
currLoad="0%";
}
sb.append(currCpu+":"+currFreq+":"+currGov+"|");
sb.append(currCpu+":"+currFreq+":"+currGov+":"+currLoad+"|");
}
sb.deleteCharAt(sb.length()-1);
mHandler.sendMessage(mHandler.obtainMessage(1, sb.toString()));
@@ -287,6 +385,45 @@ public class CPUInfoService extends Service {
return;
}
}
private String[] getCpuLoad() {
String[] results = new String[mNumCpus];
try {
BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
String line;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("cpu")) continue;
if (line.startsWith("cpu ")) continue;
String[] tokens = line.split("\\s+");
String cpuName = tokens[0];
int cpuId = Integer.parseInt(cpuName.substring(3));
if (cpuId >= mNumCpus) continue;
long idle = Long.parseLong(tokens[4]);
long total = 0;
for (int k=1; k<tokens.length; k++) {
total += Long.parseLong(tokens[k]);
}
long diffIdle = idle - mLastIdle[cpuId];
long diffTotal = total - mLastTotal[cpuId];
int load = 0;
if (diffTotal > 0) {
load = (int)((diffTotal - diffIdle) * 100 / diffTotal);
}
mLastIdle[cpuId] = idle;
mLastTotal[cpuId] = total;
results[cpuId] = load + "%";
}
reader.close();
} catch (Exception e) {
for(int j=0; j<mNumCpus; j++) results[j] = "0%";
}
return results;
}
};
@Override
@@ -294,14 +431,23 @@ public class CPUInfoService extends Service {
super.onCreate();
CPU_TEMP_DIVIDER = getResources().getInteger(R.integer.config_cpuTempDivider);
CPU_TEMP_SENSOR = getResources().getString(R.string.config_cpuTempSensor);
DISPLAY_CPUS = getResources().getString(R.string.config_displayCpus);
FPS_SENSOR = getResources().getString(R.string.config_fpsInfoSysNode);
BATTERY_TEMP_SENSOR = getResources().getString(R.string.config_batteryTempSensor);
GPU_TEMP_SENSOR = getResources().getString(R.string.config_gpuTempSensor);
CPU_TEMP_SENSOR = getResources().getString(R.string.config_cpuTempSensor);
mNumCpus = getCpus(DISPLAY_CPUS);
mCurrFreq = new String[mNumCpus];
mCurrGov = new String[mNumCpus];
mCurrLoad = new String[mNumCpus];
mCpuTempAvail = readOneLine(CPU_TEMP_SENSOR) != null;
mGpuTempAvail = readOneLine(GPU_TEMP_SENSOR) != null;
mBatTempAvail = readOneLine(BATTERY_TEMP_SENSOR) != null;
File fpsFile = new File(FPS_SENSOR);
mFpsAvail = fpsFile.exists() && fpsFile.canRead();
mView = new CPUView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
@@ -366,7 +512,7 @@ public class CPUInfoService extends Service {
for (int i = 0; i < numOfCpu; i++) {
try {
int cpu = Integer.parseInt(cpuList[i]);
Integer.parseInt(cpuList[i]);
mCpu[i] = cpuList[i];
} catch (NumberFormatException ex) {
// derped overlay

View File

@@ -25,9 +25,9 @@ import android.os.Trace;
import com.android.internal.annotations.VisibleForTesting;
/**
* Shared singleton thread for showing UI. This is a foreground thread, and in
* Shared singleton thread for showing UI. This is a realtime thread, and in
* additional should not have operations that can take more than a few ms scheduled
* on it to avoid UI jank.
* on it to avoid impacting the runtime of other non-realtime processes.
*/
public final class UiThread extends ServiceThread {
private static final long SLOW_DISPATCH_THRESHOLD_MS = 100;
@@ -36,7 +36,7 @@ public final class UiThread extends ServiceThread {
private static Handler sHandler;
private UiThread() {
super("android.ui", Process.THREAD_PRIORITY_URGENT_DISPLAY, false /*allowIo*/);
super("android.ui", android.os.Process.THREAD_PRIORITY_REALTIME, false /*allowIo*/);
}
@Override

View File

@@ -254,7 +254,7 @@ static jint nativeCloseHal(JNIEnv* env, jobject clazz) {
// TODO: clean up void methods
static const JNINativeMethod g_methods[] = {
{ "nativeAuthenticate", "(JI)I", (void*)nativeAuthenticate },
{ "nativeAuthenticate", "!(JI)I", (void*)nativeAuthenticate },
{ "nativeStopAuthentication", "()I", (void*)nativeStopAuthentication },
{ "nativeEnroll", "([BII)I", (void*)nativeEnroll },
{ "nativeSetActiveGroup", "(I[B)I", (void*)nativeSetActiveGroup },