native: frame-rate setting, idle frame rate and battery power telemetry
- MtFrameRate setting (30 / 60 default / display max) as app.Get/SetFrameRateMode, with a "画面帧率" row injected into the system option dialog (mt_framerate); saved in the SDL pref path. - FrameRatePolicy in the live loop: 30 fps after 15 s without input (not while auto hunting), display switched to 60 Hz unless the highest mode, ADPF setPreferPowerEfficiency, vsync pacing when the display already runs at the target. --fps-mode / --idle-fps / --idle-after; --fps-cap / --refresh-rate still pin a test run. - Perf log: battery current/voltage/power, plugged, fps_mode, idle columns; perf_summary groups power by mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c2cc093ed0
commit
82503315c6
@@ -37,19 +37,20 @@ public class MainActivity extends SDLActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
applyImmersiveMode();
|
||||
chosenRefreshRate = applyRefreshRate(requestedRefreshRate(launchArgs()));
|
||||
// --refresh-rate N pins the display mode for a test run; otherwise native_render switches it with
|
||||
// the frame-rate setting (setDisplayRefreshRate).
|
||||
final float pinned = requestedRefreshRate(launchArgs());
|
||||
if (pinned > 0)
|
||||
applyRefreshRate(pinned);
|
||||
}
|
||||
|
||||
// The display rate picked in onCreate (0: left to the system); handed to native as --refresh-rate.
|
||||
private int chosenRefreshRate = 0;
|
||||
|
||||
private String launchArgs() {
|
||||
Intent intent = getIntent();
|
||||
String args = intent != null ? intent.getStringExtra("args") : null;
|
||||
return args == null || args.trim().isEmpty() ? DEFAULT_ARGS : args;
|
||||
}
|
||||
|
||||
// --refresh-rate N (0 = system default); absent = the display's highest rate.
|
||||
// --refresh-rate N (0 = system default); -1 when absent.
|
||||
private static float requestedRefreshRate(String args) {
|
||||
final String[] tokens = args.trim().split("\\s+");
|
||||
for (int i = 0; i + 1 < tokens.length; ++i) {
|
||||
@@ -141,6 +142,52 @@ public class MainActivity extends SDLActivity {
|
||||
return tenths / 10f;
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): the display mode whose refresh rate is closest to `hz`
|
||||
// (the highest one when hz < 0), for the frame-rate setting. The panel then need not scan out at 120 Hz
|
||||
// for a 60 fps game.
|
||||
public void setDisplayRefreshRate(float hz) {
|
||||
runOnUiThread(() -> applyRefreshRate(hz));
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): the highest refresh rate of the current resolution.
|
||||
public float maxRefreshRate() {
|
||||
final Display display = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ? getDisplay()
|
||||
: getWindowManager().getDefaultDisplay();
|
||||
if (display == null)
|
||||
return -1f;
|
||||
float best = display.getRefreshRate();
|
||||
final Display.Mode current = display.getMode();
|
||||
for (Display.Mode mode : display.getSupportedModes())
|
||||
if (mode.getPhysicalWidth() == current.getPhysicalWidth() &&
|
||||
mode.getPhysicalHeight() == current.getPhysicalHeight())
|
||||
best = Math.max(best, mode.getRefreshRate());
|
||||
return best;
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): BATTERY_PROPERTY_CURRENT_NOW as reported -- uA per the
|
||||
// docs, mA on some vendors; the sign convention varies too (android_perf::battery_power sorts both
|
||||
// out). 0 if unknown.
|
||||
public float batteryCurrentRaw() {
|
||||
final BatteryManager manager = (BatteryManager) getSystemService(BATTERY_SERVICE);
|
||||
if (manager == null)
|
||||
return 0f;
|
||||
final int raw = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
|
||||
return raw == Integer.MIN_VALUE ? 0f : raw;
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): battery voltage in mV, -1 if unknown.
|
||||
public float batteryVoltage() {
|
||||
final Intent battery = registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
return battery != null ? battery.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1) : -1f;
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): 1 while a charger is connected (the current then no
|
||||
// longer measures the game's draw), 0 otherwise.
|
||||
public float batteryPlugged() {
|
||||
final Intent battery = registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
return battery != null && battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0 ? 1f : 0f;
|
||||
}
|
||||
|
||||
// Called from native code (android_perf.h): the rate the display runs at now.
|
||||
public float currentRefreshRate() {
|
||||
final Display display = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ? getDisplay()
|
||||
@@ -204,8 +251,6 @@ public class MainActivity extends SDLActivity {
|
||||
// Test phase: FPS readout in the top-left corner. Drop this line for release builds.
|
||||
if (!args.contains("--show-fps"))
|
||||
args = args.trim() + " --show-fps";
|
||||
if (!args.contains("--refresh-rate") && chosenRefreshRate > 0)
|
||||
args = args.trim() + " --refresh-rate " + chosenRefreshRate;
|
||||
return args.trim().split("\\s+");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user