1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 05:17:39 +03:00
This commit is contained in:
Anton Afanasyeu
2026-05-18 12:17:05 +02:00
parent 5bc968e419
commit 9b1afec032
12 changed files with 123 additions and 39 deletions

View File

@@ -18,6 +18,8 @@ public final class AppPreferences {
private static final String KEY_THEME = "theme_mode";
private static final String KEY_LOCALE = "locale_mode";
private static final String KEY_PLAY_INCOMING_AUDIO = "play_incoming_audio";
private static final String KEY_DEV_RECEIVER_DEBUG_OVERLAY = "dev_receiver_debug_overlay";
private static final String KEY_DEV_GRAB_SESSION_STATS = "dev_grab_session_stats";
private static final String PREFIX_SENDER = "sender_";
private static final String PREFIX_RECEIVER = "receiver_";
@@ -92,6 +94,24 @@ public final class AppPreferences {
prefs(context).edit().putBoolean(KEY_PLAY_INCOMING_AUDIO, play).apply();
}
/** Developer: metrics HTML overlay on receiver video (default on). */
public static boolean isShowReceiverDebugOverlay(Context context) {
return prefs(context).getBoolean(KEY_DEV_RECEIVER_DEBUG_OVERLAY, true);
}
public static void setShowReceiverDebugOverlay(Context context, boolean show) {
prefs(context).edit().putBoolean(KEY_DEV_RECEIVER_DEBUG_OVERLAY, show).apply();
}
/** Developer: write anonymous session_*.json files (default on). */
public static boolean isGrabSessionStats(Context context) {
return prefs(context).getBoolean(KEY_DEV_GRAB_SESSION_STATS, true);
}
public static void setGrabSessionStats(Context context, boolean grab) {
prefs(context).edit().putBoolean(KEY_DEV_GRAB_SESSION_STATS, grab).apply();
}
public static CastSettings loadSenderDefaults(Context context) {
CastSettings s = new CastSettings();
applyStoredCastSettings(context, PREFIX_SENDER, s);

View File

@@ -56,9 +56,6 @@ public final class CastConfig {
/** Max UDP payload chunk (fits typical WiFi MTU with header). */
public static final int UDP_CHUNK_SIZE = 1200;
/** Show diagnostics overlay on receiver playback (debug). */
public static final boolean SHOW_CAST_DIAGNOSTICS = true;
/** Max retained session stat JSON files (room for one new file on next session). */
public static final int SESSION_STATS_MAX_FILES = 20;

View File

@@ -1,15 +1,34 @@
package com.foxx.androidcast;
import android.content.Context;
import android.os.Bundle;
import android.widget.CheckBox;
import androidx.appcompat.app.AppCompatActivity;
/** Hidden developer settings (opened via version label easter egg). */
public class DeveloperSettingsActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CastLocaleHelper.attach(newBase));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
CastThemeHelper.applyTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_developer_settings);
setTitle(R.string.developer_settings_title);
CheckBox debugOverlay = findViewById(R.id.check_receiver_debug_overlay);
CheckBox sessionStats = findViewById(R.id.check_grab_session_stats);
debugOverlay.setChecked(AppPreferences.isShowReceiverDebugOverlay(this));
sessionStats.setChecked(AppPreferences.isGrabSessionStats(this));
debugOverlay.setOnCheckedChangeListener((buttonView, isChecked) ->
AppPreferences.setShowReceiverDebugOverlay(this, isChecked));
sessionStats.setOnCheckedChangeListener((buttonView, isChecked) ->
AppPreferences.setGrabSessionStats(this, isChecked));
}
}

View File

@@ -17,7 +17,9 @@ public class MainActivity extends DrawerHostActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SessionStatsStore.pruneOnAppStart(this);
if (AppPreferences.isGrabSessionStats(this)) {
SessionStatsStore.pruneOnAppStart(this);
}
com.foxx.androidcast.network.CastTransportFactory.init(this);
PermissionHelper.request(this);

View File

