mirror of
git://f0xx.org/android_cast
synced 2026-07-29 07:39:15 +03:00
snap
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -56,9 +56,6 @@ public final class CastConfig {
|
||||
/** Max UDP payload chunk (fits typical Wi‑Fi 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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
#!/bin/sh
|
||||
adb shell run-as com.foxx.androidcast ls files/session_stats/
|
||||
adb shell run-as com.foxx.androidcast cat files/session_stats/session_*.json
|
||||
#!/bin/bash
|
||||
DEVICES_LIST="$(adb devices -l)"
|
||||
echo "${DEVICES_LIST}"
|
||||
|
||||
|
||||
filter_out() {
|
||||
local -n dev_string=${1}
|
||||
[[ ${dev_string} =~ List* ]] && dev_string=""
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "${DEVICES_LIST}" | while IFS= read -r DEV; do
|
||||
SERIAL="$(echo "${DEV}" | awk '{print $1}')"
|
||||
filter_out SERIAL
|
||||
[ -z "${SERIAL}" ] && continue
|
||||
# echo "Device: ${DEV}"
|
||||
# echo "Serial: ${SERIAL}"
|
||||
adb -s "${SERIAL}" shell run-as com.foxx.androidcast ls files/session_stats/
|
||||
adb -s "${SERIAL}" shell run-as com.foxx.androidcast cat files/session_stats/session_*.json
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user