@@ -159,7 +159,9 @@ public class ReceiverCastService extends Service {
public void onCreate() {
super.onCreate();
CastNotifications.createChannels(this);
SessionStatsStore.pruneOnAppStart(this);
if (AppPreferences.isGrabSessionStats(this)) {
SessionStatsStore.pruneOnAppStart(this);
}
videoDecodeThread = new HandlerThread("VideoDecode");
videoDecodeThread.start();
videoDecodeHandler = new Handler(videoDecodeThread.getLooper());
@@ -375,12 +377,14 @@ public class ReceiverCastService extends Service {
private void onSenderConnected(String senderName, CastSettings remoteSettings, String videoMime) {
phase = Phase.CONNECTED;
castEnded = false;
if (sessionStatsRecorder == null) {
sessionStatsRecorder = new SessionStatsRecorder("receiver", settings.getTransport());
sessionStatsRecorder.setClientCount(1);
if (AppPreferences.isGrabSessionStats(this)) {
if (sessionStatsRecorder == null) {
sessionStatsRecorder = new SessionStatsRecorder("receiver", settings.getTransport());
sessionStatsRecorder.setClientCount(1);
}
sessionStatsRecorder.mergeSettings(remoteSettings);
sessionStatsRecorder.setCodecs(videoMime, "AAC");
}
sessionStatsRecorder.mergeSettings(remoteSettings);
sessionStatsRecorder.setCodecs(videoMime, "AAC");
negotiatedVideoMime = videoMime;
remoteCastSettings = remoteSettings;
streamIdle = false;

View File

@@ -23,7 +23,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.foxx.androidcast.AppPreferences;
import com.foxx.androidcast.CastConfig;
import com.foxx.androidcast.CastSettings;
import com.foxx.androidcast.DrawerHostActivity;
import com.foxx.androidcast.CastThemeHelper;
@@ -296,7 +295,7 @@ public class ReceiverPlaybackActivity extends DrawerHostActivity {
if (diagnosticsText == null) {
return;
}
boolean show = CastConfig.SHOW_CAST_DIAGNOSTICS && streamRendering;
boolean show = AppPreferences.isShowReceiverDebugOverlay(this) && streamRendering;
diagnosticsText.setVisibility(show ? View.VISIBLE : View.GONE);
if (show) {
diagnosticsText.bringToFront();
@@ -304,7 +303,8 @@ public class ReceiverPlaybackActivity extends DrawerHostActivity {
}
private void refreshDiagnostics() {
if (diagnosticsText == null || !CastConfig.SHOW_CAST_DIAGNOSTICS || !bound || receiverService == null) {
if (diagnosticsText == null || !AppPreferences.isShowReceiverDebugOverlay(this)
|| !bound || receiverService == null) {
return;
}
if (!streamRendering) {

View File

@@ -153,7 +153,9 @@ public class ScreenCastService extends Service implements
@Override
public void onCreate() {
super.onCreate();
SessionStatsStore.pruneOnAppStart(this);
if (AppPreferences.isGrabSessionStats(this)) {
SessionStatsStore.pruneOnAppStart(this);
}
CastNotifications.createChannels(this);
com.foxx.androidcast.network.CastTransportFactory.init(this);
projectionThread = new HandlerThread("CastProjection");
@@ -263,10 +265,12 @@ public class ScreenCastService extends Service implements
CastActiveState.setSenderCasting(true);
CastTrayNotifier.refresh(this);
activeSettings = settings;
sessionStatsRecorder = new SessionStatsRecorder("sender", settings.getTransport());
sessionStatsRecorder.mergeSettings(settings);
sessionStatsRecorder.setClientCount(peers.size());
sessionStatsRecorder.setCodecs(settings.getNegotiatedVideoMime(), "AAC");
if (AppPreferences.isGrabSessionStats(this)) {
sessionStatsRecorder = new SessionStatsRecorder("sender", settings.getTransport());
sessionStatsRecorder.mergeSettings(settings);
sessionStatsRecorder.setClientCount(peers.size());
sessionStatsRecorder.setCodecs(settings.getNegotiatedVideoMime(), "AAC");
}
final int projResultCode = resultCode;
final Intent projData = data != null ? new Intent(data) : null;
if (calibration) {

View File

@@ -2,6 +2,7 @@ package com.foxx.androidcast.stats;
import android.content.Context;
import com.foxx.androidcast.AppPreferences;
import com.foxx.androidcast.CastSettings;
import com.foxx.androidcast.network.control.NetworkStatsSnapshot;
import com.foxx.androidcast.network.transport.TransportLossStats;
@@ -139,6 +140,9 @@ public final class SessionStatsRecorder {
}
public void finish(Context context) {
if (!AppPreferences.isGrabSessionStats(context)) {
return;
}
long endedMs = System.currentTimeMillis();
try {
JSONObject root = new JSONObject();

View File

@@ -1,22 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp">
android:fillViewport="true">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/developer_settings_title"
android:textSize="20sp"
android:textStyle="bold" />
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/developer_settings_stub" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/developer_settings_title"
android:textSize="20sp"
android:textStyle="bold" />
<CheckBox
android:id="@+id/check_receiver_debug_overlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:checked="true"
android:text="@string/dev_show_receiver_debug_overlay" />
<CheckBox
android:id="@+id/check_grab_session_stats"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/dev_grab_session_stats" />
</LinearLayout>
</ScrollView>

View File

@@ -186,7 +186,8 @@
<string name="licenses_title">Лицензии</string>
<string name="licenses_load_error">Не могу найти факл лицензий</string>
<string name="developer_settings_title">Для разработчиков</string>
<string name="developer_settings_stub">Additional developer options will appear here.</string>
<string name="dev_show_receiver_debug_overlay">Показывать отладочный оверлей на приёмнике</string>
<string name="dev_grab_session_stats">Сохранять анонимную статистику сессий</string>
<string name="label_audio_codec">Кодек для звука</string>
<string name="codec_libvpx_vp8">libvpx (VP8)</string>
<string name="codec_libvpx_vp9">libvpx (VP9)</string>

View File

@@ -186,7 +186,8 @@
<string name="licenses_title">Licenses</string>
<string name="licenses_load_error">Could not load license text.</string>
<string name="developer_settings_title">Developer settings</string>
<string name="developer_settings_stub">Additional developer options will appear here.</string>
<string name="dev_show_receiver_debug_overlay">Show debug overlay on receiver</string>
<string name="dev_grab_session_stats">Grab anonymous session stats</string>
<string name="label_audio_codec">Voice codec</string>
<string name="codec_libvpx_vp8">libvpx (VP8)</string>
<string name="codec_libvpx_vp9">libvpx (VP9)</string>