From 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8 Mon Sep 17 00:00:00 2001 From: Anton Afanasyeu Date: Wed, 20 May 2026 15:17:13 +0200 Subject: [PATCH] contrib header changes --- .githooks/pre-commit | 4 + .gitignore | 4 + HEADER.txt | 50 ++ .../androidcast/ICastReceiverService.aidl | 10 + .../foxx/androidcast/ICastSenderService.aidl | 10 + .../foxx/androidcast/ICastStatusCallback.aidl | 10 + .../androidcast/AndroidCastApplication.java | 10 + .../com/foxx/androidcast/AppPreferences.java | 10 + .../com/foxx/androidcast/CastActiveState.java | 10 + .../foxx/androidcast/CastActivityTracker.java | 10 + .../java/com/foxx/androidcast/CastConfig.java | 10 + .../foxx/androidcast/CastLocaleHelper.java | 10 + .../foxx/androidcast/CastNotifications.java | 10 + .../com/foxx/androidcast/CastResolution.java | 10 + .../com/foxx/androidcast/CastSettings.java | 10 + .../androidcast/CastSettingsActivity.java | 10 + .../foxx/androidcast/CastSettingsBinder.java | 10 + .../androidcast/CastSettingsFragment.java | 10 + .../com/foxx/androidcast/CastThemeHelper.java | 10 + .../foxx/androidcast/CastTrayNotifier.java | 10 + .../foxx/androidcast/CastTuningEngine.java | 10 + .../DeveloperSettingsActivity.java | 10 + .../java/com/foxx/androidcast/DeviceInfo.java | 10 + .../foxx/androidcast/DrawerHostActivity.java | 9 + .../com/foxx/androidcast/IntentExtras.java | 10 + .../foxx/androidcast/LicensesActivity.java | 10 + .../com/foxx/androidcast/MainActivity.java | 10 + .../foxx/androidcast/PermissionHelper.java | 10 + .../androidcast/PictureInPictureHelper.java | 10 + .../java/com/foxx/androidcast/PinAuth.java | 10 + .../foxx/androidcast/PlatformCastSupport.java | 10 + .../java/com/foxx/androidcast/SettingsUi.java | 10 + .../androidcast/TrayForegroundService.java | 10 + .../androidcast/TrayNotificationReceiver.java | 10 + .../com/foxx/androidcast/VersionInfo.java | 10 + .../com/foxx/androidcast/VersionUtils.java | 10 + .../androidcast/crash/CrashNativeBridge.java | 10 + .../androidcast/crash/CrashReportBuilder.java | 10 + .../androidcast/crash/CrashReportStore.java | 10 + .../foxx/androidcast/crash/CrashReporter.java | 10 + .../foxx/androidcast/crash/CrashSettings.java | 10 + .../androidcast/crash/CrashSettingsStore.java | 10 + .../androidcast/crash/CrashUploadClient.java | 10 + .../crash/CrashWatcherService.java | 10 + .../diagnostics/CastDiagnosticsFormatter.java | 10 + .../diagnostics/CastDiagnosticsLabels.java | 10 + .../diagnostics/CastDiagnosticsScorer.java | 10 + .../diagnostics/CastMtuSampler.java | 10 + .../diagnostics/CpuLoadSampler.java | 10 + .../discovery/DiscoveryManager.java | 10 + .../discovery/DiscoverySelfFilter.java | 9 + .../discovery/NsdCastDiscovery.java | 10 + .../discovery/PinnedReceiversStore.java | 10 + .../discovery/ReceiverCompatibility.java | 10 + .../foxx/androidcast/media/AacAdtsHelper.java | 10 + .../androidcast/media/CodecNegotiator.java | 10 + .../media/CodecPriorityCatalog.java | 10 + .../androidcast/media/CodecPriorityId.java | 10 + .../com/foxx/androidcast/media/CodecTier.java | 10 + .../androidcast/media/EncodedStreamProbe.java | 10 + .../foxx/androidcast/media/H264Bitstream.java | 10 + .../foxx/androidcast/media/H264SpsParser.java | 10 + .../androidcast/media/PcmLevelAnalyzer.java | 10 + .../com/foxx/androidcast/media/RgbToNv21.java | 10 + .../foxx/androidcast/media/RgbToYuv420.java | 10 + .../media/StreamDimensionResolver.java | 10 + .../media/codec/AudioCodecBackend.java | 10 + .../media/codec/AudioCodecFactory.java | 10 + .../media/codec/AudioEncoderSink.java | 10 + .../media/codec/CodecSessionRegistry.java | 10 + .../codec/LibvpxCapableVideoDecoder.java | 10 + .../media/codec/LibvpxVideoEncoderSink.java | 10 + .../codec/PassthroughAudioEncoderSink.java | 9 + .../media/codec/PassthroughCodecPolicy.java | 10 + .../codec/PassthroughVideoEncoderSink.java | 9 + .../media/codec/VideoCodecBackend.java | 10 + .../media/codec/VideoCodecFactory.java | 10 + .../media/codec/VideoDecoderFactory.java | 10 + .../media/codec/VideoDecoderSink.java | 10 + .../media/codec/VideoEncoderSink.java | 10 + .../media/codec/jni/NativeCodecBridge.java | 10 + .../media/codec/jni/VpxEncodedFrame.java | 10 + .../androidcast/network/CastCodecFlags.java | 10 + .../network/CastFramingContext.java | 10 + .../androidcast/network/CastPacketFramer.java | 10 + .../androidcast/network/CastProtoHeader.java | 10 + .../androidcast/network/CastProtocol.java | 10 + .../foxx/androidcast/network/CastSession.java | 10 + .../androidcast/network/CastSessionGate.java | 10 + .../androidcast/network/CastTransport.java | 10 + .../network/CastTransportFactory.java | 10 + .../androidcast/network/TcpCastTransport.java | 10 + .../androidcast/network/UdpCastTransport.java | 10 + .../network/control/NetworkControlAdvice.java | 10 + .../network/control/NetworkControlPlane.java | 10 + .../control/NetworkFeedbackManager.java | 10 + .../network/control/NetworkStatsSnapshot.java | 10 + .../PassThroughNetworkControlPlane.java | 10 + .../network/quic/CronetEngineProvider.java | 10 + .../network/quic/QuicCronetCastTransport.java | 10 + .../transport/CombinedProtectionEngine.java | 10 + .../transport/FecProtectionEngine.java | 10 + .../transport/NackProtectionEngine.java | 10 + .../network/transport/NackRateLimiter.java | 10 + .../ProtectionNegotiationPrompts.java | 10 + .../network/transport/RetransmitCache.java | 10 + .../transport/StreamProtectionCapability.java | 10 + .../transport/StreamProtectionCompat.java | 10 + .../transport/StreamProtectionEngine.java | 10 + .../transport/StreamProtectionFactory.java | 10 + .../transport/StreamProtectionMode.java | 10 + .../StreamProtectionNegotiation.java | 10 + .../transport/StreamProtectionNegotiator.java | 10 + .../transport/StreamProtectionScopes.java | 10 + .../network/transport/TransportLossStats.java | 10 + .../transport/TransportLossStatsBridge.java | 10 + .../transport/TransportStatsProvider.java | 10 + .../transport/fec/FecEncodedGroup.java | 10 + .../transport/fec/FecShardReassembly.java | 10 + .../network/transport/fec/FecShardWire.java | 10 + .../network/transport/fec/GaloisField.java | 9 + .../transport/fec/ProtectionEnvelope.java | 10 + .../network/transport/fec/ReedSolomonFec.java | 10 + .../network/webrtc/WebRtcCastTransport.java | 10 + .../network/webrtc/WebRtcPeerAdapter.java | 10 + .../webrtc/WebRtcTransportFactory.java | 10 + .../foxx/androidcast/ota/OtaApkInstaller.java | 24 +- .../androidcast/ota/OtaBundleInstaller.java | 184 +++++++ .../androidcast/ota/OtaChannelPointer.java | 10 + .../foxx/androidcast/ota/OtaJsonFetch.java | 9 + .../com/foxx/androidcast/ota/OtaManifest.java | 56 +- .../foxx/androidcast/ota/OtaMqttFetch.java | 9 + .../androidcast/ota/OtaRuntimeSettings.java | 10 + .../androidcast/ota/OtaSettingsStore.java | 9 + .../foxx/androidcast/ota/OtaSignBundle.java | 10 + .../androidcast/ota/OtaUpdateChecker.java | 47 +- .../androidcast/ota/OtaUpdateCoordinator.java | 14 +- .../androidcast/ota/OtaUpdateService.java | 15 +- .../com/foxx/androidcast/ota/OtaVersion.java | 10 + .../androidcast/receiver/AudioDecoder.java | 10 + .../receiver/LibvpxVideoDecoder.java | 10 + .../receiver/PlaybackViewState.java | 10 + .../receiver/ReceiverActivity.java | 10 + .../receiver/ReceiverCastService.java | 10 + .../receiver/ReceiverPlaybackActivity.java | 10 + .../androidcast/receiver/ReceiverPrefs.java | 10 + .../androidcast/receiver/ReceiverSession.java | 10 + .../androidcast/receiver/StreamMetrics.java | 10 + .../androidcast/receiver/VideoDecoder.java | 10 + .../foxx/androidcast/sender/AudioCapture.java | 10 + .../foxx/androidcast/sender/AudioEncoder.java | 10 + .../androidcast/sender/CastFanoutPump.java | 10 + .../sender/CastReceiverTarget.java | 10 + .../foxx/androidcast/sender/CastSendPump.java | 10 + .../foxx/androidcast/sender/CodecCatalog.java | 10 + .../androidcast/sender/DeviceListAdapter.java | 10 + .../androidcast/sender/EncoderKeepalive.java | 10 + .../sender/MultiCastCoordinator.java | 10 + .../androidcast/sender/ScreenCastService.java | 10 + .../androidcast/sender/SenderActivity.java | 10 + .../sender/SenderAudioMetrics.java | 10 + .../sender/SenderCapturePreview.java | 10 + .../sender/SenderPreviewService.java | 10 + .../sender/SenderScreenPreview.java | 10 + .../sender/SenderStreamMetrics.java | 10 + .../foxx/androidcast/sender/VideoEncoder.java | 10 + .../calibration/CalibrationCastDriver.java | 10 + .../calibration/CalibrationEglRenderer.java | 9 + .../CalibrationSourceDimensions.java | 10 + .../calibration/TvCalibrationGenerator.java | 10 + .../sender/camera/CameraCastCapture.java | 10 + .../androidcast/settings/AppSettingsJson.java | 10 + .../stats/SessionEventJournal.java | 9 + .../stats/SessionStatsContext.java | 10 + .../stats/SessionStatsEventMapper.java | 10 + .../stats/SessionStatsRecorder.java | 10 + .../androidcast/stats/SessionStatsStore.java | 10 + .../androidcast/stats/ui/ChartTickHelper.java | 9 + .../stats/ui/SessionBarChartView.java | 10 + .../stats/ui/SessionLineChartView.java | 10 + .../androidcast/stats/ui/SessionRecord.java | 10 + .../ui/SessionStatsAnalyzerActivity.java | 10 + .../stats/ui/SessionStatsListAdapter.java | 10 + .../stats/ui/SessionStatsParser.java | 10 + .../ui/AspectRatioFrameLayout.java | 10 + .../ui/PlaybackTextureTransform.java | 10 + .../androidcast/ui/SettingsEnumSpinner.java | 10 + .../ui/SettingsScoredArrayAdapter.java | 10 + .../ui/SettingsSpinnerDropdownStyle.java | 10 + .../ui/SettingsStringArrayAdapter.java | 10 + .../foxx/androidcast/ui/ZoomPanContainer.java | 10 + .../util/CastBackgroundExecutor.java | 10 + .../foxx/androidcast/CastResolutionTest.java | 10 + .../diagnostics/CastMtuSamplerTest.java | 10 + .../discovery/DiscoverySelfFilterTest.java | 10 + .../media/EncodedStreamProbeTest.java | 10 + .../media/H264BitstreamHevcTest.java | 10 + .../foxx/androidcast/media/RgbToNv21Test.java | 10 + .../androidcast/media/RgbToYuv420Test.java | 10 + .../network/CastProtoHeaderTest.java | 10 + .../network/CastSessionGateTest.java | 10 + .../UdpCastTransportBackwardCompatTest.java | 10 + .../network/UdpCastTransportFecTest.java | 10 + .../FecProtectionEngineShardTest.java | 10 + .../transport/NackRateLimiterTest.java | 10 + .../transport/StreamProtectionCompatTest.java | 10 + .../StreamProtectionFactoryTest.java | 10 + .../StreamProtectionNegotiatorTest.java | 10 + .../transport/fec/FecShardReassemblyTest.java | 10 + .../transport/fec/FecShardWireTest.java | 10 + .../transport/fec/ReedSolomonFecTest.java | 10 + .../androidcast/ota/OtaApkInstallerTest.java | 10 + .../ota/OtaBundleInstallerTest.java | 64 +++ .../foxx/androidcast/ota/OtaManifestTest.java | 28 +- .../foxx/androidcast/ota/OtaVersionTest.java | 10 + .../CalibrationSourceDimensionsTest.java | 10 + .../stats/SessionStatsEventMapperTest.java | 10 + .../stats/SessionStatsStoreTest.java | 10 + .../ui/PlaybackTextureTransformTest.java | 10 + .../foxx/androidcast/studio/ChartTicks.java | 9 + .../androidcast/studio/SessionChartPane.java | 10 + .../androidcast/studio/SessionDocument.java | 10 + .../androidcast/studio/SessionStudioApp.java | 10 + docs/OTA.md | 29 +- .../backend/config/config.example.php | 11 + .../crash_reporter/backend/config/config.php | 11 + .../backend/public/api/upload.php | 11 + .../crash_reporter/backend/public/index.php | 11 + examples/crash_reporter/backend/src/Auth.php | 11 + .../crash_reporter/backend/src/Database.php | 11 + .../backend/src/ReportRepository.php | 11 + .../crash_reporter/backend/src/bootstrap.php | 11 + .../crash_reporter/backend/views/layout.php | 11 + .../crash_reporter/backend/views/login.php | 11 + .../backend/views/report_detail.php | 11 + examples/ota/mqtt-topics.md | 3 + .../android_cast_00.01.00.00_manifest.json | 3 + .../android_cast_00.01.01.01_manifest.json | 3 + ndk/jni/androidcast_codecs.c | 11 + ndk/jni/crash_hook.c | 11 + ndk/jni/libvpx_bridge.c | 11 + ndk/jni/opus_bridge.c | 11 + ndk/jni/speex_bridge.c | 11 + scripts/apply-project-headers.py | 86 +++ scripts/generate-ota-v0.sh | 44 +- scripts/header-pre-commit.py | 86 +++ scripts/header_lib.py | 499 ++++++++++++++++++ scripts/install-git-hooks.sh | 9 + scripts/test_header_lib.py | 83 +++ 249 files changed, 3597 insertions(+), 22 deletions(-) create mode 100755 .githooks/pre-commit create mode 100644 HEADER.txt create mode 100644 app/src/main/java/com/foxx/androidcast/ota/OtaBundleInstaller.java create mode 100644 app/src/test/java/com/foxx/androidcast/ota/OtaBundleInstallerTest.java create mode 100755 scripts/apply-project-headers.py create mode 100755 scripts/header-pre-commit.py create mode 100755 scripts/header_lib.py create mode 100755 scripts/install-git-hooks.sh create mode 100755 scripts/test_header_lib.py diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..a2278bd --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +ROOT="$(git rev-parse --show-toplevel)" +exec python3 "$ROOT/scripts/header-pre-commit.py" diff --git a/.gitignore b/.gitignore index 2b375f9..a10ca08 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,8 @@ bin lib include .log_capture +log_capture debug-capture +__pycache__ +desktop/session-studio/build/ +build/ diff --git a/HEADER.txt b/HEADER.txt new file mode 100644 index 0000000..4ddf7f2 --- /dev/null +++ b/HEADER.txt @@ -0,0 +1,50 @@ +Project source file header template +=================================== + +Place this block at the top of each source unit (after optional shebang / " # used as-is + export HEADER_CONTRIBUTOR_EMAIL="you@mail" # optional override + +Placeholders +------------ +__PACKAGE_NAME_PLACEHOLDER__ + Java/AIDL: `package com.example.foo;` + C/C++/PHP: `/* package path/relative/to/repo/file.ext */` + +__FILENAME_PLACEHOLDER__ Short filename only (e.g. MainActivity.java) + +__DATE_PLACEHOLDER__ First commit time (human-readable + timezone) + +__UPDATE_DATE_PLACEHOLDER__ Last change time; pre-commit refreshes on staged edits + +__CONTRIBUTOR__ `Name ` when known (git log/config); else `Name` + +__CLASS_NAME_PLACEHOLDER__ ` * class Foo` / interface / enum — omitted if none + +__CONTRIBUTORS_LIST_PLACEHOLDER__ + Sorted by commits, then blamed lines; `Name ` from git / @author tags + Includes Cursor Agent (project assistant, no email) + +__DIGEST__ `Digest: SHA256\t` of file without this line; omitted if N/A + +Example (Java) +-------------- +package com.foxx.androidcast; + +/********************************************************************* + * MainActivity.java + * Created at: Wed 20 May 2026 12:00:00 +0300 + * Updated at: Wed 20 May 2026 15:00:00 +0300 by Anton Afanasyeu + * class MainActivity + * Contributors: + * - Anton Afanasyeu (29 commits, 120 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 abc123... +**********************************************************************/ diff --git a/app/src/main/aidl/com/foxx/androidcast/ICastReceiverService.aidl b/app/src/main/aidl/com/foxx/androidcast/ICastReceiverService.aidl index 888362a..607bbbc 100644 --- a/app/src/main/aidl/com/foxx/androidcast/ICastReceiverService.aidl +++ b/app/src/main/aidl/com/foxx/androidcast/ICastReceiverService.aidl @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * ICastReceiverService.aidl + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Fri 15 May 2026 18:17:39 +0200 by Anton Afanasyeu + * interface ICastReceiverService + * Contributors: + * - Anton Afanasyeu (2 commits, 14 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 88566955bdbfa52d22a0c96b775ac5faf26e11d351914146475c3f8eb346a463 +**********************************************************************/ import com.foxx.androidcast.ICastStatusCallback; import android.view.Surface; diff --git a/app/src/main/aidl/com/foxx/androidcast/ICastSenderService.aidl b/app/src/main/aidl/com/foxx/androidcast/ICastSenderService.aidl index 5256718..e10ec7c 100644 --- a/app/src/main/aidl/com/foxx/androidcast/ICastSenderService.aidl +++ b/app/src/main/aidl/com/foxx/androidcast/ICastSenderService.aidl @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * ICastSenderService.aidl + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Fri 15 May 2026 16:49:02 +0200 by Anton Afanasyeu + * interface ICastSenderService + * Contributors: + * - Anton Afanasyeu (1 commits, 11 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d21d4abd6566c2426c9b3576ae9182945600ed96bc3fcee9f8671f8500e5e92a +**********************************************************************/ import com.foxx.androidcast.ICastStatusCallback; interface ICastSenderService { diff --git a/app/src/main/aidl/com/foxx/androidcast/ICastStatusCallback.aidl b/app/src/main/aidl/com/foxx/androidcast/ICastStatusCallback.aidl index 225694d..732c429 100644 --- a/app/src/main/aidl/com/foxx/androidcast/ICastStatusCallback.aidl +++ b/app/src/main/aidl/com/foxx/androidcast/ICastStatusCallback.aidl @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * ICastStatusCallback.aidl + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Fri 15 May 2026 18:17:39 +0200 by Anton Afanasyeu + * interface ICastStatusCallback + * Contributors: + * - Anton Afanasyeu (3 commits, 10 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 69ff616c65c49755706cd64afa54adf44361b35e922040e0ae26c407cb0d80a3 +**********************************************************************/ interface ICastStatusCallback { void onStatus(String status); void onAuthenticated(String senderName); diff --git a/app/src/main/java/com/foxx/androidcast/AndroidCastApplication.java b/app/src/main/java/com/foxx/androidcast/AndroidCastApplication.java index fc35c2f..d544d38 100644 --- a/app/src/main/java/com/foxx/androidcast/AndroidCastApplication.java +++ b/app/src/main/java/com/foxx/androidcast/AndroidCastApplication.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * AndroidCastApplication.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class AndroidCastApplication + * Contributors: + * - Anton Afanasyeu (5 commits, 27 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a776bd2da0db2d4424d2c82b29f4064e8b92057bb4a2cc244fd06a9bd691f074 +**********************************************************************/ import android.app.Application; import android.content.Context; diff --git a/app/src/main/java/com/foxx/androidcast/AppPreferences.java b/app/src/main/java/com/foxx/androidcast/AppPreferences.java index 5c07f6e..88d567e 100644 --- a/app/src/main/java/com/foxx/androidcast/AppPreferences.java +++ b/app/src/main/java/com/foxx/androidcast/AppPreferences.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * AppPreferences.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class AppPreferences + * Contributors: + * - Anton Afanasyeu (9 commits, 342 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 de97a9c6873e1016c993666f53e2a9d3ff32efd3bb320a1551a723fb52c017de +**********************************************************************/ import android.content.Context; import android.content.SharedPreferences; import android.os.Build; diff --git a/app/src/main/java/com/foxx/androidcast/CastActiveState.java b/app/src/main/java/com/foxx/androidcast/CastActiveState.java index 9db3e4b..55eb7b2 100644 --- a/app/src/main/java/com/foxx/androidcast/CastActiveState.java +++ b/app/src/main/java/com/foxx/androidcast/CastActiveState.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastActiveState.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CastActiveState + * Contributors: + * - Anton Afanasyeu (2 commits, 27 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 162f2f231fa3493dced21a6251e718ee20d457ed8b60b9a4d1b6f5b62ed3c19a +**********************************************************************/ import java.util.concurrent.atomic.AtomicBoolean; /** Process-wide cast session flags for UI back-key handling. */ diff --git a/app/src/main/java/com/foxx/androidcast/CastActivityTracker.java b/app/src/main/java/com/foxx/androidcast/CastActivityTracker.java index 568d3ab..0ff4ca9 100644 --- a/app/src/main/java/com/foxx/androidcast/CastActivityTracker.java +++ b/app/src/main/java/com/foxx/androidcast/CastActivityTracker.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastActivityTracker.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CastActivityTracker + * Contributors: + * - Anton Afanasyeu (1 commits, 28 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 666c3a5e9fc163616e6f43876c422dec735c496df4abf24a8f97ec526e8e27ec +**********************************************************************/ import android.app.Activity; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/CastConfig.java b/app/src/main/java/com/foxx/androidcast/CastConfig.java index 27f3d03..21ba256 100644 --- a/app/src/main/java/com/foxx/androidcast/CastConfig.java +++ b/app/src/main/java/com/foxx/androidcast/CastConfig.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastConfig.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class CastConfig + * Contributors: + * - Anton Afanasyeu (10 commits, 73 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2d04955cd4438be616e4f551cbc7e148d0bc652469af48e4ecd027c49d4cf5b0 +**********************************************************************/ /** Shared constants for the LAN cast POC. */ public final class CastConfig { public static final int DISCOVERY_PORT = 41234; diff --git a/app/src/main/java/com/foxx/androidcast/CastLocaleHelper.java b/app/src/main/java/com/foxx/androidcast/CastLocaleHelper.java index 199799a..5aee5fb 100644 --- a/app/src/main/java/com/foxx/androidcast/CastLocaleHelper.java +++ b/app/src/main/java/com/foxx/androidcast/CastLocaleHelper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastLocaleHelper.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class CastLocaleHelper + * Contributors: + * - Anton Afanasyeu (1 commits, 79 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d81acbee4562d0a5b236d0d04a9f98718684a43114f4aae298c68794e87ce4c9 +**********************************************************************/ import android.content.Context; import android.content.res.Configuration; import android.os.Build; diff --git a/app/src/main/java/com/foxx/androidcast/CastNotifications.java b/app/src/main/java/com/foxx/androidcast/CastNotifications.java index 6d551f4..834a9cc 100644 --- a/app/src/main/java/com/foxx/androidcast/CastNotifications.java +++ b/app/src/main/java/com/foxx/androidcast/CastNotifications.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastNotifications.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CastNotifications + * Contributors: + * - Anton Afanasyeu (2 commits, 61 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 608d748fe3cfc2a1f998235071603f746a55708f0eebb5eacb5612ae2c0f26ab +**********************************************************************/ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; diff --git a/app/src/main/java/com/foxx/androidcast/CastResolution.java b/app/src/main/java/com/foxx/androidcast/CastResolution.java index e0fb914..0835073 100644 --- a/app/src/main/java/com/foxx/androidcast/CastResolution.java +++ b/app/src/main/java/com/foxx/androidcast/CastResolution.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastResolution.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class CastResolution + * Contributors: + * - Anton Afanasyeu (5 commits, 80 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 258d94f85dcb71db5f559485e4e9bce64ad07521ed0e811486385f2b43357daf +**********************************************************************/ import android.content.Context; import android.util.DisplayMetrics; diff --git a/app/src/main/java/com/foxx/androidcast/CastSettings.java b/app/src/main/java/com/foxx/androidcast/CastSettings.java index fb00699..189ceaf 100644 --- a/app/src/main/java/com/foxx/androidcast/CastSettings.java +++ b/app/src/main/java/com/foxx/androidcast/CastSettings.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastSettings.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class CastSettings + * Contributors: + * - Anton Afanasyeu (8 commits, 286 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b3ffcc1bc5f0661330560c154e22c8012ceb49dac84e1fbb200dcafb3a34b91b +**********************************************************************/ import java.io.Serializable; /** User-selected cast parameters (passed sender → service → receiver via protocol). */ diff --git a/app/src/main/java/com/foxx/androidcast/CastSettingsActivity.java b/app/src/main/java/com/foxx/androidcast/CastSettingsActivity.java index c24599c..2819a09 100644 --- a/app/src/main/java/com/foxx/androidcast/CastSettingsActivity.java +++ b/app/src/main/java/com/foxx/androidcast/CastSettingsActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastSettingsActivity.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CastSettingsActivity + * Contributors: + * - Anton Afanasyeu (1 commits, 66 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 fe2993f5af3fe9225b29bbd697b1db76b184436209946aaa71411c218b609ccc +**********************************************************************/ import android.os.Bundle; import android.widget.CheckBox; import android.widget.EditText; diff --git a/app/src/main/java/com/foxx/androidcast/CastSettingsBinder.java b/app/src/main/java/com/foxx/androidcast/CastSettingsBinder.java index d8591bb..91fd1b2 100644 --- a/app/src/main/java/com/foxx/androidcast/CastSettingsBinder.java +++ b/app/src/main/java/com/foxx/androidcast/CastSettingsBinder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastSettingsBinder.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastSettingsBinder + * Contributors: + * - Anton Afanasyeu (7 commits, 643 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8d36d0b6baf281da92e6e3e170659a029668ce0147054664e38af527937878ac +**********************************************************************/ import android.os.Build; import android.view.View; import android.widget.AdapterView; diff --git a/app/src/main/java/com/foxx/androidcast/CastSettingsFragment.java b/app/src/main/java/com/foxx/androidcast/CastSettingsFragment.java index 27ef2b6..6d0df59 100644 --- a/app/src/main/java/com/foxx/androidcast/CastSettingsFragment.java +++ b/app/src/main/java/com/foxx/androidcast/CastSettingsFragment.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastSettingsFragment.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CastSettingsFragment + * Contributors: + * - Anton Afanasyeu (5 commits, 220 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bdb83325aaa0a2935a62b957ba60b887758b8f74dd2c26e764932e03c03d43ea +**********************************************************************/ import android.content.Intent; import android.os.Bundle; import android.os.SystemClock; diff --git a/app/src/main/java/com/foxx/androidcast/CastThemeHelper.java b/app/src/main/java/com/foxx/androidcast/CastThemeHelper.java index 28c90e0..d2c117e 100644 --- a/app/src/main/java/com/foxx/androidcast/CastThemeHelper.java +++ b/app/src/main/java/com/foxx/androidcast/CastThemeHelper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastThemeHelper.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CastThemeHelper + * Contributors: + * - Anton Afanasyeu (1 commits, 57 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cbd287ffcbfc3e18a0338a9c283c0539353f49eb8b0c45dc9c5179dc5be15b98 +**********************************************************************/ import android.app.Activity; import android.content.Context; diff --git a/app/src/main/java/com/foxx/androidcast/CastTrayNotifier.java b/app/src/main/java/com/foxx/androidcast/CastTrayNotifier.java index 25f27f5..b2134c9 100644 --- a/app/src/main/java/com/foxx/androidcast/CastTrayNotifier.java +++ b/app/src/main/java/com/foxx/androidcast/CastTrayNotifier.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastTrayNotifier.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class CastTrayNotifier + * Contributors: + * - Anton Afanasyeu (2 commits, 149 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4496d64128580bad13998e7edb8952d30711c276a289f9ed0444abf5d76b2de1 +**********************************************************************/ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; diff --git a/app/src/main/java/com/foxx/androidcast/CastTuningEngine.java b/app/src/main/java/com/foxx/androidcast/CastTuningEngine.java index bfa8136..80f4cf0 100644 --- a/app/src/main/java/com/foxx/androidcast/CastTuningEngine.java +++ b/app/src/main/java/com/foxx/androidcast/CastTuningEngine.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastTuningEngine.java + * Created at: Fri 15 May 2026 20:37:44 +0200 + * Updated at: Fri 15 May 2026 20:37:44 +0200 by Anton Afanasyeu + * class CastTuningEngine + * Contributors: + * - Anton Afanasyeu (1 commits, 173 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 af2a1d1fde9538e312542d79d3b83d504a770bfe20af852f9c3c6124a13b0dc7 +**********************************************************************/ import com.foxx.androidcast.network.control.NetworkStatsSnapshot; /** Resolves AUTO presets into concrete encoder/network/capture parameters. */ diff --git a/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java b/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java index a0134a2..a180ea1 100644 --- a/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java +++ b/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * DeveloperSettingsActivity.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class DeveloperSettingsActivity + * Contributors: + * - Anton Afanasyeu (6 commits, 122 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b4348356125b69d00896848a2442c06bb4f0b39806d4f4ada56aee212820c32a +**********************************************************************/ import android.content.Context; import android.os.Bundle; import android.widget.Button; diff --git a/app/src/main/java/com/foxx/androidcast/DeviceInfo.java b/app/src/main/java/com/foxx/androidcast/DeviceInfo.java index af92703..d8f6d66 100644 --- a/app/src/main/java/com/foxx/androidcast/DeviceInfo.java +++ b/app/src/main/java/com/foxx/androidcast/DeviceInfo.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * DeviceInfo.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class DeviceInfo + * Contributors: + * - Anton Afanasyeu (1 commits, 128 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 51194b9f608a719dc9bd302ce6a44971c17897388ff50e14c3c0ea9bb31b3b1c +**********************************************************************/ import android.content.Context; import android.content.SharedPreferences; import android.media.MediaDrm; diff --git a/app/src/main/java/com/foxx/androidcast/DrawerHostActivity.java b/app/src/main/java/com/foxx/androidcast/DrawerHostActivity.java index 8ada22d..cf61c70 100644 --- a/app/src/main/java/com/foxx/androidcast/DrawerHostActivity.java +++ b/app/src/main/java/com/foxx/androidcast/DrawerHostActivity.java @@ -1,5 +1,14 @@ package com.foxx.androidcast; +/********************************************************************* + * DrawerHostActivity.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (2 commits, 121 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3ddccb5d9ed03e2efea6cd7cfa2737b0b2023641d342d79a17fb904c4c897624 +**********************************************************************/ import android.content.Context; import android.os.Bundle; import android.view.KeyEvent; diff --git a/app/src/main/java/com/foxx/androidcast/IntentExtras.java b/app/src/main/java/com/foxx/androidcast/IntentExtras.java index 768e340..0234583 100644 --- a/app/src/main/java/com/foxx/androidcast/IntentExtras.java +++ b/app/src/main/java/com/foxx/androidcast/IntentExtras.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * IntentExtras.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class IntentExtras + * Contributors: + * - Anton Afanasyeu (2 commits, 44 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dee5835845935935951d0c5e1424234e16f63fe76ed0d320c2d066e79eb65fcd +**********************************************************************/ import android.content.Intent; import android.os.Build; diff --git a/app/src/main/java/com/foxx/androidcast/LicensesActivity.java b/app/src/main/java/com/foxx/androidcast/LicensesActivity.java index 5c0468f..e186134 100644 --- a/app/src/main/java/com/foxx/androidcast/LicensesActivity.java +++ b/app/src/main/java/com/foxx/androidcast/LicensesActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * LicensesActivity.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class LicensesActivity + * Contributors: + * - Anton Afanasyeu (1 commits, 43 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 935ebef063f54f3a589ddea64d016e1601ec97d100901a17fea11c4024c1547c +**********************************************************************/ import android.os.Bundle; import android.widget.Button; import android.widget.TextView; diff --git a/app/src/main/java/com/foxx/androidcast/MainActivity.java b/app/src/main/java/com/foxx/androidcast/MainActivity.java index 198dbea..7eae66b 100644 --- a/app/src/main/java/com/foxx/androidcast/MainActivity.java +++ b/app/src/main/java/com/foxx/androidcast/MainActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * MainActivity.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class MainActivity + * Contributors: + * - Anton Afanasyeu (6 commits, 90 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 07ddc304d47be2b05e4a33a0f201ede2b8d7b8c7feeebba7004aa50d785d915f +**********************************************************************/ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/PermissionHelper.java b/app/src/main/java/com/foxx/androidcast/PermissionHelper.java index 924030d..2aa4198 100644 --- a/app/src/main/java/com/foxx/androidcast/PermissionHelper.java +++ b/app/src/main/java/com/foxx/androidcast/PermissionHelper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * PermissionHelper.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class PermissionHelper + * Contributors: + * - Anton Afanasyeu (4 commits, 164 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3e4ac2f4543e9b30fbf2cacc4e385bd9bf1b0436c7aa5ce70ffad0f711fe8df6 +**********************************************************************/ import android.Manifest; import android.app.Activity; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/PictureInPictureHelper.java b/app/src/main/java/com/foxx/androidcast/PictureInPictureHelper.java index abdd8dd..7650788 100644 --- a/app/src/main/java/com/foxx/androidcast/PictureInPictureHelper.java +++ b/app/src/main/java/com/foxx/androidcast/PictureInPictureHelper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * PictureInPictureHelper.java + * Created at: Mon 18 May 2026 17:35:14 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class PictureInPictureHelper + * Contributors: + * - Anton Afanasyeu (2 commits, 102 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7de718c4dd2dd61c0ea66e0dd9a3f99308cf3275ec1a4a3aa2f6b3bc098f8016 +**********************************************************************/ import android.app.Activity; import android.app.AppOpsManager; import android.content.Context; diff --git a/app/src/main/java/com/foxx/androidcast/PinAuth.java b/app/src/main/java/com/foxx/androidcast/PinAuth.java index 9277bc9..fb20641 100644 --- a/app/src/main/java/com/foxx/androidcast/PinAuth.java +++ b/app/src/main/java/com/foxx/androidcast/PinAuth.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * PinAuth.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class PinAuth + * Contributors: + * - Anton Afanasyeu (1 commits, 38 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6165c61a6b2ae58fcef2241e57c6c32d9dea0715aca626d73501b3cf7696b313 +**********************************************************************/ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; diff --git a/app/src/main/java/com/foxx/androidcast/PlatformCastSupport.java b/app/src/main/java/com/foxx/androidcast/PlatformCastSupport.java index 69b31b8..362bac0 100644 --- a/app/src/main/java/com/foxx/androidcast/PlatformCastSupport.java +++ b/app/src/main/java/com/foxx/androidcast/PlatformCastSupport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * PlatformCastSupport.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class PlatformCastSupport + * Contributors: + * - Anton Afanasyeu (4 commits, 96 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 18bee330f23fac4e0ab8cf362cb1d0c08e2422f7db5e83dd1bbaa791ae479078 +**********************************************************************/ import android.os.Build; import android.widget.CheckBox; diff --git a/app/src/main/java/com/foxx/androidcast/SettingsUi.java b/app/src/main/java/com/foxx/androidcast/SettingsUi.java index 99ce0d3..0567995 100644 --- a/app/src/main/java/com/foxx/androidcast/SettingsUi.java +++ b/app/src/main/java/com/foxx/androidcast/SettingsUi.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * SettingsUi.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Mon 18 May 2026 16:13:34 +0200 by Anton Afanasyeu + * class SettingsUi + * Contributors: + * - Anton Afanasyeu (6 commits, 282 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 170c93a27eff81654fef9cd2fffb0ac678d584d64a35c6df1cce1f5769fc48f6 +**********************************************************************/ import android.os.Build; import android.view.View; import android.widget.AdapterView; diff --git a/app/src/main/java/com/foxx/androidcast/TrayForegroundService.java b/app/src/main/java/com/foxx/androidcast/TrayForegroundService.java index cd6f1e7..3309109 100644 --- a/app/src/main/java/com/foxx/androidcast/TrayForegroundService.java +++ b/app/src/main/java/com/foxx/androidcast/TrayForegroundService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * TrayForegroundService.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class TrayForegroundService + * Contributors: + * - Anton Afanasyeu (1 commits, 41 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 78ba745ee42c91e2edb1b39bf37ead35964c923891fd08bfd41dd5f6c20e5eac +**********************************************************************/ import android.app.Service; import android.content.Intent; import android.os.IBinder; diff --git a/app/src/main/java/com/foxx/androidcast/TrayNotificationReceiver.java b/app/src/main/java/com/foxx/androidcast/TrayNotificationReceiver.java index 8e5b152..23a1b3c 100644 --- a/app/src/main/java/com/foxx/androidcast/TrayNotificationReceiver.java +++ b/app/src/main/java/com/foxx/androidcast/TrayNotificationReceiver.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * TrayNotificationReceiver.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class TrayNotificationReceiver + * Contributors: + * - Anton Afanasyeu (1 commits, 19 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ae374cd478aa070476f2296bd91659d4d32bac8a573289642b2303b0ff171ebc +**********************************************************************/ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/VersionInfo.java b/app/src/main/java/com/foxx/androidcast/VersionInfo.java index 11e6ba4..078ab88 100644 --- a/app/src/main/java/com/foxx/androidcast/VersionInfo.java +++ b/app/src/main/java/com/foxx/androidcast/VersionInfo.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * VersionInfo.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class VersionInfo + * Contributors: + * - Anton Afanasyeu (2 commits, 33 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 17e6e61e27b385278659cf7b738998dfedc8d060bfdc129d04596c835568e956 +**********************************************************************/ /** * Application and protocol version strings (CI may replace via script). * App and proto versions are independent. diff --git a/app/src/main/java/com/foxx/androidcast/VersionUtils.java b/app/src/main/java/com/foxx/androidcast/VersionUtils.java index 7568d11..b91466b 100644 --- a/app/src/main/java/com/foxx/androidcast/VersionUtils.java +++ b/app/src/main/java/com/foxx/androidcast/VersionUtils.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * VersionUtils.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class VersionUtils + * Contributors: + * - Anton Afanasyeu (1 commits, 64 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2502541cc912d4de15fd395fb0495d531d62e9cb4dcc401ad85dd76d2fac262d +**********************************************************************/ import java.util.Locale; /** diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashNativeBridge.java b/app/src/main/java/com/foxx/androidcast/crash/CrashNativeBridge.java index 19e962b..771317a 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashNativeBridge.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashNativeBridge.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashNativeBridge.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashNativeBridge + * Contributors: + * - Anton Afanasyeu (1 commits, 40 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8b514f3041afb7bb14f77af82b2889117ee0eb16a618ccfe7bdd18dc6a7ae8fa +**********************************************************************/ import android.content.Context; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashReportBuilder.java b/app/src/main/java/com/foxx/androidcast/crash/CrashReportBuilder.java index 25cdc8d..ca38986 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashReportBuilder.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashReportBuilder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashReportBuilder.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashReportBuilder + * Contributors: + * - Anton Afanasyeu (1 commits, 179 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8c08460e946b2b0f241fa574e1623ea3dbe5e23203a5576c954328960519f8ff +**********************************************************************/ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashReportStore.java b/app/src/main/java/com/foxx/androidcast/crash/CrashReportStore.java index 15262c1..eda6f05 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashReportStore.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashReportStore.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashReportStore.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashReportStore + * Contributors: + * - Anton Afanasyeu (1 commits, 89 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0f29c399caba47f470e63fc70d59e19d957d8ea8aadfe3adf9612b5af1cd4816 +**********************************************************************/ import org.json.JSONObject; import java.io.File; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashReporter.java b/app/src/main/java/com/foxx/androidcast/crash/CrashReporter.java index 8c98e9c..b1cc48f 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashReporter.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashReporter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashReporter.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashReporter + * Contributors: + * - Anton Afanasyeu (1 commits, 82 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 77cf02ef84a200c618c0a1576253448c4cf374f47db5da012241abcc9861d1b7 +**********************************************************************/ import android.content.Context; import android.content.Intent; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashSettings.java b/app/src/main/java/com/foxx/androidcast/crash/CrashSettings.java index 673e448..e58f83d 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashSettings.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashSettings.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashSettings.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashSettings + * Contributors: + * - Anton Afanasyeu (1 commits, 22 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c0a455050fa42bf06395749696f325a5015d8438b996eff7ec04ffc53850f8c9 +**********************************************************************/ /** Crash reporter tuning from {@code settings.json} → {@code crash} (overrides app defaults). */ public final class CrashSettings { public static final String DEFAULT_UPLOAD_URL = diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashSettingsStore.java b/app/src/main/java/com/foxx/androidcast/crash/CrashSettingsStore.java index 3c01fbc..d17f255 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashSettingsStore.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashSettingsStore.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashSettingsStore.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashSettingsStore + * Contributors: + * - Anton Afanasyeu (1 commits, 79 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 977d059666e7184ea8ac019d10203af0fe288588e80559cb264ec1bb23251023 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.AppPreferences; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashUploadClient.java b/app/src/main/java/com/foxx/androidcast/crash/CrashUploadClient.java index 13d312c..66e8c97 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashUploadClient.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashUploadClient.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashUploadClient.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashUploadClient + * Contributors: + * - Anton Afanasyeu (1 commits, 57 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3b0a5fc13acd6488bbcdbda7ec4f0b176edd5750dc23bc00256ddfe4d613ad88 +**********************************************************************/ import org.json.JSONObject; import java.io.BufferedInputStream; diff --git a/app/src/main/java/com/foxx/androidcast/crash/CrashWatcherService.java b/app/src/main/java/com/foxx/androidcast/crash/CrashWatcherService.java index 080e15a..a738fb2 100644 --- a/app/src/main/java/com/foxx/androidcast/crash/CrashWatcherService.java +++ b/app/src/main/java/com/foxx/androidcast/crash/CrashWatcherService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.crash; +/********************************************************************* + * CrashWatcherService.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class CrashWatcherService + * Contributors: + * - Anton Afanasyeu (1 commits, 132 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d811f87bda10c67fb95758bf34a2aaea11f4fbcda05e2c9ef5726197440fd6c6 +**********************************************************************/ import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; diff --git a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsFormatter.java b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsFormatter.java index 51cf901..37e92b5 100644 --- a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsFormatter.java +++ b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsFormatter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CastDiagnosticsFormatter.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastDiagnosticsFormatter + * Contributors: + * - Anton Afanasyeu (4 commits, 509 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d5850de480c00191a4ea05d188b27fc693b6b1610b446b5bda642454e2acb7ae +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.CastTuningEngine; import com.foxx.androidcast.media.CodecNegotiator; diff --git a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsLabels.java b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsLabels.java index 0cc7668..317c9d4 100644 --- a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsLabels.java +++ b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsLabels.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CastDiagnosticsLabels.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Mon 18 May 2026 19:06:56 +0200 by Anton Afanasyeu + * class CastDiagnosticsLabels + * Contributors: + * - Anton Afanasyeu (5 commits, 152 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8877b68658b27f96dd1b92b051d6691dd492b73b127cb904caae8995e4ca3cba +**********************************************************************/ import com.foxx.androidcast.CastSettings; /** Human-readable names for diagnostics (no bare AUTO enum tokens). */ diff --git a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsScorer.java b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsScorer.java index 951a912..e4b9da8 100644 --- a/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsScorer.java +++ b/app/src/main/java/com/foxx/androidcast/diagnostics/CastDiagnosticsScorer.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CastDiagnosticsScorer.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class CastDiagnosticsScorer + * Contributors: + * - Anton Afanasyeu (1 commits, 62 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 65a8b453e9956d593194c1b9ce7b9145b17a44a34b22dfd030cff519638ded89 +**********************************************************************/ /** Heuristic stream quality score (0–100) from live metrics. */ public final class CastDiagnosticsScorer { private CastDiagnosticsScorer() {} diff --git a/app/src/main/java/com/foxx/androidcast/diagnostics/CastMtuSampler.java b/app/src/main/java/com/foxx/androidcast/diagnostics/CastMtuSampler.java index 6994326..326946b 100644 --- a/app/src/main/java/com/foxx/androidcast/diagnostics/CastMtuSampler.java +++ b/app/src/main/java/com/foxx/androidcast/diagnostics/CastMtuSampler.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CastMtuSampler.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastMtuSampler + * Contributors: + * - Anton Afanasyeu (1 commits, 67 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 9ca4cc1e6c4330b5d335bb920e119ececcd5f9ae0521fc2c0d00c382e3f7e326 +**********************************************************************/ import android.content.Context; import android.net.ConnectivityManager; import android.net.LinkProperties; diff --git a/app/src/main/java/com/foxx/androidcast/diagnostics/CpuLoadSampler.java b/app/src/main/java/com/foxx/androidcast/diagnostics/CpuLoadSampler.java index b38c479..fd1ba15 100644 --- a/app/src/main/java/com/foxx/androidcast/diagnostics/CpuLoadSampler.java +++ b/app/src/main/java/com/foxx/androidcast/diagnostics/CpuLoadSampler.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CpuLoadSampler.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CpuLoadSampler + * Contributors: + * - Anton Afanasyeu (1 commits, 234 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 58f78e53a4368c038af0ba3f933673c17d480209bcd6f33c6aa9a4b50f31a8e5 +**********************************************************************/ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; diff --git a/app/src/main/java/com/foxx/androidcast/discovery/DiscoveryManager.java b/app/src/main/java/com/foxx/androidcast/discovery/DiscoveryManager.java index 9afd98f..8cf37c7 100644 --- a/app/src/main/java/com/foxx/androidcast/discovery/DiscoveryManager.java +++ b/app/src/main/java/com/foxx/androidcast/discovery/DiscoveryManager.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * DiscoveryManager.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class DiscoveryManager + * Contributors: + * - Anton Afanasyeu (9 commits, 529 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 44b76dadc2e6a93d55274c415d54586eda5e2f849c072b4e250a3c4dea59da16 +**********************************************************************/ import android.content.Context; import android.net.wifi.WifiManager; import android.os.Handler; diff --git a/app/src/main/java/com/foxx/androidcast/discovery/DiscoverySelfFilter.java b/app/src/main/java/com/foxx/androidcast/discovery/DiscoverySelfFilter.java index 3bd7271..09e62d9 100644 --- a/app/src/main/java/com/foxx/androidcast/discovery/DiscoverySelfFilter.java +++ b/app/src/main/java/com/foxx/androidcast/discovery/DiscoverySelfFilter.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * DiscoverySelfFilter.java + * Created at: Sun 17 May 2026 15:45:19 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 67 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5220f398b12a33174a87393c848043015ef45df227353d6b404467974d065fc0 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.DeviceInfo; diff --git a/app/src/main/java/com/foxx/androidcast/discovery/NsdCastDiscovery.java b/app/src/main/java/com/foxx/androidcast/discovery/NsdCastDiscovery.java index 43af29a..f4a8101 100644 --- a/app/src/main/java/com/foxx/androidcast/discovery/NsdCastDiscovery.java +++ b/app/src/main/java/com/foxx/androidcast/discovery/NsdCastDiscovery.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * NsdCastDiscovery.java + * Created at: Mon 18 May 2026 17:46:19 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class NsdCastDiscovery + * Contributors: + * - Anton Afanasyeu (1 commits, 196 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 eaebdda82fa3894060a4a684e6399a34edf3c14ee7a74000cc16ddb27f7efbef +**********************************************************************/ import android.content.Context; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; diff --git a/app/src/main/java/com/foxx/androidcast/discovery/PinnedReceiversStore.java b/app/src/main/java/com/foxx/androidcast/discovery/PinnedReceiversStore.java index ba4dcbb..73d6f5f 100644 --- a/app/src/main/java/com/foxx/androidcast/discovery/PinnedReceiversStore.java +++ b/app/src/main/java/com/foxx/androidcast/discovery/PinnedReceiversStore.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * PinnedReceiversStore.java + * Created at: Mon 18 May 2026 17:46:19 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class PinnedReceiversStore + * Contributors: + * - Anton Afanasyeu (1 commits, 90 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 46e9c6c377c386c360272b3d5833f79b3f7ad54fefa021da09f196770ad7fc90 +**********************************************************************/ import android.content.Context; import android.content.SharedPreferences; diff --git a/app/src/main/java/com/foxx/androidcast/discovery/ReceiverCompatibility.java b/app/src/main/java/com/foxx/androidcast/discovery/ReceiverCompatibility.java index 672cea5..dde8a92 100644 --- a/app/src/main/java/com/foxx/androidcast/discovery/ReceiverCompatibility.java +++ b/app/src/main/java/com/foxx/androidcast/discovery/ReceiverCompatibility.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * ReceiverCompatibility.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class ReceiverCompatibility + * Contributors: + * - Anton Afanasyeu (1 commits, 45 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2f005cfe8f7472e444cb8e25992052a001defa7cb500bd9ebdec3ecc62b2da71 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.VersionInfo; import com.foxx.androidcast.network.CastCodecFlags; diff --git a/app/src/main/java/com/foxx/androidcast/media/AacAdtsHelper.java b/app/src/main/java/com/foxx/androidcast/media/AacAdtsHelper.java index 4c4e5f0..144691c 100644 --- a/app/src/main/java/com/foxx/androidcast/media/AacAdtsHelper.java +++ b/app/src/main/java/com/foxx/androidcast/media/AacAdtsHelper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * AacAdtsHelper.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class AacAdtsHelper + * Contributors: + * - Anton Afanasyeu (1 commits, 60 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 e5e7c2f68f4a40d97ebd510d0d791a2b2344e4a5587b54fd15bc3e17a7c39387 +**********************************************************************/ /** Prepends ADTS sync word so AAC decoders accept encoder access units. */ public final class AacAdtsHelper { private AacAdtsHelper() {} diff --git a/app/src/main/java/com/foxx/androidcast/media/CodecNegotiator.java b/app/src/main/java/com/foxx/androidcast/media/CodecNegotiator.java index c1c533b..9cb928a 100644 --- a/app/src/main/java/com/foxx/androidcast/media/CodecNegotiator.java +++ b/app/src/main/java/com/foxx/androidcast/media/CodecNegotiator.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * CodecNegotiator.java + * Created at: Fri 15 May 2026 20:37:44 +0200 + * Updated at: Mon 18 May 2026 19:06:56 +0200 by Anton Afanasyeu + * class CodecNegotiator + * Contributors: + * - Anton Afanasyeu (6 commits, 118 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ef7857e703bcb3f17da0a85b2f2a999f3080e0d71069e7767f5381a8eefc40e1 +**********************************************************************/ import android.media.MediaFormat; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/media/CodecPriorityCatalog.java b/app/src/main/java/com/foxx/androidcast/media/CodecPriorityCatalog.java index fdb1b71..e00d7bd 100644 --- a/app/src/main/java/com/foxx/androidcast/media/CodecPriorityCatalog.java +++ b/app/src/main/java/com/foxx/androidcast/media/CodecPriorityCatalog.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * CodecPriorityCatalog.java + * Created at: Mon 18 May 2026 18:59:14 +0200 + * Updated at: Mon 18 May 2026 19:06:56 +0200 by Anton Afanasyeu + * class CodecPriorityCatalog + * Contributors: + * - Anton Afanasyeu (2 commits, 535 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 fb5119a429e47b212225e8669680d1cb59e7ca722481569cd3daca701e0a2527 +**********************************************************************/ import android.content.Context; import android.media.MediaFormat; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/media/CodecPriorityId.java b/app/src/main/java/com/foxx/androidcast/media/CodecPriorityId.java index 2ee7009..a8a9a0f 100644 --- a/app/src/main/java/com/foxx/androidcast/media/CodecPriorityId.java +++ b/app/src/main/java/com/foxx/androidcast/media/CodecPriorityId.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * CodecPriorityId.java + * Created at: Mon 18 May 2026 18:59:14 +0200 + * Updated at: Mon 18 May 2026 18:59:14 +0200 by Anton Afanasyeu + * enum CodecPriorityId + * Contributors: + * - Anton Afanasyeu (1 commits, 96 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7322d377d22e974d10c300f08bf916f0dba2d6ce765d2b7a9442b264039ebdc1 +**********************************************************************/ import android.media.MediaFormat; import com.foxx.androidcast.CastSettings; diff --git a/app/src/main/java/com/foxx/androidcast/media/CodecTier.java b/app/src/main/java/com/foxx/androidcast/media/CodecTier.java index 1359c84..71ad056 100644 --- a/app/src/main/java/com/foxx/androidcast/media/CodecTier.java +++ b/app/src/main/java/com/foxx/androidcast/media/CodecTier.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * CodecTier.java + * Created at: Mon 18 May 2026 18:59:14 +0200 + * Updated at: Mon 18 May 2026 18:59:14 +0200 by Anton Afanasyeu + * enum CodecTier + * Contributors: + * - Anton Afanasyeu (1 commits, 14 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b78ccd5fefc1ce1edb8acda3c77187d844034dc723ea3823f1dcdc04d1c00bf0 +**********************************************************************/ /** Base tier added before per-codec component scores (lower total = higher priority). */ public enum CodecTier { HARDWARE(0), diff --git a/app/src/main/java/com/foxx/androidcast/media/EncodedStreamProbe.java b/app/src/main/java/com/foxx/androidcast/media/EncodedStreamProbe.java index c4d7a54..c465b0f 100644 --- a/app/src/main/java/com/foxx/androidcast/media/EncodedStreamProbe.java +++ b/app/src/main/java/com/foxx/androidcast/media/EncodedStreamProbe.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * EncodedStreamProbe.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class EncodedStreamProbe + * Contributors: + * - Anton Afanasyeu (1 commits, 32 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 14fefd1f2dc0f70d68bb9620a28ddae7561de4826feda15589f77b9728a6c177 +**********************************************************************/ import android.media.MediaFormat; /** Inspects encoded bitstream headers for diagnostics. */ diff --git a/app/src/main/java/com/foxx/androidcast/media/H264Bitstream.java b/app/src/main/java/com/foxx/androidcast/media/H264Bitstream.java index cdd16f3..c2cea49 100644 --- a/app/src/main/java/com/foxx/androidcast/media/H264Bitstream.java +++ b/app/src/main/java/com/foxx/androidcast/media/H264Bitstream.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * H264Bitstream.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class H264Bitstream + * Contributors: + * - Anton Afanasyeu (2 commits, 59 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 34f35ea8e68be7b3b7b1a5bdcb872f771bd66acc024c77c87eec1049e586108a +**********************************************************************/ import java.io.ByteArrayOutputStream; /** diff --git a/app/src/main/java/com/foxx/androidcast/media/H264SpsParser.java b/app/src/main/java/com/foxx/androidcast/media/H264SpsParser.java index 4889395..6056583 100644 --- a/app/src/main/java/com/foxx/androidcast/media/H264SpsParser.java +++ b/app/src/main/java/com/foxx/androidcast/media/H264SpsParser.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * H264SpsParser.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Fri 15 May 2026 17:47:09 +0200 by Anton Afanasyeu + * class H264SpsParser + * Contributors: + * - Anton Afanasyeu (1 commits, 170 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 e3d6068aa10b99580c4cf7d32bab017f5bb0396d973af2c9835479759126be26 +**********************************************************************/ import android.util.Log; /** Extracts coded picture size from H.264 SPS (csd-0 / Annex-B). */ diff --git a/app/src/main/java/com/foxx/androidcast/media/PcmLevelAnalyzer.java b/app/src/main/java/com/foxx/androidcast/media/PcmLevelAnalyzer.java index dd8aaac..adccf43 100644 --- a/app/src/main/java/com/foxx/androidcast/media/PcmLevelAnalyzer.java +++ b/app/src/main/java/com/foxx/androidcast/media/PcmLevelAnalyzer.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * PcmLevelAnalyzer.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class PcmLevelAnalyzer + * Contributors: + * - Anton Afanasyeu (1 commits, 67 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ddde6fc40ce49037fd4909f8732acd8db1344ff0d5127b8a30f4317950058f9d +**********************************************************************/ /** Peak/RMS analysis for 16-bit little-endian PCM. */ public final class PcmLevelAnalyzer { /** ~-46 dBFS; below this counts as silence. */ diff --git a/app/src/main/java/com/foxx/androidcast/media/RgbToNv21.java b/app/src/main/java/com/foxx/androidcast/media/RgbToNv21.java index 659ddcf..3e4d63f 100644 --- a/app/src/main/java/com/foxx/androidcast/media/RgbToNv21.java +++ b/app/src/main/java/com/foxx/androidcast/media/RgbToNv21.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * RgbToNv21.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class RgbToNv21 + * Contributors: + * - Anton Afanasyeu (1 commits, 52 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0c252db38e3dc88ff060adaad16ea98d3ad987dacbdc29866b0450fa64c4a91c +**********************************************************************/ import android.graphics.Bitmap; /** ARGB bitmap to NV21 for YUV420 encoder input. */ diff --git a/app/src/main/java/com/foxx/androidcast/media/RgbToYuv420.java b/app/src/main/java/com/foxx/androidcast/media/RgbToYuv420.java index 124344d..bee1c05 100644 --- a/app/src/main/java/com/foxx/androidcast/media/RgbToYuv420.java +++ b/app/src/main/java/com/foxx/androidcast/media/RgbToYuv420.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * RgbToYuv420.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class RgbToYuv420 + * Contributors: + * - Anton Afanasyeu (3 commits, 152 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 83090016677ef209cbf10ed4622d5ea91ea6826bdb4cec87abda4fff38ab91fc +**********************************************************************/ import android.graphics.Bitmap; import android.media.Image; diff --git a/app/src/main/java/com/foxx/androidcast/media/StreamDimensionResolver.java b/app/src/main/java/com/foxx/androidcast/media/StreamDimensionResolver.java index 2776178..22f35dc 100644 --- a/app/src/main/java/com/foxx/androidcast/media/StreamDimensionResolver.java +++ b/app/src/main/java/com/foxx/androidcast/media/StreamDimensionResolver.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * StreamDimensionResolver.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Fri 15 May 2026 17:47:09 +0200 by Anton Afanasyeu + * class StreamDimensionResolver + * Contributors: + * - Anton Afanasyeu (1 commits, 42 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4e251b5f6e24e7f1d25e011c50900ac71f646bc390f8fd807d59ede90c87f9d0 +**********************************************************************/ /** * Resolves display dimensions using STREAM_CONFIG and SPS (csd-0). * SPS confirms coded size; config reflects sender VirtualDisplay (preferred for rotation). diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecBackend.java b/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecBackend.java index 743edf3..ae3992f 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecBackend.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecBackend.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * AudioCodecBackend.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * enum AudioCodecBackend + * Contributors: + * - Anton Afanasyeu (1 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a3e8cbaafae40d12639d3afb5fc1612a6f7459ce87813ab32db79fb1295b160f +**********************************************************************/ /** Implementation backing negotiated / configured audio. */ public enum AudioCodecBackend { MEDIA_CODEC_AAC("MediaCodec AAC-LC"), diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecFactory.java b/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecFactory.java index c5cba0e..d04d671 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecFactory.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/AudioCodecFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * AudioCodecFactory.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class AudioCodecFactory + * Contributors: + * - Anton Afanasyeu (1 commits, 18 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cabd8206db44b5aa04bcb29685d606b9fd1887da3f806cacde70f6ab50d8627e +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.sender.AudioEncoder; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/AudioEncoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/AudioEncoderSink.java index 2754943..a717a53 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/AudioEncoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/AudioEncoderSink.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * AudioEncoderSink.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * interface AudioEncoderSink + * Contributors: + * - Anton Afanasyeu (1 commits, 21 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 90599f0653960bf2abd5acaad53ed356c93791addf4f2b2016d1b4ab2aaaecf7 +**********************************************************************/ import java.io.IOException; /** Audio encoder pipeline (AAC via MediaCodec today; Speex/Opus later). */ diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/CodecSessionRegistry.java b/app/src/main/java/com/foxx/androidcast/media/codec/CodecSessionRegistry.java index b4e6e0b..4c3f09c 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/CodecSessionRegistry.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/CodecSessionRegistry.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * CodecSessionRegistry.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class CodecSessionRegistry + * Contributors: + * - Anton Afanasyeu (1 commits, 69 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 140617f123313015f483828dd18977bba84a49f7b7d12bbee24873908a550b9f +**********************************************************************/ import com.foxx.androidcast.CastSettings; /** Active codec backends for diagnostics overlay (receiver reads sender prefs + local decode). */ diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxCapableVideoDecoder.java b/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxCapableVideoDecoder.java index bbb48d5..7212085 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxCapableVideoDecoder.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxCapableVideoDecoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * LibvpxCapableVideoDecoder.java + * Created at: Mon 18 May 2026 17:05:47 +0200 + * Updated at: Mon 18 May 2026 17:05:47 +0200 by Anton Afanasyeu + * class LibvpxCapableVideoDecoder + * Contributors: + * - Anton Afanasyeu (1 commits, 52 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3a4aa27b931e77bf7ec67651b47aea2e03d7f40320cd9bae0aff1ff9e59fd756 +**********************************************************************/ import android.util.Log; import android.view.Surface; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxVideoEncoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxVideoEncoderSink.java index 1a4d87b..335933a 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxVideoEncoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/LibvpxVideoEncoderSink.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * LibvpxVideoEncoderSink.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class LibvpxVideoEncoderSink + * Contributors: + * - Anton Afanasyeu (3 commits, 237 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 816c190473ca485c66ac20fd3dce407934aa59fb8a8d378d26b0e3cfaa93a451 +**********************************************************************/ import android.graphics.Bitmap; import android.graphics.PixelFormat; import android.media.Image; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughAudioEncoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughAudioEncoderSink.java index 5219901..6dac45d 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughAudioEncoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughAudioEncoderSink.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * PassthroughAudioEncoderSink.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 42 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dfd84edfe75353b1a4ad6338fe2b6e2b00d822cba052de699bc363051f070886 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.sender.AudioEncoder; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java index 5d2b324..e4c1555 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughCodecPolicy.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * PassthroughCodecPolicy.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 17:05:47 +0200 by Anton Afanasyeu + * class PassthroughCodecPolicy + * Contributors: + * - Anton Afanasyeu (3 commits, 147 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c1cb0e5c2fc9cefd76d673abfdc4f2740b4d7397e7de7956a340d4896e72daf1 +**********************************************************************/ import android.media.MediaFormat; import com.foxx.androidcast.CastSettings; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughVideoEncoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughVideoEncoderSink.java index ec92a6c..d40fa1c 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughVideoEncoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/PassthroughVideoEncoderSink.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * PassthroughVideoEncoderSink.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 65 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 acc514297e421faa55c42985081ef95f236ec0ad67cc3c066fa6fa583d6765f1 +**********************************************************************/ import android.graphics.Bitmap; import android.view.Surface; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecBackend.java b/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecBackend.java index 5d6056c..4d7fb4f 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecBackend.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecBackend.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * VideoCodecBackend.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * enum VideoCodecBackend + * Contributors: + * - Anton Afanasyeu (2 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8b186ea93d80070f21a253710cfff90640a9d81db3ebd09baf1c9bc402f4b19f +**********************************************************************/ /** Implementation backing a negotiated video MIME. */ public enum VideoCodecBackend { MEDIA_CODEC_HW("MediaCodec (HW)"), diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecFactory.java b/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecFactory.java index 96e3f4b..d5c392b 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecFactory.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/VideoCodecFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * VideoCodecFactory.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class VideoCodecFactory + * Contributors: + * - Anton Afanasyeu (2 commits, 27 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b8fe0383fede0eeebec3168b5808277136a800057cee232d1ae7b7f1695141c4 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.media.codec.jni.NativeCodecBridge; import com.foxx.androidcast.sender.VideoEncoder; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderFactory.java b/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderFactory.java index bf05d9c..1af384c 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderFactory.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * VideoDecoderFactory.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 17:05:47 +0200 by Anton Afanasyeu + * class VideoDecoderFactory + * Contributors: + * - Anton Afanasyeu (2 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1df40e44f12bbaad052b116851044728e7d85264bdda9f636b0bbab159ef7f7a +**********************************************************************/ import com.foxx.androidcast.media.codec.jni.NativeCodecBridge; import com.foxx.androidcast.receiver.VideoDecoder; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderSink.java index d4b257b..9ec2169 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/VideoDecoderSink.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * VideoDecoderSink.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * interface VideoDecoderSink + * Contributors: + * - Anton Afanasyeu (1 commits, 24 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f3e3d03ad0a9f7bc960028bb4a6a87fad99f48da3b75e6087981956e5f93dab0 +**********************************************************************/ import android.view.Surface; import java.io.IOException; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/VideoEncoderSink.java b/app/src/main/java/com/foxx/androidcast/media/codec/VideoEncoderSink.java index fc5f5bf..96815a8 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/VideoEncoderSink.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/VideoEncoderSink.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec; +/********************************************************************* + * VideoEncoderSink.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * interface VideoEncoderSink + * Contributors: + * - Anton Afanasyeu (1 commits, 34 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6b6feb3a9dc99f90c29e54305c32de6f5e0e8dd45ad7d5a3f6039567642d242c +**********************************************************************/ import android.graphics.Bitmap; import android.view.Surface; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/jni/NativeCodecBridge.java b/app/src/main/java/com/foxx/androidcast/media/codec/jni/NativeCodecBridge.java index ae6aff9..035991c 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/jni/NativeCodecBridge.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/jni/NativeCodecBridge.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec.jni; +/********************************************************************* + * NativeCodecBridge.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 17:05:47 +0200 by Anton Afanasyeu + * class NativeCodecBridge + * Contributors: + * - Anton Afanasyeu (3 commits, 117 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 85eb4903f054caa9cccbd87793a63c40b661700f8e6b5fedb825f04744d3153b +**********************************************************************/ import android.util.Log; import android.view.Surface; diff --git a/app/src/main/java/com/foxx/androidcast/media/codec/jni/VpxEncodedFrame.java b/app/src/main/java/com/foxx/androidcast/media/codec/jni/VpxEncodedFrame.java index d3850f9..947bd44 100644 --- a/app/src/main/java/com/foxx/androidcast/media/codec/jni/VpxEncodedFrame.java +++ b/app/src/main/java/com/foxx/androidcast/media/codec/jni/VpxEncodedFrame.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media.codec.jni; +/********************************************************************* + * VpxEncodedFrame.java + * Created at: Mon 18 May 2026 17:05:47 +0200 + * Updated at: Mon 18 May 2026 17:05:47 +0200 by Anton Afanasyeu + * class VpxEncodedFrame + * Contributors: + * - Anton Afanasyeu (1 commits, 12 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 14d48bc528324744dc8ff64c1543740826d3b9f123266d2dc9a50969aae37be6 +**********************************************************************/ /** One compressed VP8/VP9 frame from libvpx. */ public final class VpxEncodedFrame { public final byte[] data; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java b/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java index e0feba0..9b9ffbc 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastCodecFlags.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastCodecFlags.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class CastCodecFlags + * Contributors: + * - Anton Afanasyeu (1 commits, 53 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0d19da4f9bc8d1dec18092777bc476af51763ff27d167a19ca1b62cd5be30458 +**********************************************************************/ import android.media.MediaFormat; import com.foxx.androidcast.sender.CodecCatalog; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastFramingContext.java b/app/src/main/java/com/foxx/androidcast/network/CastFramingContext.java index 491a514..b8a44f5 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastFramingContext.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastFramingContext.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastFramingContext.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class CastFramingContext + * Contributors: + * - Anton Afanasyeu (1 commits, 26 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 e372ad99b992ebc59f48f302ec64f200ef44037d138bcb930d1f1e40950ecd84 +**********************************************************************/ /** Per-session values written into {@link CastProtoHeader}. */ public final class CastFramingContext { public final int sessionId; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastPacketFramer.java b/app/src/main/java/com/foxx/androidcast/network/CastPacketFramer.java index e375237..8d98338 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastPacketFramer.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastPacketFramer.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastPacketFramer.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class CastPacketFramer + * Contributors: + * - Anton Afanasyeu (2 commits, 112 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b3754ac188b79a099a1ec75b069c1c0ee246749a16df31cb0a1f03dc26bbc285 +**********************************************************************/ import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastProtoHeader.java b/app/src/main/java/com/foxx/androidcast/network/CastProtoHeader.java index 0bffc8d..aa9c549 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastProtoHeader.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastProtoHeader.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastProtoHeader.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class CastProtoHeader + * Contributors: + * - Anton Afanasyeu (1 commits, 131 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 12e42b2de9e3b317ebe8a55eca1d099b524e3fc4d8ae43ef8aa55d4345f9f6f2 +**********************************************************************/ import com.foxx.androidcast.VersionInfo; import java.nio.ByteBuffer; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastProtocol.java b/app/src/main/java/com/foxx/androidcast/network/CastProtocol.java index b9d425f..8c44236 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastProtocol.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastProtocol.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastProtocol.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastProtocol + * Contributors: + * - Anton Afanasyeu (9 commits, 521 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5cad5f5d7b19c23e11c9d906c8faaad080c4fe1c4979e63534f143ba6450f964 +**********************************************************************/ import com.foxx.androidcast.CastConfig; import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.network.control.NetworkControlAdvice; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastSession.java b/app/src/main/java/com/foxx/androidcast/network/CastSession.java index 877be8c..5ba9a0a 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastSession.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastSession.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastSession.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class CastSession + * Contributors: + * - Anton Afanasyeu (8 commits, 200 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 81d0fcee90b930796bd96b7797126ff5bea83230c19284f2b353ff23ebe861b3 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.media.CodecNegotiator; import com.foxx.androidcast.media.CodecPriorityCatalog; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastSessionGate.java b/app/src/main/java/com/foxx/androidcast/network/CastSessionGate.java index 853e565..35b9ef3 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastSessionGate.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastSessionGate.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastSessionGate.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class CastSessionGate + * Contributors: + * - Anton Afanasyeu (1 commits, 37 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d7cbe13ecd00c0eff21bc5fab590cdcd5c0ff61bc196003800d5222a36987d6b +**********************************************************************/ /** * Binds to the first non-zero session id on a connection and drops stale packets from other casts. */ diff --git a/app/src/main/java/com/foxx/androidcast/network/CastTransport.java b/app/src/main/java/com/foxx/androidcast/network/CastTransport.java index a4b4f90..1f02212 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastTransport.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastTransport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastTransport.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * interface CastTransport + * Contributors: + * - Anton Afanasyeu (4 commits, 48 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5f6c3eac36ae5bbdb505ea5887fb12d45d7389e9779aecc325dc0ee5a89efa86 +**********************************************************************/ import com.foxx.androidcast.network.transport.TransportLossStats; import java.io.Closeable; diff --git a/app/src/main/java/com/foxx/androidcast/network/CastTransportFactory.java b/app/src/main/java/com/foxx/androidcast/network/CastTransportFactory.java index e680118..ab4d633 100644 --- a/app/src/main/java/com/foxx/androidcast/network/CastTransportFactory.java +++ b/app/src/main/java/com/foxx/androidcast/network/CastTransportFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastTransportFactory.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastTransportFactory + * Contributors: + * - Anton Afanasyeu (5 commits, 83 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7c439b37f91dd94df72bc0f354cd68ef000393f2d6fe68b804e5b5189fd83626 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.CastConfig; diff --git a/app/src/main/java/com/foxx/androidcast/network/TcpCastTransport.java b/app/src/main/java/com/foxx/androidcast/network/TcpCastTransport.java index 2f13863..8d63ffe 100644 --- a/app/src/main/java/com/foxx/androidcast/network/TcpCastTransport.java +++ b/app/src/main/java/com/foxx/androidcast/network/TcpCastTransport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * TcpCastTransport.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class TcpCastTransport + * Contributors: + * - Anton Afanasyeu (6 commits, 281 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 18d570b2bd2d08bbcfac95e43e5cf3fd61eb6591e1f539715bea93e104ca5ae9 +**********************************************************************/ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; diff --git a/app/src/main/java/com/foxx/androidcast/network/UdpCastTransport.java b/app/src/main/java/com/foxx/androidcast/network/UdpCastTransport.java index 2a2f075..0d268c7 100644 --- a/app/src/main/java/com/foxx/androidcast/network/UdpCastTransport.java +++ b/app/src/main/java/com/foxx/androidcast/network/UdpCastTransport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * UdpCastTransport.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class UdpCastTransport + * Contributors: + * - Anton Afanasyeu (8 commits, 596 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 00e1e8c88544801396c85cc876275d12331452f11f15b297a90f7276cac18095 +**********************************************************************/ import android.util.Log; import com.foxx.androidcast.CastConfig; diff --git a/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlAdvice.java b/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlAdvice.java index f199bd2..468479e 100644 --- a/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlAdvice.java +++ b/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlAdvice.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.control; +/********************************************************************* + * NetworkControlAdvice.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class NetworkControlAdvice + * Contributors: + * - Anton Afanasyeu (2 commits, 17 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d370483b41b728cce3dee488c9b7ac305c3c46abf8a2914715b02b4ee438768b +**********************************************************************/ import com.foxx.androidcast.CastConfig; /** Actionable guidance produced by the network control plane (may be no-op). */ diff --git a/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlPlane.java b/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlPlane.java index 5066901..2be7634 100644 --- a/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlPlane.java +++ b/app/src/main/java/com/foxx/androidcast/network/control/NetworkControlPlane.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.control; +/********************************************************************* + * NetworkControlPlane.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Fri 15 May 2026 17:47:09 +0200 by Anton Afanasyeu + * interface NetworkControlPlane + * Contributors: + * - Anton Afanasyeu (1 commits, 22 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c259f63567dfca2cd2bb4d623817347ec502ebc8dc23ca4ffb6f6e640150425c +**********************************************************************/ /** * Pluggable network intelligence: bandwidth estimation, congestion, transport switching. * Replace {@link PassThroughNetworkControlPlane} with a real implementation when ready. diff --git a/app/src/main/java/com/foxx/androidcast/network/control/NetworkFeedbackManager.java b/app/src/main/java/com/foxx/androidcast/network/control/NetworkFeedbackManager.java index e00ee02..ddf0823 100644 --- a/app/src/main/java/com/foxx/androidcast/network/control/NetworkFeedbackManager.java +++ b/app/src/main/java/com/foxx/androidcast/network/control/NetworkFeedbackManager.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.control; +/********************************************************************* + * NetworkFeedbackManager.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Fri 15 May 2026 17:47:09 +0200 by Anton Afanasyeu + * class NetworkFeedbackManager + * Contributors: + * - Anton Afanasyeu (1 commits, 91 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1e092cc8a586f5aea0c30b866f5ded2a565853aaaf4fa6ae424d7b0f481fc030 +**********************************************************************/ import android.util.Log; import com.foxx.androidcast.network.CastProtocol; diff --git a/app/src/main/java/com/foxx/androidcast/network/control/NetworkStatsSnapshot.java b/app/src/main/java/com/foxx/androidcast/network/control/NetworkStatsSnapshot.java index bebb93f..5f259b9 100644 --- a/app/src/main/java/com/foxx/androidcast/network/control/NetworkStatsSnapshot.java +++ b/app/src/main/java/com/foxx/androidcast/network/control/NetworkStatsSnapshot.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.control; +/********************************************************************* + * NetworkStatsSnapshot.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class NetworkStatsSnapshot + * Contributors: + * - Anton Afanasyeu (4 commits, 100 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c6bb775850299ada94ed1ed4a46bab38a98b2057ca520d41d28e3c66cd87d641 +**********************************************************************/ /** Point-in-time network metrics exchanged between sender and receiver. */ public class NetworkStatsSnapshot { public long sequence; diff --git a/app/src/main/java/com/foxx/androidcast/network/control/PassThroughNetworkControlPlane.java b/app/src/main/java/com/foxx/androidcast/network/control/PassThroughNetworkControlPlane.java index 052fb67..42ce951 100644 --- a/app/src/main/java/com/foxx/androidcast/network/control/PassThroughNetworkControlPlane.java +++ b/app/src/main/java/com/foxx/androidcast/network/control/PassThroughNetworkControlPlane.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.control; +/********************************************************************* + * PassThroughNetworkControlPlane.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class PassThroughNetworkControlPlane + * Contributors: + * - Anton Afanasyeu (6 commits, 136 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 9342c241e07a9e20bcc01189aa60599b74299eed704b73f276069d284a787a42 +**********************************************************************/ import com.foxx.androidcast.CastConfig; /** diff --git a/app/src/main/java/com/foxx/androidcast/network/quic/CronetEngineProvider.java b/app/src/main/java/com/foxx/androidcast/network/quic/CronetEngineProvider.java index 03014e0..3b4677f 100644 --- a/app/src/main/java/com/foxx/androidcast/network/quic/CronetEngineProvider.java +++ b/app/src/main/java/com/foxx/androidcast/network/quic/CronetEngineProvider.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.quic; +/********************************************************************* + * CronetEngineProvider.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class CronetEngineProvider + * Contributors: + * - Anton Afanasyeu (1 commits, 50 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f5230a728a1b6f74b43032d303535600f085b851bee1aa3ffdedbd49429c1c59 +**********************************************************************/ import android.content.Context; import com.google.android.gms.net.CronetProviderInstaller; diff --git a/app/src/main/java/com/foxx/androidcast/network/quic/QuicCronetCastTransport.java b/app/src/main/java/com/foxx/androidcast/network/quic/QuicCronetCastTransport.java index d42b63a..e5da96a 100644 --- a/app/src/main/java/com/foxx/androidcast/network/quic/QuicCronetCastTransport.java +++ b/app/src/main/java/com/foxx/androidcast/network/quic/QuicCronetCastTransport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.quic; +/********************************************************************* + * QuicCronetCastTransport.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class QuicCronetCastTransport + * Contributors: + * - Anton Afanasyeu (2 commits, 143 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5467419a77ef3f01fedafc49ecde37906a9e2308fefb0021cf8885e5e78adae6 +**********************************************************************/ import android.content.Context; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/CombinedProtectionEngine.java b/app/src/main/java/com/foxx/androidcast/network/transport/CombinedProtectionEngine.java index 88013f0..a3b7f33 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/CombinedProtectionEngine.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/CombinedProtectionEngine.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * CombinedProtectionEngine.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CombinedProtectionEngine + * Contributors: + * - Anton Afanasyeu (2 commits, 46 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1ad9b755b97b582e842dbb260a45a5c00354f49950f3b356327f21fbafcc6ec8 +**********************************************************************/ /** FEC 3/4 (default) plus NACK retransmission. */ public final class CombinedProtectionEngine implements StreamProtectionEngine { private final FecProtectionEngine fec; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/FecProtectionEngine.java b/app/src/main/java/com/foxx/androidcast/network/transport/FecProtectionEngine.java index d9ee5bb..e8407a1 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/FecProtectionEngine.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/FecProtectionEngine.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * FecProtectionEngine.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class FecProtectionEngine + * Contributors: + * - Anton Afanasyeu (3 commits, 270 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 526677234fd414bc5ebec7da1b352eac12c336f85b70f9d3500e22728ff2f2d1 +**********************************************************************/ import com.foxx.androidcast.network.CastProtoHeader; import com.foxx.androidcast.network.CastProtocol; import com.foxx.androidcast.network.transport.fec.FecEncodedGroup; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/NackProtectionEngine.java b/app/src/main/java/com/foxx/androidcast/network/transport/NackProtectionEngine.java index 650f3eb..6506842 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/NackProtectionEngine.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/NackProtectionEngine.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * NackProtectionEngine.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class NackProtectionEngine + * Contributors: + * - Anton Afanasyeu (2 commits, 98 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 10ca17df4e5cc4388e8cde7e5ee18a95834d0f35b0505376aeaec883c3f6cfde +**********************************************************************/ import com.foxx.androidcast.network.CastProtocol; import java.io.ByteArrayOutputStream; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/NackRateLimiter.java b/app/src/main/java/com/foxx/androidcast/network/transport/NackRateLimiter.java index 828e416..31b95b9 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/NackRateLimiter.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/NackRateLimiter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * NackRateLimiter.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class NackRateLimiter + * Contributors: + * - Anton Afanasyeu (1 commits, 46 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8d2d4b7469b334ba92ad5f5374de828f35373a1cb6db9da3d714f39bd68d64f7 +**********************************************************************/ import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/ProtectionNegotiationPrompts.java b/app/src/main/java/com/foxx/androidcast/network/transport/ProtectionNegotiationPrompts.java index 812cc2d..5f51fd6 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/ProtectionNegotiationPrompts.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/ProtectionNegotiationPrompts.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * ProtectionNegotiationPrompts.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class ProtectionNegotiationPrompts + * Contributors: + * - Anton Afanasyeu (1 commits, 56 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dea8661d88add8f5890ec3972b910a025fb2f08936cc623012df81d1c49fb0f5 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.CastSettings; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/RetransmitCache.java b/app/src/main/java/com/foxx/androidcast/network/transport/RetransmitCache.java index 80937de..ff7c87f 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/RetransmitCache.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/RetransmitCache.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * RetransmitCache.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class RetransmitCache + * Contributors: + * - Anton Afanasyeu (2 commits, 53 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4322b90ca68dc4b86d43cd08fcc716aa784793cc5387f148d715153614aa54ad +**********************************************************************/ import java.util.LinkedHashMap; import java.util.Map; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCapability.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCapability.java index 94b8096..355b917 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCapability.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCapability.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionCapability.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionCapability + * Contributors: + * - Anton Afanasyeu (1 commits, 46 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 111b4c7604a9f3cf31ee5ce22c043c5514639a65319f4f647b1ec3c9ef6be706 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import java.util.EnumSet; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCompat.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCompat.java index abfc46c..bc7c013 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCompat.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionCompat.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionCompat.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class StreamProtectionCompat + * Contributors: + * - Anton Afanasyeu (1 commits, 26 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f82d2d385ad2e5c1828772f1f65f2c34c31424c9e7bbcb7fa9082790bc5da780 +**********************************************************************/ import com.foxx.androidcast.network.transport.fec.FecShardWire; import com.foxx.androidcast.network.transport.fec.ProtectionEnvelope; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionEngine.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionEngine.java index 493259b..5ab4092 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionEngine.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionEngine.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionEngine.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * interface StreamProtectionEngine + * Contributors: + * - Anton Afanasyeu (2 commits, 39 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cd65458b03554455c13e8a1840e9f69fdc9aa150c488684b2bad354d2d112224 +**********************************************************************/ /** * FEC / NACK over UDP logical payloads (before ACUD fragmentation). */ diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionFactory.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionFactory.java index d703290..d7f3ddc 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionFactory.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionFactory.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionFactory + * Contributors: + * - Anton Afanasyeu (2 commits, 65 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 37d6ee995c84c821bf1b19289e2d2a7ca9bb06b7abaab3a91f77b4c7786021a4 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.network.UdpCastTransport; import com.foxx.androidcast.network.transport.fec.ProtectionEnvelope; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionMode.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionMode.java index 70cdc61..4a826ac 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionMode.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionMode.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionMode.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * enum StreamProtectionMode + * Contributors: + * - Anton Afanasyeu (3 commits, 38 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c9a8f91f998b09cf1b71e3c7278c5c5c2fc7c6ecbea2fb6d635933c062e016bc +**********************************************************************/ /** Active UDP stream protection mode. */ public enum StreamProtectionMode { NONE, diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiation.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiation.java index b762331..e28114e 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiation.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiation.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionNegotiation.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionNegotiation + * Contributors: + * - Anton Afanasyeu (1 commits, 45 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 fc9318ae60374bf7b9f6ec7ebd33d9a1430362e2b88d8e5d2121659b6585295f +**********************************************************************/ import com.foxx.androidcast.CastSettings; /** Outcome of matching local/remote {@link CastSettings.StreamProtection} preferences. */ diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiator.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiator.java index 14cda8f..fca357f 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiator.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiator.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionNegotiator.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionNegotiator + * Contributors: + * - Anton Afanasyeu (3 commits, 242 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 27372ce6f48d7eb7df3748e22f0fa9385ac70170b4e4b66122ce27e136984860 +**********************************************************************/ import com.foxx.androidcast.CastSettings; import com.foxx.androidcast.R; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionScopes.java b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionScopes.java index dc509e9..f7d5141 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionScopes.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/StreamProtectionScopes.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionScopes.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class StreamProtectionScopes + * Contributors: + * - Anton Afanasyeu (1 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 42793583e62578d8b79fe2b63a6fc21964f200a4feb61dd7d6662f655796ec6e +**********************************************************************/ import com.foxx.androidcast.network.CastProtocol; /** Which UDP cast message types use FEC/NACK payload wrapping. */ diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStats.java b/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStats.java index c757b20..f8cc968 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStats.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStats.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * TransportLossStats.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class TransportLossStats + * Contributors: + * - Anton Afanasyeu (3 commits, 130 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2871b0287670ab7d4afd77ceb9c27e9dd302fbe4a10fd2bd5f445f9fbb1b9968 +**********************************************************************/ /** * Per-transport loss / damage counters (UDP datagrams, reassembly, app-layer drops). * Thread-safe increments; copy for stats exchange. diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStatsBridge.java b/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStatsBridge.java index 192b1c7..3075fba 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStatsBridge.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/TransportLossStatsBridge.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * TransportLossStatsBridge.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class TransportLossStatsBridge + * Contributors: + * - Anton Afanasyeu (3 commits, 45 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1e1aa06bab315f58f621b247930e9a378815c176604c564f63081b70ee259315 +**********************************************************************/ import com.foxx.androidcast.network.control.NetworkStatsSnapshot; /** Copies {@link TransportLossStats} into {@link NetworkStatsSnapshot} for overlay / heartbeat. */ diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/TransportStatsProvider.java b/app/src/main/java/com/foxx/androidcast/network/transport/TransportStatsProvider.java index 002e0d9..551abb9 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/TransportStatsProvider.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/TransportStatsProvider.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * TransportStatsProvider.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * interface TransportStatsProvider + * Contributors: + * - Anton Afanasyeu (1 commits, 6 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 84c4d36433f474f2e5ea5f31f2194895f08ecbfc7270c64cc55e3825496b8e0f +**********************************************************************/ /** Transports that expose {@link TransportLossStats}. */ public interface TransportStatsProvider { TransportLossStats getLossStats(); diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecEncodedGroup.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecEncodedGroup.java index 9f8a6ac..40a9875 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecEncodedGroup.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecEncodedGroup.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * FecEncodedGroup.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class FecEncodedGroup + * Contributors: + * - Anton Afanasyeu (1 commits, 25 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 26c542f5247a4b547d6a3bc55f5d6211bb92c8a5aa977680ea21f5b19f53b97f +**********************************************************************/ /** Reed–Solomon shards ready for per-datagram transmission. */ public final class FecEncodedGroup { public final byte mode; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardReassembly.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardReassembly.java index 0cbf7db..af73899 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardReassembly.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardReassembly.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * FecShardReassembly.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class FecShardReassembly + * Contributors: + * - Anton Afanasyeu (1 commits, 86 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 553d2646d5f0180f58519d94eac7e9fa9537a4ac12ae9a8049a9a722a7f79001 +**********************************************************************/ import java.util.Arrays; /** Collects per-datagram FEC shards until Reed–Solomon decode succeeds. */ diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardWire.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardWire.java index b9bca7b..42b164a 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardWire.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/FecShardWire.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * FecShardWire.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class FecShardWire + * Contributors: + * - Anton Afanasyeu (2 commits, 135 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a6e8fb37a7d8551159d846d51392109da739e17dd7aa5e7315e11c74eff57565 +**********************************************************************/ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/GaloisField.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/GaloisField.java index bae9745..baa554b 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/GaloisField.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/GaloisField.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * GaloisField.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 64 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3526aef418e90173731524354d50d9333f8f2de663c19aadf4f555c0d64327f8 +**********************************************************************/ /** GF(2^8) arithmetic for Reed-Solomon. */ final class GaloisField { private static final int[] EXP = new int[512]; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/ProtectionEnvelope.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/ProtectionEnvelope.java index a27b0c2..ad37c06 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/ProtectionEnvelope.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/ProtectionEnvelope.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * ProtectionEnvelope.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class ProtectionEnvelope + * Contributors: + * - Anton Afanasyeu (1 commits, 151 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5c74e0c64d1239e5d5e5f1b1d55c1a6448a420c70ef5eaa2683da43ee218e697 +**********************************************************************/ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; diff --git a/app/src/main/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFec.java b/app/src/main/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFec.java index 8b9481f..38f8640 100644 --- a/app/src/main/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFec.java +++ b/app/src/main/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFec.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * ReedSolomonFec.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class ReedSolomonFec + * Contributors: + * - Anton Afanasyeu (1 commits, 175 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0802b2891a59368244337769d722cfe858b9eaaa576f503d2c2d910cf542cd96 +**********************************************************************/ import java.util.Arrays; /** diff --git a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcCastTransport.java b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcCastTransport.java index 79cf591..4fa0845 100644 --- a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcCastTransport.java +++ b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcCastTransport.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.webrtc; +/********************************************************************* + * WebRtcCastTransport.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * interface WebRtcCastTransport + * Contributors: + * - Anton Afanasyeu (1 commits, 62 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8108b951dfede7247d7f684e7118ac8e83963d27c59c810f5c894386c33dd05f +**********************************************************************/ import com.foxx.androidcast.network.CastProtocol; import com.foxx.androidcast.network.CastTransport; diff --git a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcPeerAdapter.java b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcPeerAdapter.java index fdacb5e..9f36871 100644 --- a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcPeerAdapter.java +++ b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcPeerAdapter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.webrtc; +/********************************************************************* + * WebRtcPeerAdapter.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * interface WebRtcPeerAdapter + * Contributors: + * - Anton Afanasyeu (1 commits, 37 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 148a9946f4c76155c7cbc5dee7253839f18c78cc72046387c146dbd463c7ce74 +**********************************************************************/ /** * Abstraction over future {@code org.webrtc.PeerConnection} or pion peer APIs. * Implementations will map cast frames to SCTP DataChannel or encoded tracks. diff --git a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcTransportFactory.java b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcTransportFactory.java index 8aec38f..a5aa246 100644 --- a/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcTransportFactory.java +++ b/app/src/main/java/com/foxx/androidcast/network/webrtc/WebRtcTransportFactory.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.webrtc; +/********************************************************************* + * WebRtcTransportFactory.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class WebRtcTransportFactory + * Contributors: + * - Anton Afanasyeu (1 commits, 19 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 fd79fe0ba81323ac4b2d0ea0c45d4a1f69240aaa4bc88052c5831661ea0a5990 +**********************************************************************/ import com.foxx.androidcast.CastConfig; import com.foxx.androidcast.network.CastTransport; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaApkInstaller.java b/app/src/main/java/com/foxx/androidcast/ota/OtaApkInstaller.java index a599a23..29bbd00 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaApkInstaller.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaApkInstaller.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaApkInstaller.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaApkInstaller + * Contributors: + * - Anton Afanasyeu (1 commits, 123 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6682b40f72d4e32a56c0085e591f65ba0691f82542540961c5da0aab19d88a88 +**********************************************************************/ import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -28,9 +38,21 @@ public final class OtaApkInstaller { private OtaApkInstaller() {} + /** Resolves a verified APK: HTTP bundle when present, else legacy per-artifact download. */ public static File downloadApk(Context context, OtaManifest manifest, ProgressListener listener) throws Exception { - if (manifest == null || manifest.apkUrl.isEmpty()) { + if (manifest == null) { + throw new IllegalArgumentException("Missing manifest"); + } + if (manifest.hasHttpBundle()) { + return OtaBundleInstaller.downloadApkFromBundle(context, manifest, listener); + } + return downloadApkLegacy(context, manifest, listener); + } + + static File downloadApkLegacy(Context context, OtaManifest manifest, ProgressListener listener) + throws Exception { + if (manifest.apkUrl.isEmpty()) { throw new IllegalArgumentException("Missing apkUrl"); } File dir = new File(context.getCacheDir(), "ota"); diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaBundleInstaller.java b/app/src/main/java/com/foxx/androidcast/ota/OtaBundleInstaller.java new file mode 100644 index 0000000..f484d41 --- /dev/null +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaBundleInstaller.java @@ -0,0 +1,184 @@ +package com.foxx.androidcast.ota; + +/********************************************************************* + * OtaBundleInstaller.java + * Created at: Wed 20 May 2026 15:15:10 +0200 + * Updated at: Wed 20 May 2026 15:15:10 +0200 by Cursor Agent + * class OtaBundleInstaller + * Contributors: + * - Cursor Agent (project assistant) + * Digest: SHA256 5c17ea3c41608a428c736c8a8657c28a4f8f21d0e2f699283138e96b52e6f176 +**********************************************************************/ +import android.content.Context; +import android.util.Log; + +import org.json.JSONObject; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * Downloads an optional {@code .otabundle.zip} (STORE entries: manifest.json, sign.json, + * package.apk) and returns a verified local APK file. + */ +public final class OtaBundleInstaller { + private static final String TAG = "OtaBundleInstaller"; + static final String ENTRY_MANIFEST = "manifest.json"; + static final String ENTRY_SIGN = "sign.json"; + static final String ENTRY_PACKAGE = "package.apk"; + + private static final int CONNECT_TIMEOUT_MS = 15_000; + private static final int READ_TIMEOUT_MS = 300_000; + private static final int MAX_BUNDLE_BYTES = 512 * 1024 * 1024; + + private OtaBundleInstaller() {} + + public static File downloadApkFromBundle(Context context, OtaManifest manifest, + OtaApkInstaller.ProgressListener listener) throws Exception { + if (manifest == null || !manifest.hasHttpBundle()) { + throw new IllegalArgumentException("Missing HTTP bundleUrl"); + } + File cacheRoot = new File(context.getCacheDir(), "ota"); + if (!cacheRoot.exists() && !cacheRoot.mkdirs()) { + throw new IllegalStateException("Cannot create OTA cache dir"); + } + int version = manifest.effectiveVersionCode(); + File bundleZip = new File(cacheRoot, "bundle-" + version + ".otabundle.zip"); + File extractDir = new File(cacheRoot, "bundle-" + version); + deleteRecursive(extractDir); + if (bundleZip.exists() && !bundleZip.delete()) { + throw new IllegalStateException("Cannot replace cached bundle"); + } + downloadBundleZip(manifest, bundleZip, listener); + if (!manifest.bundleSha256Hex.isEmpty()) { + String actual = OtaApkInstaller.sha256Hex(bundleZip); + if (!manifest.bundleSha256Hex.equalsIgnoreCase(actual)) { + bundleZip.delete(); + throw new IllegalStateException("Bundle checksum mismatch"); + } + } + if (!extractDir.mkdirs()) { + throw new IllegalStateException("Cannot create bundle extract dir"); + } + unzipBundle(bundleZip, extractDir); + File apk = new File(extractDir, ENTRY_PACKAGE); + if (!apk.isFile()) { + throw new IllegalStateException("Bundle missing " + ENTRY_PACKAGE); + } + String expectedSha = manifest.sha256Hex; + if (expectedSha.isEmpty()) { + File signFile = new File(extractDir, ENTRY_SIGN); + if (signFile.isFile()) { + try (FileInputStream fis = new FileInputStream(signFile)) { + byte[] buf = fis.readAllBytes(); + OtaSignBundle sign = OtaSignBundle.fromJson( + new JSONObject(new String(buf, StandardCharsets.UTF_8))); + expectedSha = sign.sha256Hex; + } + } + } + if (!expectedSha.isEmpty()) { + String actualApk = OtaApkInstaller.sha256Hex(apk); + if (!expectedSha.equalsIgnoreCase(actualApk)) { + deleteRecursive(extractDir); + throw new IllegalStateException("APK checksum mismatch (bundle)"); + } + } + Log.i(TAG, "Extracted bundle APK " + apk.length() + " bytes"); + return apk; + } + + private static void downloadBundleZip(OtaManifest manifest, File out, + OtaApkInstaller.ProgressListener listener) throws Exception { + HttpURLConnection conn = (HttpURLConnection) new URL(manifest.bundleUrl).openConnection(); + conn.setConnectTimeout(CONNECT_TIMEOUT_MS); + conn.setReadTimeout(READ_TIMEOUT_MS); + conn.setInstanceFollowRedirects(true); + int code = conn.getResponseCode(); + if (code < 200 || code >= 300) { + conn.disconnect(); + throw new IllegalStateException("Bundle download HTTP " + code); + } + long total = manifest.bundleSizeBytes > 0L + ? manifest.bundleSizeBytes + : conn.getContentLengthLong(); + if (total > MAX_BUNDLE_BYTES) { + conn.disconnect(); + throw new IllegalStateException("Bundle too large"); + } + try (InputStream in = new BufferedInputStream(conn.getInputStream()); + FileOutputStream fos = new FileOutputStream(out)) { + byte[] buf = new byte[32 * 1024]; + long downloaded = 0; + int n; + while ((n = in.read(buf)) != -1) { + downloaded += n; + if (downloaded > MAX_BUNDLE_BYTES) { + throw new IllegalStateException("Bundle exceeds size limit"); + } + fos.write(buf, 0, n); + if (listener != null) { + listener.onProgress(downloaded, total > 0 ? total : downloaded); + } + } + } finally { + conn.disconnect(); + } + Log.i(TAG, "Downloaded bundle " + out.length() + " bytes"); + } + + static void unzipBundle(File zipFile, File destDir) throws Exception { + try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream( + new FileInputStream(zipFile)))) { + ZipEntry entry; + byte[] buf = new byte[8192]; + while ((entry = zis.getNextEntry()) != null) { + if (entry.isDirectory()) { + continue; + } + String name = entry.getName(); + int slash = name.lastIndexOf('/'); + if (slash >= 0) { + name = name.substring(slash + 1); + } + if (!ENTRY_MANIFEST.equals(name) && !ENTRY_SIGN.equals(name) + && !ENTRY_PACKAGE.equals(name)) { + continue; + } + File out = new File(destDir, name); + try (BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(out))) { + int n; + while ((n = zis.read(buf)) != -1) { + bos.write(buf, 0, n); + } + } + zis.closeEntry(); + } + } + } + + static void deleteRecursive(File file) { + if (file == null || !file.exists()) { + return; + } + if (file.isDirectory()) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + deleteRecursive(child); + } + } + } + file.delete(); + } +} diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaChannelPointer.java b/app/src/main/java/com/foxx/androidcast/ota/OtaChannelPointer.java index f2c86b9..b7f46e9 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaChannelPointer.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaChannelPointer.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaChannelPointer.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaChannelPointer + * Contributors: + * - Anton Afanasyeu (1 commits, 23 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6aed382703256fd3aaa07d4d41e4f2e957e74ee006a2194115ba620227599207 +**********************************************************************/ import org.json.JSONObject; /** Default-channel entry ({@code v0/ota/channel/stable.json}). */ diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaJsonFetch.java b/app/src/main/java/com/foxx/androidcast/ota/OtaJsonFetch.java index 2efb3c0..84deb8e 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaJsonFetch.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaJsonFetch.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaJsonFetch.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 116 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 fb5df09d6e63f506add8f8c645da557091ed3b03948e1c036ab11b94120a1f48 +**********************************************************************/ import org.json.JSONObject; import java.io.BufferedInputStream; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaManifest.java b/app/src/main/java/com/foxx/androidcast/ota/OtaManifest.java index 11c035b..e1c939e 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaManifest.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaManifest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaManifest.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaManifest + * Contributors: + * - Anton Afanasyeu (1 commits, 128 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 9876faf3b24922b0737a168c8c7230f52bb1e6e1bb1d1444c59bb3acfa202f2f +**********************************************************************/ import android.text.TextUtils; import org.json.JSONException; @@ -17,14 +27,27 @@ public final class OtaManifest { public final String versionName; public final String apkUrl; public final String signUrl; + /** SHA-256 of {@code package.apk} inside the bundle or standalone {@code .otapkg}. */ public final String sha256Hex; public final long packageSizeBytes; public final boolean mandatory; public final String releaseNotes; + /** Optional HTTP(S) zip bundle ({@code manifest.json}, {@code sign.json}, {@code package.apk}). */ + public final String bundleUrl; + public final String bundleSha256Hex; + public final long bundleSizeBytes; public OtaManifest(int major, int minor, int build, int versionCode, String versionName, String apkUrl, String signUrl, String sha256Hex, long packageSizeBytes, boolean mandatory, String releaseNotes) { + this(major, minor, build, versionCode, versionName, apkUrl, signUrl, sha256Hex, + packageSizeBytes, mandatory, releaseNotes, "", "", 0L); + } + + public OtaManifest(int major, int minor, int build, int versionCode, String versionName, + String apkUrl, String signUrl, String sha256Hex, long packageSizeBytes, + boolean mandatory, String releaseNotes, String bundleUrl, String bundleSha256Hex, + long bundleSizeBytes) { this.major = major; this.minor = minor; this.build = build; @@ -36,6 +59,9 @@ public final class OtaManifest { this.packageSizeBytes = Math.max(0L, packageSizeBytes); this.mandatory = mandatory; this.releaseNotes = releaseNotes != null ? releaseNotes : ""; + this.bundleUrl = bundleUrl != null ? bundleUrl : ""; + this.bundleSha256Hex = bundleSha256Hex != null ? bundleSha256Hex.toLowerCase() : ""; + this.bundleSizeBytes = Math.max(0L, bundleSizeBytes); } public boolean hasVersionTriple() { @@ -59,8 +85,22 @@ public final class OtaManifest { return String.valueOf(versionCode); } + /** HTTP(S) bundle download is preferred over separate artifact fetches. */ + public boolean hasHttpBundle() { + return !bundleUrl.isEmpty() && OtaJsonFetch.isHttpUrl(bundleUrl); + } + + /** Size shown in the update dialog (bundle zip when applicable). */ + public long downloadSizeBytes() { + if (hasHttpBundle() && bundleSizeBytes > 0L) { + return bundleSizeBytes; + } + return packageSizeBytes; + } + public boolean isValid() { - return !apkUrl.isEmpty() && effectiveVersionCode() > 0; + return effectiveVersionCode() > 0 + && (!apkUrl.isEmpty() || hasHttpBundle()); } public static OtaManifest fromJson(JSONObject root) { @@ -78,7 +118,10 @@ public final class OtaManifest { root.optString("sha256", ""), root.optLong("sizeBytes", 0L), root.optBoolean("mandatory", false), - root.optString("releaseNotes", "")); + root.optString("releaseNotes", ""), + root.optString("bundleUrl", ""), + root.optString("bundleSha256", ""), + root.optLong("bundleSizeBytes", 0L)); } public static OtaManifest fromJsonString(String json) { @@ -115,6 +158,15 @@ public final class OtaManifest { if (packageSizeBytes > 0) { o.put("sizeBytes", packageSizeBytes); } + if (!bundleUrl.isEmpty()) { + o.put("bundleUrl", bundleUrl); + } + if (!bundleSha256Hex.isEmpty()) { + o.put("bundleSha256", bundleSha256Hex); + } + if (bundleSizeBytes > 0) { + o.put("bundleSizeBytes", bundleSizeBytes); + } o.put("mandatory", mandatory); o.put("releaseNotes", releaseNotes); return o; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaMqttFetch.java b/app/src/main/java/com/foxx/androidcast/ota/OtaMqttFetch.java index 420ca63..22f9d67 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaMqttFetch.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaMqttFetch.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaMqttFetch.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 114 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cdacc7e68102160a95336578000f9ad828b901812d3d464109cdd4cfea8e9806 +**********************************************************************/ import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaRuntimeSettings.java b/app/src/main/java/com/foxx/androidcast/ota/OtaRuntimeSettings.java index 733c995..9cbb6bd 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaRuntimeSettings.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaRuntimeSettings.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaRuntimeSettings.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaRuntimeSettings + * Contributors: + * - Anton Afanasyeu (1 commits, 20 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ff20558ef75f3e39b99d453750a4e45bab2bb3a537f746c1a5644643b7c65c69 +**********************************************************************/ import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaSettingsStore.java b/app/src/main/java/com/foxx/androidcast/ota/OtaSettingsStore.java index 4ff6570..d91117d 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaSettingsStore.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaSettingsStore.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaSettingsStore.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 189 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1a090c92a975ab23b7d7a6afdb6ce02cbd42b91420d0749372b37680c5be9129 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.AppPreferences; diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaSignBundle.java b/app/src/main/java/com/foxx/androidcast/ota/OtaSignBundle.java index 68d3269..eaaa24e 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaSignBundle.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaSignBundle.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaSignBundle.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaSignBundle + * Contributors: + * - Anton Afanasyeu (1 commits, 19 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 246d10a7e62d5f21162e672887c345186d51f974d5ddee6f234b0f536ec1be1d +**********************************************************************/ import org.json.JSONObject; /** Checksums and digests for one OTA build ({@code *_sign.json}). */ diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateChecker.java b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateChecker.java index 026adbd..821af87 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateChecker.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateChecker.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaUpdateChecker.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaUpdateChecker + * Contributors: + * - Anton Afanasyeu (1 commits, 134 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dabb50d5a774f59ee9dcb1bef81e4acd7899c58fb486f180b91927fff5a527eb +**********************************************************************/ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -68,13 +78,11 @@ public final class OtaUpdateChecker { return Result.error(normalized, "Invalid manifest JSON"); } if (!manifest.isValid()) { - return Result.error(normalized, "Manifest missing version or apkUrl"); + return Result.error(normalized, "Manifest missing version or download URL"); } manifest = enrichFromSignBundle(manifest, strictVerification); - long sizeBytes = manifest.packageSizeBytes > 0L - ? manifest.packageSizeBytes - : OtaJsonFetch.getContentLength(manifest.apkUrl); - if (sizeBytes > 0L && sizeBytes != manifest.packageSizeBytes) { + long sizeBytes = resolveDisplaySizeBytes(manifest); + if (sizeBytes > 0L) { manifest = new OtaManifest( manifest.major, manifest.minor, @@ -84,9 +92,12 @@ public final class OtaUpdateChecker { manifest.apkUrl, manifest.signUrl, manifest.sha256Hex, - sizeBytes, + manifest.hasHttpBundle() ? manifest.packageSizeBytes : sizeBytes, manifest.mandatory, - manifest.releaseNotes); + manifest.releaseNotes, + manifest.bundleUrl, + manifest.bundleSha256Hex, + manifest.hasHttpBundle() ? sizeBytes : manifest.bundleSizeBytes); } boolean available = OtaVersion.isUpdateAvailable( manifest.effectiveVersionCode(), installed); @@ -137,6 +148,26 @@ public final class OtaUpdateChecker { } return new OtaManifest(manifest.major, manifest.minor, manifest.build, manifest.versionCode, manifest.versionName, manifest.apkUrl, manifest.signUrl, sign.sha256Hex, - manifest.packageSizeBytes, manifest.mandatory, manifest.releaseNotes); + manifest.packageSizeBytes, manifest.mandatory, manifest.releaseNotes, + manifest.bundleUrl, manifest.bundleSha256Hex, manifest.bundleSizeBytes); + } + + static long resolveDisplaySizeBytes(OtaManifest manifest) throws Exception { + if (manifest.hasHttpBundle()) { + if (manifest.bundleSizeBytes > 0L) { + return manifest.bundleSizeBytes; + } + long len = OtaJsonFetch.getContentLength(manifest.bundleUrl); + if (len > 0L) { + return len; + } + } + if (manifest.packageSizeBytes > 0L) { + return manifest.packageSizeBytes; + } + if (!manifest.apkUrl.isEmpty()) { + return OtaJsonFetch.getContentLength(manifest.apkUrl); + } + return 0L; } } diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateCoordinator.java b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateCoordinator.java index 6c9b0c0..9148d11 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateCoordinator.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateCoordinator.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaUpdateCoordinator.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaUpdateCoordinator + * Contributors: + * - Anton Afanasyeu (1 commits, 128 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 153fce4c938a190612e24f788ae29927fb969e3a3ed8514acc3dc7f083a957d6 +**********************************************************************/ import android.app.Activity; import android.content.Context; import android.os.Bundle; @@ -104,8 +114,8 @@ public final class OtaUpdateCoordinator { : manifest.releaseNotes; String currentVersion = OtaUpdateChecker.installedVersionName(activity) + " (" + OtaUpdateChecker.installedVersionCode(activity) + ")"; - double sizeMb = manifest.packageSizeBytes > 0 - ? (manifest.packageSizeBytes / (1024.0 * 1024.0)) : 0.0; + double sizeMb = manifest.downloadSizeBytes() > 0 + ? (manifest.downloadSizeBytes() / (1024.0 * 1024.0)) : 0.0; String sizeText = sizeMb > 0 ? String.format(java.util.Locale.US, "%.2f", sizeMb) : "?"; String message = activity.getString(R.string.ota_update_message, manifest.displayVersion(), diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateService.java b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateService.java index ae0ba1f..ce5098a 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateService.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaUpdateService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaUpdateService.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaUpdateService + * Contributors: + * - Anton Afanasyeu (1 commits, 361 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 83b6e7e6dea20a90d53d1d30744c02afc7b4692449dbc9b70a197c5c071de814 +**********************************************************************/ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -284,7 +294,10 @@ public final class OtaUpdateService extends Service { "", manifest.packageSizeBytes, manifest.mandatory, - manifest.releaseNotes); + manifest.releaseNotes, + manifest.bundleUrl, + "", + manifest.bundleSizeBytes); } File apk = OtaApkInstaller.downloadApk(this, checkedManifest, (downloaded, total) -> { Notification n = buildDownloadNotification(downloaded, total, total <= 0); diff --git a/app/src/main/java/com/foxx/androidcast/ota/OtaVersion.java b/app/src/main/java/com/foxx/androidcast/ota/OtaVersion.java index 4d787fb..0386ed4 100644 --- a/app/src/main/java/com/foxx/androidcast/ota/OtaVersion.java +++ b/app/src/main/java/com/foxx/androidcast/ota/OtaVersion.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaVersion.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaVersion + * Contributors: + * - Anton Afanasyeu (1 commits, 49 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cb224d32ed84ff6056039bb968b429b1840e4c96fa213686caeebe930dc084e6 +**********************************************************************/ import com.foxx.androidcast.BuildConfig; /** major.minor.build packed the same way as Gradle {@code versionCode}. */ diff --git a/app/src/main/java/com/foxx/androidcast/receiver/AudioDecoder.java b/app/src/main/java/com/foxx/androidcast/receiver/AudioDecoder.java index 380d78a..b750afc 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/AudioDecoder.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/AudioDecoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * AudioDecoder.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class AudioDecoder + * Contributors: + * - Anton Afanasyeu (5 commits, 412 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f7bf70934a99b2da46a0e9063a8d0695bfccc5b7178308fdb9990e8a3b85002f +**********************************************************************/ import android.content.Context; import android.media.AudioAttributes; import android.media.AudioFormat; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/LibvpxVideoDecoder.java b/app/src/main/java/com/foxx/androidcast/receiver/LibvpxVideoDecoder.java index 2773c76..32ad0bc 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/LibvpxVideoDecoder.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/LibvpxVideoDecoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * LibvpxVideoDecoder.java + * Created at: Mon 18 May 2026 17:05:47 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class LibvpxVideoDecoder + * Contributors: + * - Anton Afanasyeu (2 commits, 89 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 17f03b3cb874bed8aeda4f9e04eca271d2ebaab138722da86f6278c7582d9219 +**********************************************************************/ import android.util.Log; import android.view.Surface; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/PlaybackViewState.java b/app/src/main/java/com/foxx/androidcast/receiver/PlaybackViewState.java index d8268a0..12b549b 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/PlaybackViewState.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/PlaybackViewState.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * PlaybackViewState.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class PlaybackViewState + * Contributors: + * - Anton Afanasyeu (1 commits, 21 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ce660967a5947203a6964e7d8e80867e268504c3bb4e7347355985559197efd6 +**********************************************************************/ /** Zoom/pan state for receiver diagnostics (updated from playback UI). */ public final class PlaybackViewState { private static volatile int zoomPercent; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverActivity.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverActivity.java index 3b27eb7..688a5fe 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverActivity.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * ReceiverActivity.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class ReceiverActivity + * Contributors: + * - Anton Afanasyeu (5 commits, 156 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 e964baa1b7ad23be67df455817ed504baa75a1bd159db8ea9ed85d808488fa1e +**********************************************************************/ import android.content.ComponentName; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java index f963577..e4c5232 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * ReceiverCastService.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class ReceiverCastService + * Contributors: + * - Anton Afanasyeu (17 commits, 1019 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7d81ff830ce741b1f520fb07418af465287df9a6c4849da70fee29b38d802263 +**********************************************************************/ import android.app.NotificationManager; import android.app.Service; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java index fb4f0d6..2e25c01 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * ReceiverPlaybackActivity.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class ReceiverPlaybackActivity + * Contributors: + * - Anton Afanasyeu (13 commits, 641 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 65c6a33bf17574ffe6c011e36cb4755d88f5866489fa959b8dd9482deffb2143 +**********************************************************************/ import android.content.ComponentName; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPrefs.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPrefs.java index 26039af..d0bea34 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPrefs.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPrefs.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * ReceiverPrefs.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Fri 15 May 2026 17:47:09 +0200 by Anton Afanasyeu + * class ReceiverPrefs + * Contributors: + * - Anton Afanasyeu (1 commits, 24 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a6c1daf09882bbd25c2aeda5fe2dd93532ee01ce3025bc8ba9e0789f15ddb66f +**********************************************************************/ import android.content.Context; import android.content.SharedPreferences; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverSession.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverSession.java index 9cb254f..bc7d541 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverSession.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverSession.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * ReceiverSession.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class ReceiverSession + * Contributors: + * - Anton Afanasyeu (11 commits, 319 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 daec1110a015b4809acd32710db9de074af512c46f724f06448c3cc7293d392a +**********************************************************************/ import android.util.Log; import android.content.Context; diff --git a/app/src/main/java/com/foxx/androidcast/receiver/StreamMetrics.java b/app/src/main/java/com/foxx/androidcast/receiver/StreamMetrics.java index c62727a..c9caa96 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/StreamMetrics.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/StreamMetrics.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * StreamMetrics.java + * Created at: Fri 15 May 2026 18:17:39 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class StreamMetrics + * Contributors: + * - Anton Afanasyeu (5 commits, 258 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 9adc31419aaf18c20d39d8155a5bdeb451cbcdc23a01f7681203905d85cffb23 +**********************************************************************/ import com.foxx.androidcast.network.control.NetworkStatsSnapshot; /** Receiver-side counters for diagnostics overlay and bandwidth estimates. */ diff --git a/app/src/main/java/com/foxx/androidcast/receiver/VideoDecoder.java b/app/src/main/java/com/foxx/androidcast/receiver/VideoDecoder.java index a84d58a..4c842bd 100644 --- a/app/src/main/java/com/foxx/androidcast/receiver/VideoDecoder.java +++ b/app/src/main/java/com/foxx/androidcast/receiver/VideoDecoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.receiver; +/********************************************************************* + * VideoDecoder.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class VideoDecoder + * Contributors: + * - Anton Afanasyeu (6 commits, 206 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5f5c706795090ba6ba3588024f217cefb7d8f733aec9a8865489d89c638b0f44 +**********************************************************************/ import android.media.MediaCodec; import android.media.MediaFormat; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/sender/AudioCapture.java b/app/src/main/java/com/foxx/androidcast/sender/AudioCapture.java index a4293bb..3c4d051 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/AudioCapture.java +++ b/app/src/main/java/com/foxx/androidcast/sender/AudioCapture.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * AudioCapture.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class AudioCapture + * Contributors: + * - Anton Afanasyeu (5 commits, 319 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dcd208fc064fb69a33ef9d0f113189357a9c36f4726bd1e112006be56dab4ac5 +**********************************************************************/ import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; diff --git a/app/src/main/java/com/foxx/androidcast/sender/AudioEncoder.java b/app/src/main/java/com/foxx/androidcast/sender/AudioEncoder.java index 771a5c4..2aef890 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/AudioEncoder.java +++ b/app/src/main/java/com/foxx/androidcast/sender/AudioEncoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * AudioEncoder.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class AudioEncoder + * Contributors: + * - Anton Afanasyeu (6 commits, 177 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b4bcd5f56604bfd8f645099bf2725741dea913ae413b21afadf527af6c474bd4 +**********************************************************************/ import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; diff --git a/app/src/main/java/com/foxx/androidcast/sender/CastFanoutPump.java b/app/src/main/java/com/foxx/androidcast/sender/CastFanoutPump.java index 6d932c7..e6ebe9c 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/CastFanoutPump.java +++ b/app/src/main/java/com/foxx/androidcast/sender/CastFanoutPump.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * CastFanoutPump.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class CastFanoutPump + * Contributors: + * - Anton Afanasyeu (3 commits, 186 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c14a7adbbf46d384d7243a1420b0f8c77faa95567ecd547de459cce4e7026393 +**********************************************************************/ import android.util.Log; import com.foxx.androidcast.network.CastProtocol; diff --git a/app/src/main/java/com/foxx/androidcast/sender/CastReceiverTarget.java b/app/src/main/java/com/foxx/androidcast/sender/CastReceiverTarget.java index 8be863d..7fb2301 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/CastReceiverTarget.java +++ b/app/src/main/java/com/foxx/androidcast/sender/CastReceiverTarget.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * CastReceiverTarget.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class CastReceiverTarget + * Contributors: + * - Anton Afanasyeu (1 commits, 29 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 199a71f729016db131a422923ed572bf936e1ece58b9abccdb0de133c64f4999 +**********************************************************************/ import java.io.Serializable; /** One cast destination (host, port, capabilities from discovery). */ diff --git a/app/src/main/java/com/foxx/androidcast/sender/CastSendPump.java b/app/src/main/java/com/foxx/androidcast/sender/CastSendPump.java index 4231c10..e9e22ab 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/CastSendPump.java +++ b/app/src/main/java/com/foxx/androidcast/sender/CastSendPump.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * CastSendPump.java + * Created at: Fri 15 May 2026 18:37:53 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class CastSendPump + * Contributors: + * - Anton Afanasyeu (6 commits, 188 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 28e82a800130d851f3d42c2ca733bdd7017a4238c11dfa88855a2bfd6e96918f +**********************************************************************/ import android.util.Log; import com.foxx.androidcast.network.CastProtocol; diff --git a/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java b/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java index f1cdc73..6f3ded4 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java +++ b/app/src/main/java/com/foxx/androidcast/sender/CodecCatalog.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * CodecCatalog.java + * Created at: Fri 15 May 2026 20:37:44 +0200 + * Updated at: Mon 18 May 2026 19:06:56 +0200 by Anton Afanasyeu + * class CodecCatalog + * Contributors: + * - Anton Afanasyeu (5 commits, 288 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d8c78d7980e97e5b57e8719bb016a0e72ed6a60cb7b1df1712b30c3349525a16 +**********************************************************************/ import android.media.MediaCodecInfo; import android.media.MediaCodecList; import android.media.MediaFormat; diff --git a/app/src/main/java/com/foxx/androidcast/sender/DeviceListAdapter.java b/app/src/main/java/com/foxx/androidcast/sender/DeviceListAdapter.java index 3a97816..aabfd1f 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/DeviceListAdapter.java +++ b/app/src/main/java/com/foxx/androidcast/sender/DeviceListAdapter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * DeviceListAdapter.java + * Created at: Fri 15 May 2026 17:47:09 +0200 + * Updated at: Mon 18 May 2026 17:46:19 +0200 by Anton Afanasyeu + * class DeviceListAdapter + * Contributors: + * - Anton Afanasyeu (4 commits, 123 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f2a6ec3b8f64c45f0cb27e7a4574793be08a73a54aa134a0f3927adffb85303e +**********************************************************************/ import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; diff --git a/app/src/main/java/com/foxx/androidcast/sender/EncoderKeepalive.java b/app/src/main/java/com/foxx/androidcast/sender/EncoderKeepalive.java index e2747c3..700d684 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/EncoderKeepalive.java +++ b/app/src/main/java/com/foxx/androidcast/sender/EncoderKeepalive.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * EncoderKeepalive.java + * Created at: Fri 15 May 2026 20:37:44 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class EncoderKeepalive + * Contributors: + * - Anton Afanasyeu (3 commits, 55 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cac57a14101810b9568aec381154a2b53184d0fc27792375ca21961c3774c76f +**********************************************************************/ import android.os.Handler; import android.os.Looper; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/sender/MultiCastCoordinator.java b/app/src/main/java/com/foxx/androidcast/sender/MultiCastCoordinator.java index 5014c65..5e4ed5f 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/MultiCastCoordinator.java +++ b/app/src/main/java/com/foxx/androidcast/sender/MultiCastCoordinator.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * MultiCastCoordinator.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class MultiCastCoordinator + * Contributors: + * - Anton Afanasyeu (7 commits, 264 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8cb8c4e79c55618777e7b027e06a4fb1692fffd35686a58a68700e5d25b35806 +**********************************************************************/ import android.content.Context; import android.util.Log; diff --git a/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java b/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java index bcc7665..94c9d5b 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java +++ b/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * ScreenCastService.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class ScreenCastService + * Contributors: + * - Anton Afanasyeu (17 commits, 1124 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2d9a6eb2c484afcce0448f518947d328ad3381759cd34124184652d754cbc82e +**********************************************************************/ import android.app.Service; import android.content.Intent; import android.content.pm.ServiceInfo; diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderActivity.java b/app/src/main/java/com/foxx/androidcast/sender/SenderActivity.java index dc2c83c..5592af2 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderActivity.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderActivity.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class SenderActivity + * Contributors: + * - Anton Afanasyeu (10 commits, 523 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 54d7724bae7604e074c874b2b0e4f579dd4ec6768048616f44d35925ed26bcfb +**********************************************************************/ import android.app.Activity; import android.content.Intent; import android.media.projection.MediaProjectionConfig; diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderAudioMetrics.java b/app/src/main/java/com/foxx/androidcast/sender/SenderAudioMetrics.java index 16e1b43..5264091 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderAudioMetrics.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderAudioMetrics.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderAudioMetrics.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class SenderAudioMetrics + * Contributors: + * - Anton Afanasyeu (1 commits, 61 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b55fe36dfceac83d619dde0950f39a7fd6eb36d96185fb4e8dee2ad720c063c0 +**********************************************************************/ import com.foxx.androidcast.media.PcmLevelAnalyzer; /** Pre-encode PCM level stats on the sender. */ diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderCapturePreview.java b/app/src/main/java/com/foxx/androidcast/sender/SenderCapturePreview.java index 9dcfe22..bf6e159 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderCapturePreview.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderCapturePreview.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderCapturePreview.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class SenderCapturePreview + * Contributors: + * - Anton Afanasyeu (3 commits, 301 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 847d3bd64e72df1966e209c76cc86d2116913f9b081e6b0f69aa959fff46ec63 +**********************************************************************/ import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderPreviewService.java b/app/src/main/java/com/foxx/androidcast/sender/SenderPreviewService.java index 5fd649f..20857e7 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderPreviewService.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderPreviewService.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderPreviewService.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class SenderPreviewService + * Contributors: + * - Anton Afanasyeu (1 commits, 64 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7ca6c54ac895e148148828a79ad8de959869d15cd9f1ad1a0eb3db39cad0ae53 +**********************************************************************/ import android.app.Service; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderScreenPreview.java b/app/src/main/java/com/foxx/androidcast/sender/SenderScreenPreview.java index 0941f85..36476d9 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderScreenPreview.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderScreenPreview.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderScreenPreview.java + * Created at: Sun 17 May 2026 18:17:14 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class SenderScreenPreview + * Contributors: + * - Anton Afanasyeu (3 commits, 212 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dd9db6f007b623cbeb04bba1896652adfcab6794bb8ded3ca366661022d8e2ac +**********************************************************************/ import android.app.Activity; import android.content.Context; import android.content.Intent; diff --git a/app/src/main/java/com/foxx/androidcast/sender/SenderStreamMetrics.java b/app/src/main/java/com/foxx/androidcast/sender/SenderStreamMetrics.java index aecd2d4..7d1cc98 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/SenderStreamMetrics.java +++ b/app/src/main/java/com/foxx/androidcast/sender/SenderStreamMetrics.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * SenderStreamMetrics.java + * Created at: Fri 15 May 2026 20:37:44 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class SenderStreamMetrics + * Contributors: + * - Anton Afanasyeu (2 commits, 77 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 dc82118898b4cb47ee92db41e42d9bcf471fcb2eaf33e90f8aac7c85f2fe9d47 +**********************************************************************/ /** Sender-side encode/send counters for notification diagnostics. */ public final class SenderStreamMetrics { private long encodedFrames; diff --git a/app/src/main/java/com/foxx/androidcast/sender/VideoEncoder.java b/app/src/main/java/com/foxx/androidcast/sender/VideoEncoder.java index 01a88d4..d3e1c67 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/VideoEncoder.java +++ b/app/src/main/java/com/foxx/androidcast/sender/VideoEncoder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender; +/********************************************************************* + * VideoEncoder.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class VideoEncoder + * Contributors: + * - Anton Afanasyeu (7 commits, 272 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3255bf54ca8deb1dbdb9a12f5af0e6b79fcd9e12bfff29669dafbc7cc98a29d1 +**********************************************************************/ import android.graphics.Bitmap; import android.media.MediaCodec; import android.media.MediaCodecInfo; diff --git a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationCastDriver.java b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationCastDriver.java index db83713..4394f3a 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationCastDriver.java +++ b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationCastDriver.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender.calibration; +/********************************************************************* + * CalibrationCastDriver.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class CalibrationCastDriver + * Contributors: + * - Anton Afanasyeu (2 commits, 199 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cf78c710c75b6b1cea109a2b1c075a32fe6acda8eaafdb6ca8b8b6761bccbdeb +**********************************************************************/ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; diff --git a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationEglRenderer.java b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationEglRenderer.java index 53a3009..e3cfda0 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationEglRenderer.java +++ b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationEglRenderer.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.sender.calibration; +/********************************************************************* + * CalibrationEglRenderer.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 236 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7c5bed16581d90c6ffc993e87b8bf471d9fe2126a6b0d1520c4cda4565979fbe +**********************************************************************/ import android.graphics.Bitmap; import android.opengl.EGL14; import android.opengl.EGLConfig; diff --git a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensions.java b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensions.java index 053fc60..dfd9c11 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensions.java +++ b/app/src/main/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensions.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender.calibration; +/********************************************************************* + * CalibrationSourceDimensions.java + * Created at: Sun 17 May 2026 15:45:19 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class CalibrationSourceDimensions + * Contributors: + * - Anton Afanasyeu (1 commits, 61 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f8ed9ec55e79a6748c89ffe266ccd96ae9f1b5e7d9099a9673037b8e96d485bb +**********************************************************************/ import android.content.Context; import android.graphics.BitmapFactory; diff --git a/app/src/main/java/com/foxx/androidcast/sender/calibration/TvCalibrationGenerator.java b/app/src/main/java/com/foxx/androidcast/sender/calibration/TvCalibrationGenerator.java index b72f67f..967b401 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/calibration/TvCalibrationGenerator.java +++ b/app/src/main/java/com/foxx/androidcast/sender/calibration/TvCalibrationGenerator.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender.calibration; +/********************************************************************* + * TvCalibrationGenerator.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class TvCalibrationGenerator + * Contributors: + * - Anton Afanasyeu (2 commits, 166 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 91f187b1a6bced54927ee71071368d295fa76ac1a2be7fbb28e78a028f044b6c +**********************************************************************/ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; diff --git a/app/src/main/java/com/foxx/androidcast/sender/camera/CameraCastCapture.java b/app/src/main/java/com/foxx/androidcast/sender/camera/CameraCastCapture.java index 4e8976c..a043ffd 100644 --- a/app/src/main/java/com/foxx/androidcast/sender/camera/CameraCastCapture.java +++ b/app/src/main/java/com/foxx/androidcast/sender/camera/CameraCastCapture.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender.camera; +/********************************************************************* + * CameraCastCapture.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 18:17:14 +0200 by Anton Afanasyeu + * class CameraCastCapture + * Contributors: + * - Anton Afanasyeu (2 commits, 160 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 73eef53b1dc3d45a9ad382cb2f4a48dcdb41e5af06721ba88f03a8543dd149df +**********************************************************************/ import android.content.Context; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; diff --git a/app/src/main/java/com/foxx/androidcast/settings/AppSettingsJson.java b/app/src/main/java/com/foxx/androidcast/settings/AppSettingsJson.java index 8ab853d..28b46ba 100644 --- a/app/src/main/java/com/foxx/androidcast/settings/AppSettingsJson.java +++ b/app/src/main/java/com/foxx/androidcast/settings/AppSettingsJson.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.settings; +/********************************************************************* + * AppSettingsJson.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class AppSettingsJson + * Contributors: + * - Anton Afanasyeu (1 commits, 32 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f9604e97b5516a98cfe4045f7225257be1a486f8ecb49b3e0fee7804d60e81d9 +**********************************************************************/ import android.content.Context; import org.json.JSONObject; diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionEventJournal.java b/app/src/main/java/com/foxx/androidcast/stats/SessionEventJournal.java index 6dd3e33..82f934f 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/SessionEventJournal.java +++ b/app/src/main/java/com/foxx/androidcast/stats/SessionEventJournal.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionEventJournal.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 79 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bdcbdc4ec9eb6ea4e03470d561683d6d1d8f7d71bf3ab72b3fca4488962d0d69 +**********************************************************************/ import org.json.JSONArray; import org.json.JSONObject; diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsContext.java b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsContext.java index eba3eca..47f1cba 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsContext.java +++ b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsContext.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsContext.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class SessionStatsContext + * Contributors: + * - Anton Afanasyeu (2 commits, 74 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f9a324c0a51439b0e60ae67b3ee95fbd3c30d5c55dd1829bbae0e93082e1880f +**********************************************************************/ import android.content.Context; import java.util.concurrent.atomic.AtomicReference; diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsEventMapper.java b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsEventMapper.java index 3f7760c..ed72958 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsEventMapper.java +++ b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsEventMapper.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsEventMapper.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsEventMapper + * Contributors: + * - Anton Afanasyeu (1 commits, 44 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0cf9e6cd7052a7d0caf605829d7d9a49cb0d8cec7c4546375064f6f5c33b0630 +**********************************************************************/ import com.foxx.androidcast.network.CastProtocol; /** Maps cast protocol message types to session journal event types. */ diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java index aee177e..62bd22d 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java +++ b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsRecorder.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class SessionStatsRecorder + * Contributors: + * - Anton Afanasyeu (6 commits, 358 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bbaaffebe2258cc874f3863da673a23a51be5d68e3b52217814bb2eb863b1214 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.AppPreferences; diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsStore.java b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsStore.java index e3a94d7..a4665e2 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsStore.java +++ b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsStore.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsStore.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsStore + * Contributors: + * - Anton Afanasyeu (2 commits, 110 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bbe679457e1c206a3e3d61abdf85c260c44a721c1ff36101b274f130d7c7ef94 +**********************************************************************/ import android.content.Context; import com.foxx.androidcast.CastConfig; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/ChartTickHelper.java b/app/src/main/java/com/foxx/androidcast/stats/ui/ChartTickHelper.java index 61d55fd..2bad915 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/ChartTickHelper.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/ChartTickHelper.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * ChartTickHelper.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 79 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 01fff6847633832b6a1eb6e5a40fe2ecc9681ebca9e9a1c7877556b181ad41d0 +**********************************************************************/ import java.util.ArrayList; import java.util.List; import java.util.Locale; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionBarChartView.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionBarChartView.java index 776cae9..d00e614 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionBarChartView.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionBarChartView.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionBarChartView.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionBarChartView + * Contributors: + * - Anton Afanasyeu (1 commits, 110 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 376aa816ff1d0e09f5bd63454c1f63a0215b4e2d6c1a7a59b3c60f08be330ecd +**********************************************************************/ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionLineChartView.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionLineChartView.java index d19dcdb..f6e3405 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionLineChartView.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionLineChartView.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionLineChartView.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionLineChartView + * Contributors: + * - Anton Afanasyeu (1 commits, 481 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 78f208cc95a3c55f9c6bc761be1e9dbb9a4fdfb20a71b07bad3059ecf8445cb4 +**********************************************************************/ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionRecord.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionRecord.java index 8eabefb..decbcbd 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionRecord.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionRecord.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionRecord.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionRecord + * Contributors: + * - Anton Afanasyeu (1 commits, 228 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0cbd107918e1438f379c78ff86daa383f1994e593c944ed27c389aa7ff945c2d +**********************************************************************/ import org.json.JSONObject; import java.util.ArrayList; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsAnalyzerActivity.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsAnalyzerActivity.java index d322019..8098647 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsAnalyzerActivity.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsAnalyzerActivity.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionStatsAnalyzerActivity.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsAnalyzerActivity + * Contributors: + * - Anton Afanasyeu (1 commits, 182 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6c27d2acb82c3cca5aaabe976d33bb397bb4c43ac2c80545fe2e5a2e85ff9e27 +**********************************************************************/ import android.content.Intent; import android.net.Uri; import android.os.Bundle; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsListAdapter.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsListAdapter.java index 89b9eef..ecf0377 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsListAdapter.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsListAdapter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionStatsListAdapter.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * interface Listener + * Contributors: + * - Anton Afanasyeu (1 commits, 105 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 303f3eec4fbd9f792a206731f0620e5745c7312176ed522570787c78d6f5e8c7 +**********************************************************************/ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsParser.java b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsParser.java index 6d1b9fe..33e6001 100644 --- a/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsParser.java +++ b/app/src/main/java/com/foxx/androidcast/stats/ui/SessionStatsParser.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats.ui; +/********************************************************************* + * SessionStatsParser.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsParser + * Contributors: + * - Anton Afanasyeu (1 commits, 22 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6937b2e105160b45ff3a9bb09e2e93de982e5dc89b12cd48e5e120db82761c4f +**********************************************************************/ import org.json.JSONObject; import java.io.File; diff --git a/app/src/main/java/com/foxx/androidcast/ui/AspectRatioFrameLayout.java b/app/src/main/java/com/foxx/androidcast/ui/AspectRatioFrameLayout.java index bf3f6c5..a9f3f53 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/AspectRatioFrameLayout.java +++ b/app/src/main/java/com/foxx/androidcast/ui/AspectRatioFrameLayout.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * AspectRatioFrameLayout.java + * Created at: Fri 15 May 2026 16:49:02 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class AspectRatioFrameLayout + * Contributors: + * - Anton Afanasyeu (2 commits, 78 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f26d0ffbe6f475f4c9d75deadf5d0759b9031916aec97bc489859ceff2508e46 +**********************************************************************/ import android.content.Context; import android.util.AttributeSet; import android.widget.FrameLayout; diff --git a/app/src/main/java/com/foxx/androidcast/ui/PlaybackTextureTransform.java b/app/src/main/java/com/foxx/androidcast/ui/PlaybackTextureTransform.java index 80b05f6..835581b 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/PlaybackTextureTransform.java +++ b/app/src/main/java/com/foxx/androidcast/ui/PlaybackTextureTransform.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * PlaybackTextureTransform.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class PlaybackTextureTransform + * Contributors: + * - Anton Afanasyeu (1 commits, 41 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 730a6b0e0b8b09cedec725fc448ae23c954ac71824901459edb3fe25e589d1e3 +**********************************************************************/ import android.graphics.Matrix; import android.view.TextureView; diff --git a/app/src/main/java/com/foxx/androidcast/ui/SettingsEnumSpinner.java b/app/src/main/java/com/foxx/androidcast/ui/SettingsEnumSpinner.java index f539198..8ab37a5 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/SettingsEnumSpinner.java +++ b/app/src/main/java/com/foxx/androidcast/ui/SettingsEnumSpinner.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * SettingsEnumSpinner.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 22:19:39 +0200 by Anton Afanasyeu + * class SettingsEnumSpinner + * Contributors: + * - Anton Afanasyeu (2 commits, 114 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 726ac0939215915b4c5f4db8a62d4da985100c8dce988d06955a44e6702a7ef8 +**********************************************************************/ import android.content.Context; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/com/foxx/androidcast/ui/SettingsScoredArrayAdapter.java b/app/src/main/java/com/foxx/androidcast/ui/SettingsScoredArrayAdapter.java index 028897f..af9e2ff 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/SettingsScoredArrayAdapter.java +++ b/app/src/main/java/com/foxx/androidcast/ui/SettingsScoredArrayAdapter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * SettingsScoredArrayAdapter.java + * Created at: Mon 18 May 2026 22:19:39 +0200 + * Updated at: Mon 18 May 2026 22:19:39 +0200 by Anton Afanasyeu + * class SettingsScoredArrayAdapter + * Contributors: + * - Anton Afanasyeu (1 commits, 70 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c31072ae0af01528d4e527249ab0dbdf4e4a8d2b2a43b3cc3ff1631fa4290217 +**********************************************************************/ import android.content.Context; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/java/com/foxx/androidcast/ui/SettingsSpinnerDropdownStyle.java b/app/src/main/java/com/foxx/androidcast/ui/SettingsSpinnerDropdownStyle.java index b379487..cb18c7c 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/SettingsSpinnerDropdownStyle.java +++ b/app/src/main/java/com/foxx/androidcast/ui/SettingsSpinnerDropdownStyle.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * SettingsSpinnerDropdownStyle.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class SettingsSpinnerDropdownStyle + * Contributors: + * - Anton Afanasyeu (1 commits, 62 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 ea6eaf08187aeb12e6bd56eb40bfe0da56224f75d1487941cf5207359b0b63ab +**********************************************************************/ import android.graphics.Color; import android.graphics.Typeface; import android.view.View; diff --git a/app/src/main/java/com/foxx/androidcast/ui/SettingsStringArrayAdapter.java b/app/src/main/java/com/foxx/androidcast/ui/SettingsStringArrayAdapter.java index f33aee7..87c03ca 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/SettingsStringArrayAdapter.java +++ b/app/src/main/java/com/foxx/androidcast/ui/SettingsStringArrayAdapter.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * SettingsStringArrayAdapter.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Mon 18 May 2026 22:19:39 +0200 by Anton Afanasyeu + * class SettingsStringArrayAdapter + * Contributors: + * - Anton Afanasyeu (3 commits, 73 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 30d18d934f97bea9996aff3f5df54490b70a05a9a970902ab4357d9c63707f37 +**********************************************************************/ import android.content.Context; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/java/com/foxx/androidcast/ui/ZoomPanContainer.java b/app/src/main/java/com/foxx/androidcast/ui/ZoomPanContainer.java index 6ed77c4..31e33a0 100644 --- a/app/src/main/java/com/foxx/androidcast/ui/ZoomPanContainer.java +++ b/app/src/main/java/com/foxx/androidcast/ui/ZoomPanContainer.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * ZoomPanContainer.java + * Created at: Sat 16 May 2026 13:35:48 +0200 + * Updated at: Sat 16 May 2026 13:35:48 +0200 by Anton Afanasyeu + * class ZoomPanContainer + * Contributors: + * - Anton Afanasyeu (1 commits, 134 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b2a9eaa46434f9d4971692e0e92b6e892c1060b3f4d737c203af7dcf7d9f0511 +**********************************************************************/ import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; diff --git a/app/src/main/java/com/foxx/androidcast/util/CastBackgroundExecutor.java b/app/src/main/java/com/foxx/androidcast/util/CastBackgroundExecutor.java index ac2625a..656ee1a 100644 --- a/app/src/main/java/com/foxx/androidcast/util/CastBackgroundExecutor.java +++ b/app/src/main/java/com/foxx/androidcast/util/CastBackgroundExecutor.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.util; +/********************************************************************* + * CastBackgroundExecutor.java + * Created at: Sun 17 May 2026 15:45:19 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class CastBackgroundExecutor + * Contributors: + * - Anton Afanasyeu (1 commits, 27 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cb0eaf12c274325d0540565b840756d7a4e4cc128f05aab48b692f2488235e6d +**********************************************************************/ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; diff --git a/app/src/test/java/com/foxx/androidcast/CastResolutionTest.java b/app/src/test/java/com/foxx/androidcast/CastResolutionTest.java index f5543f5..69db36a 100644 --- a/app/src/test/java/com/foxx/androidcast/CastResolutionTest.java +++ b/app/src/test/java/com/foxx/androidcast/CastResolutionTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast; +/********************************************************************* + * CastResolutionTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class CastResolutionTest + * Contributors: + * - Anton Afanasyeu (2 commits, 19 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 54ee2dbb5d0f3ea47ba31f1e0b8d85030a43933ea7ec28cdfd7439d164bbf810 +**********************************************************************/ import com.foxx.androidcast.sender.calibration.CalibrationSourceDimensions; import org.junit.Test; diff --git a/app/src/test/java/com/foxx/androidcast/diagnostics/CastMtuSamplerTest.java b/app/src/test/java/com/foxx/androidcast/diagnostics/CastMtuSamplerTest.java index f7bddc3..36b829f 100644 --- a/app/src/test/java/com/foxx/androidcast/diagnostics/CastMtuSamplerTest.java +++ b/app/src/test/java/com/foxx/androidcast/diagnostics/CastMtuSamplerTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.diagnostics; +/********************************************************************* + * CastMtuSamplerTest.java + * Created at: Tue 19 May 2026 12:23:39 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class CastMtuSamplerTest + * Contributors: + * - Anton Afanasyeu (1 commits, 27 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 6a7e905e3cd593226895fef722f1c1c28ef3a9f12bc7f78d99f27859ff916114 +**********************************************************************/ import static org.junit.Assert.assertEquals; import com.foxx.androidcast.CastConfig; diff --git a/app/src/test/java/com/foxx/androidcast/discovery/DiscoverySelfFilterTest.java b/app/src/test/java/com/foxx/androidcast/discovery/DiscoverySelfFilterTest.java index 1bd76c9..2a6ee4a 100644 --- a/app/src/test/java/com/foxx/androidcast/discovery/DiscoverySelfFilterTest.java +++ b/app/src/test/java/com/foxx/androidcast/discovery/DiscoverySelfFilterTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.discovery; +/********************************************************************* + * DiscoverySelfFilterTest.java + * Created at: Sun 17 May 2026 15:45:19 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class DiscoverySelfFilterTest + * Contributors: + * - Anton Afanasyeu (1 commits, 21 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 86e357220fd41740dec4da1e6762f7fb7ff44c60bc39c9ffe57ecd8e09e58716 +**********************************************************************/ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/media/EncodedStreamProbeTest.java b/app/src/test/java/com/foxx/androidcast/media/EncodedStreamProbeTest.java index f2d9a9b..7e644b9 100644 --- a/app/src/test/java/com/foxx/androidcast/media/EncodedStreamProbeTest.java +++ b/app/src/test/java/com/foxx/androidcast/media/EncodedStreamProbeTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * EncodedStreamProbeTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class EncodedStreamProbeTest + * Contributors: + * - Anton Afanasyeu (1 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d22080bf28df926149e758f4c886e6a917de5a8e0be2dc14c94b4d30bb4c18c1 +**********************************************************************/ import static org.junit.Assert.assertTrue; import android.media.MediaFormat; diff --git a/app/src/test/java/com/foxx/androidcast/media/H264BitstreamHevcTest.java b/app/src/test/java/com/foxx/androidcast/media/H264BitstreamHevcTest.java index 88bcb03..d45da50 100644 --- a/app/src/test/java/com/foxx/androidcast/media/H264BitstreamHevcTest.java +++ b/app/src/test/java/com/foxx/androidcast/media/H264BitstreamHevcTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * H264BitstreamHevcTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class H264BitstreamHevcTest + * Contributors: + * - Anton Afanasyeu (1 commits, 16 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d811e0c348d2339390c98a6983952b933da9a592ff9c7b43350b6eb57cf9e682 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/media/RgbToNv21Test.java b/app/src/test/java/com/foxx/androidcast/media/RgbToNv21Test.java index a70c014..0ac366e 100644 --- a/app/src/test/java/com/foxx/androidcast/media/RgbToNv21Test.java +++ b/app/src/test/java/com/foxx/androidcast/media/RgbToNv21Test.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * RgbToNv21Test.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class RgbToNv21Test + * Contributors: + * - Anton Afanasyeu (1 commits, 34 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a753d55bdf4c807f92c8491375ac2d0fa827b101cb6196ea1a4d6c781152fb68 +**********************************************************************/ import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/app/src/test/java/com/foxx/androidcast/media/RgbToYuv420Test.java b/app/src/test/java/com/foxx/androidcast/media/RgbToYuv420Test.java index 7d50095..c4dd90e 100644 --- a/app/src/test/java/com/foxx/androidcast/media/RgbToYuv420Test.java +++ b/app/src/test/java/com/foxx/androidcast/media/RgbToYuv420Test.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.media; +/********************************************************************* + * RgbToYuv420Test.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class RgbToYuv420Test + * Contributors: + * - Anton Afanasyeu (1 commits, 25 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4e8d36e3cb5f40640edc6e90d9fc8f9f32bdce23ddb0b2a2d8d293f2936c009b +**********************************************************************/ import org.junit.Test; import static org.junit.Assert.assertNotEquals; diff --git a/app/src/test/java/com/foxx/androidcast/network/CastProtoHeaderTest.java b/app/src/test/java/com/foxx/androidcast/network/CastProtoHeaderTest.java index 0481fd4..ba73a23 100644 --- a/app/src/test/java/com/foxx/androidcast/network/CastProtoHeaderTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/CastProtoHeaderTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastProtoHeaderTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class CastProtoHeaderTest + * Contributors: + * - Anton Afanasyeu (1 commits, 34 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4026bd80ef13a3c3ca7e8133976d6428c761c7bc19bb62a3e2ac7346643a39dc +**********************************************************************/ import org.junit.Test; import static org.junit.Assert.assertArrayEquals; diff --git a/app/src/test/java/com/foxx/androidcast/network/CastSessionGateTest.java b/app/src/test/java/com/foxx/androidcast/network/CastSessionGateTest.java index 9a0dca5..a7e50f3 100644 --- a/app/src/test/java/com/foxx/androidcast/network/CastSessionGateTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/CastSessionGateTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * CastSessionGateTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sat 16 May 2026 18:50:36 +0200 by Anton Afanasyeu + * class CastSessionGateTest + * Contributors: + * - Anton Afanasyeu (1 commits, 49 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 c32c4ef66b912bca05b5af6cb877189769048259687011cb9aaf34454c75e28c +**********************************************************************/ import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportBackwardCompatTest.java b/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportBackwardCompatTest.java index 6848af4..07d56dd 100644 --- a/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportBackwardCompatTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportBackwardCompatTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * UdpCastTransportBackwardCompatTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class UdpCastTransportBackwardCompatTest + * Contributors: + * - Anton Afanasyeu (1 commits, 53 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 22ad9f1020f5bd753fa96b0a5249e92130d50af94311efb93a0d6a1a8c2525bc +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportFecTest.java b/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportFecTest.java index 0ad5c04..26858e8 100644 --- a/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportFecTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/UdpCastTransportFecTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network; +/********************************************************************* + * UdpCastTransportFecTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class UdpCastTransportFecTest + * Contributors: + * - Anton Afanasyeu (2 commits, 117 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 77c0d7d3585bc42d3b40fe1db3b1b400a0abc8980d4b6d18b54b1a3476a0e820 +**********************************************************************/ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/FecProtectionEngineShardTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/FecProtectionEngineShardTest.java index 33a8a24..3c53472 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/FecProtectionEngineShardTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/FecProtectionEngineShardTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * FecProtectionEngineShardTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class FecProtectionEngineShardTest + * Contributors: + * - Anton Afanasyeu (2 commits, 56 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 40f0a42dc09acfffed2a805dab7bc05e624fc7a204dfd0eba33da85e2e309501 +**********************************************************************/ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/NackRateLimiterTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/NackRateLimiterTest.java index 4af24a2..14d3734 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/NackRateLimiterTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/NackRateLimiterTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * NackRateLimiterTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class NackRateLimiterTest + * Contributors: + * - Anton Afanasyeu (1 commits, 25 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0d9ea1348bc9d1238d33ec7e6c5ffc04712e2a6ed369e8c8a61d42c49dc6b859 +**********************************************************************/ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionCompatTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionCompatTest.java index b16995d..ea540ee 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionCompatTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionCompatTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionCompatTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Mon 18 May 2026 14:25:02 +0200 by Anton Afanasyeu + * class StreamProtectionCompatTest + * Contributors: + * - Anton Afanasyeu (1 commits, 36 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0e6469f9b641b0c9e283fb20d72d4ee28b2c69a8cb38943d340984c0ed5c643e +**********************************************************************/ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionFactoryTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionFactoryTest.java index ed35222..cbae3b1 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionFactoryTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionFactoryTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionFactoryTest.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionFactoryTest + * Contributors: + * - Anton Afanasyeu (2 commits, 55 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 78db7652959223f21a4f351001f4c9240395b75eab254b2dcac152074bc47a49 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiatorTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiatorTest.java index 0479d58..cf9fc21 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiatorTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/StreamProtectionNegotiatorTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport; +/********************************************************************* + * StreamProtectionNegotiatorTest.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class StreamProtectionNegotiatorTest + * Contributors: + * - Anton Afanasyeu (2 commits, 110 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5dcc89dce4afdec1de723496f4276fa7e7a35991a4a8a197f1cfe209eb662d29 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardReassemblyTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardReassemblyTest.java index a338cef..5bbff8b 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardReassemblyTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardReassemblyTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * FecShardReassemblyTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class FecShardReassemblyTest + * Contributors: + * - Anton Afanasyeu (2 commits, 81 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 2f121c49deb742560b5c3acedc607865788872a84a49aa405836e0bb6d533c3f +**********************************************************************/ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardWireTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardWireTest.java index fe769ad..6abf5d5 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardWireTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/fec/FecShardWireTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * FecShardWireTest.java + * Created at: Mon 18 May 2026 14:25:02 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * class FecShardWireTest + * Contributors: + * - Anton Afanasyeu (2 commits, 70 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b9f547315efda46e7752450d424e96099dc0cb1889fe8228b380527b9229ae28 +**********************************************************************/ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; diff --git a/app/src/test/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFecTest.java b/app/src/test/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFecTest.java index 102b1df..4e890f9 100644 --- a/app/src/test/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFecTest.java +++ b/app/src/test/java/com/foxx/androidcast/network/transport/fec/ReedSolomonFecTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.network.transport.fec; +/********************************************************************* + * ReedSolomonFecTest.java + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * class ReedSolomonFecTest + * Contributors: + * - Anton Afanasyeu (1 commits, 59 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 5075686696c29640df2abe5e7b9b29df9625e49583c7f4d1cfaba10a37d1d65f +**********************************************************************/ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; diff --git a/app/src/test/java/com/foxx/androidcast/ota/OtaApkInstallerTest.java b/app/src/test/java/com/foxx/androidcast/ota/OtaApkInstallerTest.java index ee3a032..c3034eb 100644 --- a/app/src/test/java/com/foxx/androidcast/ota/OtaApkInstallerTest.java +++ b/app/src/test/java/com/foxx/androidcast/ota/OtaApkInstallerTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaApkInstallerTest.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaApkInstallerTest + * Contributors: + * - Anton Afanasyeu (1 commits, 23 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 928e47db96f21c0724998397acfa34ba00ad5a3373954a4812c2b6347eee9e07 +**********************************************************************/ import static org.junit.Assert.assertEquals; import org.junit.Test; diff --git a/app/src/test/java/com/foxx/androidcast/ota/OtaBundleInstallerTest.java b/app/src/test/java/com/foxx/androidcast/ota/OtaBundleInstallerTest.java new file mode 100644 index 0000000..67b02db --- /dev/null +++ b/app/src/test/java/com/foxx/androidcast/ota/OtaBundleInstallerTest.java @@ -0,0 +1,64 @@ +package com.foxx.androidcast.ota; + +/********************************************************************* + * OtaBundleInstallerTest.java + * Created at: Wed 20 May 2026 15:15:13 +0200 + * Updated at: Wed 20 May 2026 15:15:13 +0200 by Cursor Agent + * class OtaBundleInstallerTest + * Contributors: + * - Cursor Agent (project assistant) + * Digest: SHA256 b443d5cd08659a05999aba622deb4d8b888d37bb832e65120ab9eaddb06f99eb +**********************************************************************/ +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class OtaBundleInstallerTest { + @org.junit.Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Test + public void unzipBundle_extractsPackageApk() throws Exception { + File zip = tmp.newFile("test.otabundle.zip"); + byte[] apkBytes = "fake-apk".getBytes(StandardCharsets.UTF_8); + try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream( + new FileOutputStream(zip)))) { + writeStoredEntry(zos, OtaBundleInstaller.ENTRY_SIGN, + "{\"schema\":\"v0\",\"sha256\":\"deadbeef\"}"); + writeStoredEntry(zos, OtaBundleInstaller.ENTRY_PACKAGE, new String(apkBytes, StandardCharsets.UTF_8)); + } + File dest = tmp.newFolder("extract"); + OtaBundleInstaller.unzipBundle(zip, dest); + File apk = new File(dest, OtaBundleInstaller.ENTRY_PACKAGE); + assertTrue(apk.isFile()); + assertEquals(apkBytes.length, apk.length()); + } + + private static void writeStoredEntry(ZipOutputStream zos, String name, String body) + throws Exception { + ZipEntry e = new ZipEntry(name); + e.setMethod(ZipEntry.STORED); + byte[] data = body.getBytes(StandardCharsets.UTF_8); + e.setSize(data.length); + e.setCompressedSize(data.length); + e.setCrc(crc32(data)); + zos.putNextEntry(e); + zos.write(data); + zos.closeEntry(); + } + + private static long crc32(byte[] data) { + java.util.zip.CRC32 crc = new java.util.zip.CRC32(); + crc.update(data); + return crc.getValue(); + } +} diff --git a/app/src/test/java/com/foxx/androidcast/ota/OtaManifestTest.java b/app/src/test/java/com/foxx/androidcast/ota/OtaManifestTest.java index ac3c867..7dff862 100644 --- a/app/src/test/java/com/foxx/androidcast/ota/OtaManifestTest.java +++ b/app/src/test/java/com/foxx/androidcast/ota/OtaManifestTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaManifestTest.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaManifestTest + * Contributors: + * - Anton Afanasyeu (1 commits, 32 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 556f497b8a8c6e58841755e39a11f9c55b4a99b2fbc418bc373d4b8818d8d285 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -25,9 +35,25 @@ public class OtaManifestTest { } @Test - public void isValid_requiresApkUrlAndVersion() { + public void isValid_requiresDownloadTargetAndVersion() { assertFalse(new OtaManifest(0, 0, 0, 0, "", "", "", "", 0L, false, "").isValid()); assertTrue(new OtaManifest(0, 0, 1, 0, "", "https://x/a.apk", "", "", 0L, false, "") .isValid()); + OtaManifest bundleOnly = new OtaManifest(0, 1, 0, 0, "0.1.0", "", "", "abc", 0L, + false, "", "https://x/bundle.otabundle.zip", "def", 99L); + assertTrue(bundleOnly.isValid()); + assertTrue(bundleOnly.hasHttpBundle()); + assertEquals(99L, bundleOnly.downloadSizeBytes()); + } + + @Test + public void bundleFields_roundTripInConstructor() { + OtaManifest m = new OtaManifest(0, 1, 2, 0, "0.1.2", + "https://h/a.otapkg", "", "dead", 50L, false, "", + "https://h/a.otabundle.zip", "BEEF", 1000L); + assertEquals("https://h/a.otabundle.zip", m.bundleUrl); + assertEquals("beef", m.bundleSha256Hex); + assertEquals(1000L, m.bundleSizeBytes); + assertEquals(1000L, m.downloadSizeBytes()); } } diff --git a/app/src/test/java/com/foxx/androidcast/ota/OtaVersionTest.java b/app/src/test/java/com/foxx/androidcast/ota/OtaVersionTest.java index de29190..1d2cbe6 100644 --- a/app/src/test/java/com/foxx/androidcast/ota/OtaVersionTest.java +++ b/app/src/test/java/com/foxx/androidcast/ota/OtaVersionTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ota; +/********************************************************************* + * OtaVersionTest.java + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * class OtaVersionTest + * Contributors: + * - Anton Afanasyeu (1 commits, 26 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 4417a6f760b4c4a4fc19f8e302c9ff12d8163abde933ac439eb2dae27c10f585 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensionsTest.java b/app/src/test/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensionsTest.java index 5a98a72..78c1282 100644 --- a/app/src/test/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensionsTest.java +++ b/app/src/test/java/com/foxx/androidcast/sender/calibration/CalibrationSourceDimensionsTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.sender.calibration; +/********************************************************************* + * CalibrationSourceDimensionsTest.java + * Created at: Sun 17 May 2026 15:45:19 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class CalibrationSourceDimensionsTest + * Contributors: + * - Anton Afanasyeu (1 commits, 24 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b9587a4ce230a98f72fba276ef83e5c08ffa57597efefc92350302f271c21dcf +**********************************************************************/ import static org.junit.Assert.assertEquals; import com.foxx.androidcast.CastResolution; diff --git a/app/src/test/java/com/foxx/androidcast/stats/SessionStatsEventMapperTest.java b/app/src/test/java/com/foxx/androidcast/stats/SessionStatsEventMapperTest.java index 1039772..8b33259 100644 --- a/app/src/test/java/com/foxx/androidcast/stats/SessionStatsEventMapperTest.java +++ b/app/src/test/java/com/foxx/androidcast/stats/SessionStatsEventMapperTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsEventMapperTest.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsEventMapperTest + * Contributors: + * - Anton Afanasyeu (1 commits, 38 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8a3ace38f6f02e6827f2db0cffe7f8ef953de3c7a2598a0e38cb279456269484 +**********************************************************************/ import static org.junit.Assert.assertEquals; import com.foxx.androidcast.network.CastProtocol; diff --git a/app/src/test/java/com/foxx/androidcast/stats/SessionStatsStoreTest.java b/app/src/test/java/com/foxx/androidcast/stats/SessionStatsStoreTest.java index d5e3a40..cce22d2 100644 --- a/app/src/test/java/com/foxx/androidcast/stats/SessionStatsStoreTest.java +++ b/app/src/test/java/com/foxx/androidcast/stats/SessionStatsStoreTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.stats; +/********************************************************************* + * SessionStatsStoreTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStatsStoreTest + * Contributors: + * - Anton Afanasyeu (2 commits, 70 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 03c7cec2b65c676e4a743525b069a5ccac78904df58127c470f86b15271a43a8 +**********************************************************************/ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/app/src/test/java/com/foxx/androidcast/ui/PlaybackTextureTransformTest.java b/app/src/test/java/com/foxx/androidcast/ui/PlaybackTextureTransformTest.java index 93df8db..effdc59 100644 --- a/app/src/test/java/com/foxx/androidcast/ui/PlaybackTextureTransformTest.java +++ b/app/src/test/java/com/foxx/androidcast/ui/PlaybackTextureTransformTest.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.ui; +/********************************************************************* + * PlaybackTextureTransformTest.java + * Created at: Sat 16 May 2026 18:50:36 +0200 + * Updated at: Sun 17 May 2026 15:45:19 +0200 by Anton Afanasyeu + * class PlaybackTextureTransformTest + * Contributors: + * - Anton Afanasyeu (2 commits, 41 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bf16dafb719c89d716f5945fb356f35a17a3920000594bf57176fa8c6158018e +**********************************************************************/ import static org.junit.Assert.assertEquals; import org.junit.Test; diff --git a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/ChartTicks.java b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/ChartTicks.java index a8d3c76..0932040 100644 --- a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/ChartTicks.java +++ b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/ChartTicks.java @@ -1,5 +1,14 @@ package com.foxx.androidcast.studio; +/********************************************************************* + * ChartTicks.java + * Created at: Tue 19 May 2026 19:43:06 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 79 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 3742b3bf96491351681637e8d9208c0827ff8eb75e1cc87421792e73292c05b3 +**********************************************************************/ import java.util.ArrayList; import java.util.List; import java.util.Locale; diff --git a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionChartPane.java b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionChartPane.java index a428be0..a459560 100644 --- a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionChartPane.java +++ b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionChartPane.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.studio; +/********************************************************************* + * SessionChartPane.java + * Created at: Mon 18 May 2026 18:26:28 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionChartPane + * Contributors: + * - Anton Afanasyeu (2 commits, 437 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 88e24e0068b1b54ae5bbae7f1f2705c0a5ddcb4a09bf9969c292c1e28acb6165 +**********************************************************************/ import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.input.MouseEvent; diff --git a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionDocument.java b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionDocument.java index 5acbdd2..1d4120e 100644 --- a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionDocument.java +++ b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionDocument.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.studio; +/********************************************************************* + * SessionDocument.java + * Created at: Mon 18 May 2026 18:26:28 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionDocument + * Contributors: + * - Anton Afanasyeu (2 commits, 94 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 e6fbb284dfd0b410796567df776d245a25ab6f152a709cc582d557723911f34e +**********************************************************************/ import org.json.JSONArray; import org.json.JSONObject; diff --git a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionStudioApp.java b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionStudioApp.java index 248f322..438bfe2 100644 --- a/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionStudioApp.java +++ b/desktop/session-studio/src/main/java/com/foxx/androidcast/studio/SessionStudioApp.java @@ -1,5 +1,15 @@ package com.foxx.androidcast.studio; +/********************************************************************* + * SessionStudioApp.java + * Created at: Mon 18 May 2026 18:26:28 +0200 + * Updated at: Tue 19 May 2026 19:43:06 +0200 by Anton Afanasyeu + * class SessionStudioApp + * Contributors: + * - Anton Afanasyeu (2 commits, 147 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7579fea3417e33902e2decdd2da173933e04884e35a6e8ab727b8c263959d5c4 +**********************************************************************/ import javafx.application.Application; import javafx.collections.ListChangeListener; import javafx.scene.Scene; diff --git a/docs/OTA.md b/docs/OTA.md index d377635..4c215b3 100644 --- a/docs/OTA.md +++ b/docs/OTA.md @@ -1,8 +1,8 @@ # Over-the-air (OTA) updates — deployment schema **v0** -The app checks a **stable channel URL**, follows it to a per-build manifest, then downloads the APK. Version comparison uses **`major.minor.build`** (packed into Android `versionCode` at build time). Deploy never computes `versionCode` by hand. +The app checks a **stable channel URL**, follows it to a per-build manifest, then downloads the update. Version comparison uses **`major.minor.build`** (packed into Android `versionCode` at build time). Deploy never computes `versionCode` by hand. -The client runs checks and downloads in **`OtaUpdateService`** (a standalone `Service`, not embedded in cast/receiver services). Launch checks enqueue work there; APK download uses a **foreground service** (`dataSync`) with a progress notification. +The client runs checks and downloads in **`OtaUpdateService`** (a standalone `Service`, not embedded in cast/receiver services). Launch checks enqueue work there; download uses a **foreground service** (`dataSync`) with a progress notification. MQTT is fully supported for OTA sources using retained topic payloads (`mqtt://...` / `mqtts://...`). The URI path is treated as the exact topic to subscribe. @@ -13,6 +13,7 @@ https://host/v0/ota/channel/stable.json https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}.otapkg https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}_sign.json https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}_manifest.json +https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}.otabundle.zip ``` - **`v0`** — deployment schema version (default channel). @@ -59,6 +60,10 @@ Example: `0.1.5` → `versionCode` **105**. "versionName": "0.1.5", "apkUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05.otapkg", "signUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05_sign.json", + "sizeBytes": 42100000, + "bundleUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05.00.otabundle.zip", + "bundleSha256": "…", + "bundleSizeBytes": 42150000, "mandatory": false, "releaseNotes": "" } @@ -73,7 +78,23 @@ Example: `0.1.5` → `versionCode` **105**. } ``` -The app loads `sha256` from `sign.json` when the manifest omits it. +The app loads `sha256` from `sign.json` when the manifest omits it (APK hash inside the bundle or standalone `.otapkg`). + +## Optional HTTP bundle (`.otabundle.zip`) + +`generate-ota-v0.sh` emits a **STORE** (uncompressed) zip so the APK is not re-deflated: + +| Entry inside zip | Content | +|------------------|---------| +| `manifest.json` | Same as `*_manifest.json` | +| `sign.json` | Same as `*_sign.json` | +| `package.apk` | Release APK bytes | + +**Check path (lightweight):** channel → small `*_manifest.json` (+ optional `*_sign.json`) — no bundle download until the user installs. + +**Download path (HTTP):** if `bundleUrl` is `http`/`https`, the app downloads one zip, verifies `bundleSha256`, unpacks, verifies `package.apk` against `sha256`, then runs the installer. If `bundleUrl` is absent, it falls back to separate `apkUrl` / `signUrl` fetches (required for MQTT). + +**MQTT:** keep **per-artifact** retained topics (`manifest.json`, `sign.json`, `.otapkg`). Do not publish full bundles on MQTT (message size limits). The app ignores `bundleUrl` when the scheme is not HTTP(S). ## MQTT transport @@ -114,5 +135,5 @@ Legacy `ota.manifest.url` still works as a direct manifest URL fallback. 1. Bump `ota.major` / `ota.minor` / `ota.build` (or Gradle defaults). 2. Build signed release APK (`versionCode` is derived automatically). -3. Run `generate-ota-v0.sh` and upload `v0/ota/**`. +3. Run `generate-ota-v0.sh` and upload `v0/ota/**` (including `.otabundle.zip`). 4. Confirm `stable.json` points at the new `*_manifest.json`. diff --git a/examples/crash_reporter/backend/config/config.example.php b/examples/crash_reporter/backend/config/config.example.php index 1771604..2958d29 100644 --- a/examples/crash_reporter/backend/config/config.example.php +++ b/examples/crash_reporter/backend/config/config.example.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 19 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 a68b41e3b977416def464ec6a1aaeba10e660254325672cac891ab6200ba1bea +**********************************************************************/ return [ 'app_name' => 'Android Cast Crashes', // Production: '/app/androidcast_project/crashes' — Local php -S: use '' (empty string) diff --git a/examples/crash_reporter/backend/config/config.php b/examples/crash_reporter/backend/config/config.php index c2fd78e..a14b90b 100644 --- a/examples/crash_reporter/backend/config/config.php +++ b/examples/crash_reporter/backend/config/config.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 18 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 bcfa082fa936d758ce5ee539b5077c187dad629168b8784e2c65bb4cfe29a8a4 +**********************************************************************/ return [ 'app_name' => 'Android Cast Crashes', 'base_path' => '/app/androidcast_project/crashes', diff --git a/examples/crash_reporter/backend/public/api/upload.php b/examples/crash_reporter/backend/public/api/upload.php index cb62a4b..767151b 100644 --- a/examples/crash_reporter/backend/public/api/upload.php +++ b/examples/crash_reporter/backend/public/api/upload.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 21 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 d32979211e6246f5520b0570e2d1d10f5e86eb35fd94ede60634535f2ca143de +**********************************************************************/ declare(strict_types=1); require_once __DIR__ . '/../../src/bootstrap.php'; diff --git a/examples/crash_reporter/backend/public/index.php b/examples/crash_reporter/backend/public/index.php index 8327d6a..170f8d0 100644 --- a/examples/crash_reporter/backend/public/index.php +++ b/examples/crash_reporter/backend/public/index.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 59 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1cc27633c3b71e75c1e2dbc9b23ff2bb241958a8d7b31b5ae1594706182d381e +**********************************************************************/ declare(strict_types=1); require_once __DIR__ . '/../src/bootstrap.php'; diff --git a/examples/crash_reporter/backend/src/Auth.php b/examples/crash_reporter/backend/src/Auth.php index a05afd6..55fe935 100644 --- a/examples/crash_reporter/backend/src/Auth.php +++ b/examples/crash_reporter/backend/src/Auth.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 52 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 f1ce3231dfbf323fadc228d391266b298af4cb4eeefcd6cf78d7f4a899da74bf +**********************************************************************/ declare(strict_types=1); final class Auth { diff --git a/examples/crash_reporter/backend/src/Database.php b/examples/crash_reporter/backend/src/Database.php index 8a045bf..3ce26aa 100644 --- a/examples/crash_reporter/backend/src/Database.php +++ b/examples/crash_reporter/backend/src/Database.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 39 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 da4b9e05725c9a560a82071c392bdc1f35e06f7315a8cf2122518e6093d08cc8 +**********************************************************************/ declare(strict_types=1); final class Database { diff --git a/examples/crash_reporter/backend/src/ReportRepository.php b/examples/crash_reporter/backend/src/ReportRepository.php index 3ab2251..52cbd09 100644 --- a/examples/crash_reporter/backend/src/ReportRepository.php +++ b/examples/crash_reporter/backend/src/ReportRepository.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 57 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 17a4ce13743f8580baaeb5cf1d7c37715cdc17f1b17c9f598925dda3e1c12294 +**********************************************************************/ declare(strict_types=1); final class ReportRepository { diff --git a/examples/crash_reporter/backend/src/bootstrap.php b/examples/crash_reporter/backend/src/bootstrap.php index 7911a2c..d8a37e2 100644 --- a/examples/crash_reporter/backend/src/bootstrap.php +++ b/examples/crash_reporter/backend/src/bootstrap.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 41 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 8fdf942d57489d19dbe5358656cd1a0b1156eda966e3e5d7a180f603ace4243f +**********************************************************************/ declare(strict_types=1); $configPath = __DIR__ . '/../config/config.php'; diff --git a/examples/crash_reporter/backend/views/layout.php b/examples/crash_reporter/backend/views/layout.php index dcb05ee..5f1f01d 100644 --- a/examples/crash_reporter/backend/views/layout.php +++ b/examples/crash_reporter/backend/views/layout.php @@ -1,3 +1,14 @@ +/* package examples/crash_reporter/backend/views/layout.php */ + +/********************************************************************* + * layout.php + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 82 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 1c049b65f48ad5b675ec6c774c1a5ddca713d37e638cf1b930c68e97531d4c4e +**********************************************************************/ diff --git a/examples/crash_reporter/backend/views/login.php b/examples/crash_reporter/backend/views/login.php index 9bf46f7..7853487 100644 --- a/examples/crash_reporter/backend/views/login.php +++ b/examples/crash_reporter/backend/views/login.php @@ -1,3 +1,14 @@ +/* package examples/crash_reporter/backend/views/login.php */ + +/********************************************************************* + * login.php + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 23 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 37ae18b8cc9050f282aa8bf9a040932e7405448f45d6a9c0ba043a262deab8b2 +**********************************************************************/ diff --git a/examples/crash_reporter/backend/views/report_detail.php b/examples/crash_reporter/backend/views/report_detail.php index 3671b03..d8a0440 100644 --- a/examples/crash_reporter/backend/views/report_detail.php +++ b/examples/crash_reporter/backend/views/report_detail.php @@ -1,4 +1,15 @@ + * Contributors: + * - Anton Afanasyeu (1 commits, 50 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 830d53711eef7690d747cb85455201ddbd613807203ff970614e992f1474de81 +**********************************************************************/ $p = $report['payload'] ?? []; $device = $p['device'] ?? []; $app = $p['app'] ?? []; diff --git a/examples/ota/mqtt-topics.md b/examples/ota/mqtt-topics.md index 7ba79e2..dd719c7 100644 --- a/examples/ota/mqtt-topics.md +++ b/examples/ota/mqtt-topics.md @@ -12,6 +12,9 @@ Publish retained payloads for these topics: - `v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_sign.json` - `v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01.otapkg` +HTTP mirrors may also host `*.otabundle.zip` (manifest + sign + `package.apk` in one STORED zip). +The app uses **per-artifact MQTT topics only** — it does not download bundles over MQTT. + Example source URL in app settings: - `mqtt://foxx.org:1883/v0/ota/channel/stable.json` diff --git a/examples/ota/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_manifest.json b/examples/ota/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_manifest.json index 07084a3..b8ceb65 100644 --- a/examples/ota/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_manifest.json +++ b/examples/ota/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_manifest.json @@ -7,6 +7,9 @@ "apkUrl": "https://foxx.org/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00.otapkg", "signUrl": "https://foxx.org/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00_sign.json", "sizeBytes": 10485760, + "bundleUrl": "https://foxx.org/v0/ota/00/00.01/00.01.00/android_cast_00.01.00.00.otabundle.zip", + "bundleSha256": "0000000000000000000000000000000000000000000000000000000000000000", + "bundleSizeBytes": 10500000, "mandatory": false, "releaseNotes": "Current production baseline." } diff --git a/examples/ota/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_manifest.json b/examples/ota/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_manifest.json index 33167c6..5413f3d 100644 --- a/examples/ota/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_manifest.json +++ b/examples/ota/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_manifest.json @@ -7,6 +7,9 @@ "apkUrl": "https://foxx.org/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01.otapkg", "signUrl": "https://foxx.org/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01_sign.json", "sizeBytes": 11534336, + "bundleUrl": "https://foxx.org/v0/ota/00/00.01/00.01.01/android_cast_00.01.01.01.otabundle.zip", + "bundleSha256": "0000000000000000000000000000000000000000000000000000000000000000", + "bundleSizeBytes": 11600000, "mandatory": false, "releaseNotes": "Next OTA candidate with service-based updater." } diff --git a/ndk/jni/androidcast_codecs.c b/ndk/jni/androidcast_codecs.c index 4e593f7..82fa6da 100644 --- a/ndk/jni/androidcast_codecs.c +++ b/ndk/jni/androidcast_codecs.c @@ -1,3 +1,14 @@ +/* package ndk/jni/androidcast_codecs.c */ + +/********************************************************************* + * androidcast_codecs.c + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 11 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 b9b751d48b4e612c4400e84ff5cb5d6c9e82884ba76c906591bd8fdfc0559771 +**********************************************************************/ #include #include diff --git a/ndk/jni/crash_hook.c b/ndk/jni/crash_hook.c index 9e747bb..fc7cadb 100644 --- a/ndk/jni/crash_hook.c +++ b/ndk/jni/crash_hook.c @@ -1,3 +1,14 @@ +/* package ndk/jni/crash_hook.c */ + +/********************************************************************* + * crash_hook.c + * Created at: Wed 20 May 2026 14:31:55 +0200 + * Updated at: Wed 20 May 2026 14:31:55 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 122 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 7541b6c0d3bf233b316e0ca2f66e40a7692054fadb8ff4a965fca8f530d90e1f +**********************************************************************/ #include #include #include diff --git a/ndk/jni/libvpx_bridge.c b/ndk/jni/libvpx_bridge.c index 54ff29b..77e361b 100644 --- a/ndk/jni/libvpx_bridge.c +++ b/ndk/jni/libvpx_bridge.c @@ -1,3 +1,14 @@ +/* package ndk/jni/libvpx_bridge.c */ + +/********************************************************************* + * libvpx_bridge.c + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Tue 19 May 2026 12:23:39 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (5 commits, 424 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 34be3d873167d9aeb4ec3525d87260fc517ee25b21b1a52870ec330dbc642983 +**********************************************************************/ #include #include #include diff --git a/ndk/jni/opus_bridge.c b/ndk/jni/opus_bridge.c index e589d11..97c7769 100644 --- a/ndk/jni/opus_bridge.c +++ b/ndk/jni/opus_bridge.c @@ -1,3 +1,14 @@ +/* package ndk/jni/opus_bridge.c */ + +/********************************************************************* + * opus_bridge.c + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 13 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 0ba245379ed3ff43dcec08a0276292e8fe58be0a189b7736e753f7765a393853 +**********************************************************************/ #include #ifndef ANDROIDCAST_HAVE_OPUS diff --git a/ndk/jni/speex_bridge.c b/ndk/jni/speex_bridge.c index 69e1c23..7379784 100644 --- a/ndk/jni/speex_bridge.c +++ b/ndk/jni/speex_bridge.c @@ -1,3 +1,14 @@ +/* package ndk/jni/speex_bridge.c */ + +/********************************************************************* + * speex_bridge.c + * Created at: Sun 17 May 2026 22:49:49 +0200 + * Updated at: Sun 17 May 2026 22:49:49 +0200 by Anton Afanasyeu + * Contributors: + * - Anton Afanasyeu (1 commits, 13 lines) + * - Cursor Agent (project assistant) + * Digest: SHA256 cb806bd95d66394159981dfd3f23667cbc0cd51fd8f9dbe9f6a390e0a6112095 +**********************************************************************/ #include #ifndef ANDROIDCAST_HAVE_SPEEX diff --git a/scripts/apply-project-headers.py b/scripts/apply-project-headers.py new file mode 100755 index 0000000..e1784d0 --- /dev/null +++ b/scripts/apply-project-headers.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Apply HEADER.txt blocks to all project sources.""" +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +from header_lib import ( + REPO_ROOT, + apply_header_to_content, + has_valid_header, + header_needs_identity_refresh, + is_excluded_path, + iter_source_files, +) + + +def main() -> int: + parser = argparse.ArgumentParser(description="Apply project headers to source files") + parser.add_argument("--check", action="store_true", help="Only report files missing headers") + parser.add_argument( + "--fix-identity", + action="store_true", + help="Re-apply headers where contributors lack email but git has one", + ) + parser.add_argument("--path", type=str, default="", help="Limit to one file or directory") + args = parser.parse_args() + + root = REPO_ROOT + targets = list(iter_source_files(root)) + if args.path: + p = Path(args.path) + if not p.is_absolute(): + p = REPO_ROOT / p + if p.is_file(): + targets = [p] + else: + targets = [f for f in iter_source_files(root) if str(f).startswith(str(p))] + + missing = [] + identity_fix = [] + changed = 0 + skipped_vendor = 0 + for path in sorted(targets): + if is_excluded_path(path): + skipped_vendor += 1 + continue + text = path.read_text(encoding="utf-8", errors="replace") + if args.check: + if not has_valid_header(text): + missing.append(path.relative_to(REPO_ROOT)) + elif header_needs_identity_refresh(text, path): + identity_fix.append(path.relative_to(REPO_ROOT)) + continue + if args.fix_identity: + if not header_needs_identity_refresh(text, path) and has_valid_header(text): + continue + new_text = apply_header_to_content(path, text) + if new_text != text: + path.write_text(new_text, encoding="utf-8", newline="\n") + changed += 1 + + if args.check: + if missing: + print("Missing headers:", len(missing)) + for m in missing[:50]: + print(" ", m) + if len(missing) > 50: + print(" ...") + if identity_fix: + print("Identity refresh suggested:", len(identity_fix)) + for m in identity_fix[:30]: + print(" ", m) + if not missing and not identity_fix: + print("All", len(targets) - skipped_vendor, "tracked files OK (third-party skipped).") + return 0 + return 1 if missing else 0 + + note = f" (skipped {skipped_vendor} under third-party/vendor paths)" if skipped_vendor else "" + print(f"Updated {changed} / {len(targets) - skipped_vendor} source files{note}.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/generate-ota-v0.sh b/scripts/generate-ota-v0.sh index 9cf6deb..45fe16e 100755 --- a/scripts/generate-ota-v0.sh +++ b/scripts/generate-ota-v0.sh @@ -8,7 +8,8 @@ # v0/ota/channel/stable.json # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_manifest.json # v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB_sign.json -# (copy APK to …/android_cast_00.MM.mm.BB.otapkg if out-dir set) +# v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otapkg +# v0/ota/00/00.MM/00.MM.mm/android_cast_00.MM.mm.BB.otabundle.zip (STORE zip) set -euo pipefail apk="${1:?APK path required}" @@ -48,7 +49,9 @@ artifact_base="${base}/android_cast_${ver_p}.${bld_p}" apk_url="${artifact_base}.otapkg" sign_url="${artifact_base}_sign.json" manifest_url="${artifact_base}_manifest.json" +bundle_url="${artifact_base}.otabundle.zip" sha256="$(sha256sum "$apk" | awk '{print $1}')" +apk_size="$(stat -c%s "$apk" 2>/dev/null || wc -c <"$apk" | tr -d ' ')" rel_root="${out_dir}/v0/ota" rel_dir="${rel_root}/00/${maj_p}/${ver_p}" @@ -57,14 +60,18 @@ mkdir -p "${rel_dir}" "${rel_root}/channel" pkg_name="android_cast_${ver_p}.${bld_p}.otapkg" cp -f "$apk" "${rel_dir}/${pkg_name}" -cat >"${rel_dir}/android_cast_${ver_p}.${bld_p}_sign.json" <"${rel_dir}/${sign_name}" <"${rel_dir}/android_cast_${ver_p}.${bld_p}_manifest.json" <"${rel_dir}/${manifest_name}" <"${rel_dir}/android_cast_${ver_p}.${bld_p}_manifest.json" </dev/null || wc -c <"${rel_dir}/${bundle_name}" | tr -d ' ')" + +# Patch manifest with bundle fields (jq optional; use temp file + heredoc rewrite) +cat >"${rel_dir}/${manifest_name}" <&2 echo "Channel: ${host_base%/}/v0/ota/channel/stable.json" >&2 +echo "Bundle: ${bundle_url} (${bundle_size} bytes)" >&2 cat "${rel_root}/channel/stable.json" diff --git a/scripts/header-pre-commit.py b/scripts/header-pre-commit.py new file mode 100755 index 0000000..c47fea2 --- /dev/null +++ b/scripts/header-pre-commit.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Git pre-commit: validate headers on new files; refresh Updated/Digest on staged edits.""" +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path + +from header_lib import ( + REPO_ROOT, + SOURCE_SUFFIXES, + apply_header_to_content, + has_valid_header, + header_needs_identity_refresh, + is_excluded_path, + resolve_header_contributor, + update_header_timestamps, +) + + +def staged_files() -> list[Path]: + out = subprocess.check_output( + ["git", "diff", "--cached", "--name-only", "--diff-filter=ACMR"], + cwd=REPO_ROOT, + text=True, + ) + files = [] + for line in out.splitlines(): + p = REPO_ROOT / line.strip() + if not p.is_file() or p.suffix.lower() not in SOURCE_SUFFIXES: + continue + if is_excluded_path(p): + continue + files.append(p) + return files + + +def is_new_file(path: Path) -> bool: + rel = path.relative_to(REPO_ROOT).as_posix() + try: + subprocess.check_call( + ["git", "diff", "--cached", "--diff-filter=A", "--quiet", "--", rel], + cwd=REPO_ROOT, + ) + return False + except subprocess.CalledProcessError: + return True + + +def main() -> int: + errors = [] + contributor = resolve_header_contributor() + for path in staged_files(): + text = path.read_text(encoding="utf-8", errors="replace") + if is_new_file(path): + if not has_valid_header(text): + errors.append( + f"{path.relative_to(REPO_ROOT)}: new file must include HEADER.txt block" + ) + text = apply_header_to_content(path, text) + text = update_header_timestamps(text, path, contributor) + else: + if has_valid_header(text): + if header_needs_identity_refresh(text, path): + text = apply_header_to_content(path, text) + text = update_header_timestamps(text, path, contributor) + else: + text = apply_header_to_content(path, text) + text = update_header_timestamps(text, path, contributor) + path.write_text(text, encoding="utf-8", newline="\n") + rel = path.relative_to(REPO_ROOT).as_posix() + subprocess.check_call(["git", "add", "--", rel], cwd=REPO_ROOT) + + if errors: + for e in errors: + print(e, file=sys.stderr) + print( + "Run: python3 scripts/apply-project-headers.py", + file=sys.stderr, + ) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/header_lib.py b/scripts/header_lib.py new file mode 100755 index 0000000..16bb3aa --- /dev/null +++ b/scripts/header_lib.py @@ -0,0 +1,499 @@ +#!/usr/bin/env python3 +"""Shared logic for project source headers (see HEADER.txt).""" +from __future__ import annotations + +import hashlib +import re +import subprocess +from dataclasses import dataclass +from datetime import datetime +from pathlib import Path +from typing import Iterable + +REPO_ROOT = Path(__file__).resolve().parents[1] +HEADER_TEMPLATE = REPO_ROOT / "HEADER.txt" +BANNER_START = "/*********************************************************************" +BANNER_END = "**********************************************************************/" +MARKER_CREATED = "Created at:" +MARKER_UPDATED = "Updated at:" +MARKER_DIGEST = "Digest:" +MARKER_CONTRIBUTORS = "Contributors:" +MARKER_CLASS = re.compile(r"^\s*\*?\s*(class|interface|enum)\s+(\w+)", re.I) + +ASSISTANT_NAME = "Cursor Agent" +ASSISTANT_CONTRIBUTOR = ASSISTANT_NAME +IDENTITY_IN_ANGLE = re.compile(r"^(.+?)\s*<([^>]+)>\s*$") +IGNORED_GIT_AUTHORS = frozenset({"Not Committed Yet", "Unknown"}) +SOURCE_SUFFIXES = {".java", ".aidl", ".c", ".cpp", ".h", ".php"} + +SKIP_DIR_NAMES = { + ".git", + ".gradle", + "build", + ".cxx", + "third-party", + "node_modules", + ".idea", +} +EXCLUDED_PATH_MARKERS = frozenset({"third-party"}) + + +def is_excluded_path(path: Path) -> bool: + """Never apply headers under third-party/ or other vendor trees.""" + resolved = path.resolve() + root = REPO_ROOT.resolve() + try: + rel_parts = resolved.relative_to(root).parts + except ValueError: + return True + if any(part in EXCLUDED_PATH_MARKERS for part in rel_parts): + return True + return any(part in SKIP_DIR_NAMES for part in rel_parts) + + +@dataclass +class FileMeta: + rel_path: str + filename: str + package_line: str + class_line: str + created_at: str + updated_at: str + last_contributor: str + contributors_block: str + language: str + + +def iter_source_files(root: Path) -> Iterable[Path]: + for path in root.rglob("*"): + if path.suffix.lower() not in SOURCE_SUFFIXES: + continue + if is_excluded_path(path): + continue + if path.is_file(): + yield path + + +_GLOBAL_IDENTITY_MAP: dict[str, str] | None = None + + +def global_git_identity_map() -> dict[str, str]: + """Repo-wide author -> email from git shortlog.""" + global _GLOBAL_IDENTITY_MAP + if _GLOBAL_IDENTITY_MAP is not None: + return _GLOBAL_IDENTITY_MAP + emails: dict[str, str] = {} + out = run_git(["shortlog", "-sne", "--all"], REPO_ROOT) + for line in out.splitlines(): + line = line.strip() + if not line: + continue + # "29\tAnton Afanasyeu " or "29 Anton ..." + if "\t" in line: + _, rest = line.split("\t", 1) + else: + parts = line.split(None, 1) + rest = parts[1] if len(parts) > 1 else line + name, mail = parse_identity(rest.strip()) + if is_tracked_author(name) and mail: + emails.setdefault(name, mail) + _GLOBAL_IDENTITY_MAP = emails + return emails + + +def run_git(args: list[str], cwd: Path) -> str: + try: + out = subprocess.check_output( + ["git", *args], + cwd=cwd, + stderr=subprocess.DEVNULL, + text=True, + ) + return out.strip() + except (subprocess.CalledProcessError, FileNotFoundError): + return "" + + +def normalize_email(raw: str) -> str: + e = raw.strip() + if e.startswith("<") and e.endswith(">"): + e = e[1:-1].strip() + if not e or e.lower() in {"unknown", "none", "n/a"}: + return "" + if "@" not in e: + return "" + return e + + +def parse_identity(text: str) -> tuple[str, str]: + """Split 'Name ' or plain name.""" + t = text.strip() + if not t: + return "", "" + m = IDENTITY_IN_ANGLE.match(t) + if m: + return m.group(1).strip(), normalize_email(m.group(2)) + return t, "" + + +def is_tracked_author(name: str) -> bool: + n = name.strip() + return bool(n) and n not in IGNORED_GIT_AUTHORS + + +def format_identity(name: str, email: str = "") -> str: + name = name.strip() + email = normalize_email(email) + if not name: + return ASSISTANT_NAME + if email: + return f"{name} <{email}>" + return name + + +def format_git_date(raw: str) -> str: + if not raw: + return datetime.now().astimezone().strftime("%a %d %b %Y %H:%M:%S %z") + try: + # git %ai: 2026-05-20 15:04:12 +0300 + dt = datetime.strptime(raw, "%Y-%m-%d %H:%M:%S %z") + return dt.strftime("%a %d %b %Y %H:%M:%S %z") + except ValueError: + return raw + + +def git_identity_map(path: Path, body: str = "") -> dict[str, str]: + """Map git author name -> email (best effort per file).""" + rel = repo_relative(path) + emails: dict[str, str] = {} + log = run_git(["log", "--follow", "--format=%an%x09%ae", "--", rel], REPO_ROOT) + for line in log.splitlines(): + if "\t" not in line: + continue + an, ae = line.split("\t", 1) + an, ae = an.strip(), normalize_email(ae) + if is_tracked_author(an) and ae: + emails.setdefault(an, ae) + + blame = run_git(["blame", "--line-porcelain", "--", rel], REPO_ROOT) + author_name: str | None = None + for line in blame.splitlines(): + if line.startswith("author "): + author_name = line[7:].strip() + elif line.startswith("author-mail "): + mail = normalize_email(line[12:]) + if is_tracked_author(author_name or "") and mail: + emails.setdefault(author_name, mail) + author_name = None + elif line.startswith("\t"): + author_name = None + + for tag in re.finditer( + r"@author\s+(.+)$|/\*\s*@author\s+(.+?)\s*\*/", + body, + re.MULTILINE | re.IGNORECASE, + ): + fragment = (tag.group(1) or tag.group(2) or "").strip() + name, mail = parse_identity(fragment) + if name and mail: + emails.setdefault(name, mail) + for name, mail in global_git_identity_map().items(): + emails.setdefault(name, mail) + return emails + + +def git_created_updated(path: Path, body: str = "") -> tuple[str, str, str]: + rel = repo_relative(path) + created_raw = run_git( + ["log", "--follow", "--diff-filter=A", "--format=%ai", "-1", "--", rel], + REPO_ROOT, + ) + updated_raw = run_git(["log", "-1", "--format=%ai", "--", rel], REPO_ROOT) + last = run_git(["log", "-1", "--format=%an%x09%ae", "--", rel], REPO_ROOT) + if "\t" in last: + an, ae = last.split("\t", 1) + author = format_identity(an, ae) + elif last: + id_map = git_identity_map(path, body) + author = format_identity(last, id_map.get(last, "")) + else: + author = ASSISTANT_NAME + return ( + format_git_date(created_raw), + format_git_date(updated_raw or created_raw), + author, + ) + + +def git_config_identity() -> tuple[str, str]: + name = run_git(["config", "user.name"], REPO_ROOT) + email = run_git(["config", "user.email"], REPO_ROOT) + return name, email + + +def git_config_identity_formatted() -> str: + name, email = git_config_identity() + if name: + return format_identity(name, email) + return ASSISTANT_NAME + + +def resolve_header_contributor() -> str: + """ + Pre-commit / env contributor: HEADER_CONTRIBUTOR or HEADER_CONTRIBUTOR_EMAIL + enriched with git user.email when the name has no address. + """ + import os + + raw = os.environ.get("HEADER_CONTRIBUTOR", "").strip() + email_extra = normalize_email(os.environ.get("HEADER_CONTRIBUTOR_EMAIL", "")) + cfg_name, cfg_email = git_config_identity() + + if raw: + name, email = parse_identity(raw) + if not name: + name = raw + if not email: + email = email_extra or cfg_email or global_git_identity_map().get(name, "") + return format_identity(name, email) + + if email_extra and cfg_name: + return format_identity(cfg_name, email_extra) + return git_config_identity_formatted() + + +def git_contributors(path: Path, body_line_count: int, body: str = "") -> list[tuple[str, int, int]]: + rel = repo_relative(path) + id_map = git_identity_map(path, body) + commit_counts: dict[str, int] = {} + log = run_git(["log", "--follow", "--format=%an", "--", rel], REPO_ROOT) + for line in log.splitlines(): + name = line.strip() + if is_tracked_author(name): + commit_counts[name] = commit_counts.get(name, 0) + 1 + + line_counts: dict[str, int] = {} + blame = run_git(["blame", "--line-porcelain", "--", rel], REPO_ROOT) + author: str | None = None + for line in blame.splitlines(): + if line.startswith("author "): + author = line[7:].strip() + elif line.startswith("\t") and author and is_tracked_author(author): + line_counts[author] = line_counts.get(author, 0) + 1 + + names = {n for n in (set(commit_counts) | set(line_counts)) if is_tracked_author(n)} + rows: list[tuple[str, int, int]] = [] + for name in names: + label = format_identity(name, id_map.get(name, "")) + rows.append((label, commit_counts.get(name, 0), line_counts.get(name, 0))) + rows.sort(key=lambda r: (-r[1], -r[2], r[0].lower())) + if not rows: + rows = [(ASSISTANT_NAME, 0, body_line_count)] + return rows + + +def contributors_block(rows: list[tuple[str, int, int]], include_assistant: bool = True) -> str: + lines = [] + for label, commits, nlines in rows: + name, _ = parse_identity(label) + if name == ASSISTANT_NAME: + continue + lines.append(f" * - {label} ({commits} commits, {nlines} lines)") + if include_assistant: + lines.append(f" * - {ASSISTANT_NAME} (project assistant)") + return "\n".join(lines) + + +def detect_class_line(body: str, suffix: str) -> str: + if suffix not in {".java", ".aidl", ".cpp", ".php"}: + return "" + patterns = [ + ("class", r"^\s*public\s+(?:final\s+)?class\s+(\w+)"), + ("class", r"^\s*class\s+(\w+)"), + ("interface", r"^\s*public\s+interface\s+(\w+)"), + ("interface", r"^\s*interface\s+(\w+)"), + ("enum", r"^\s*public\s+enum\s+(\w+)"), + ("enum", r"^\s*enum\s+(\w+)"), + ] + for line in body.splitlines(): + for kind, pat in patterns: + m = re.match(pat, line) + if m: + return f" * {kind} {m.group(1)}" + return "" + + +def package_line_for_file(source_text: str, rel_path: str, suffix: str) -> str: + for line in source_text.splitlines(): + if suffix in {".java", ".aidl"}: + m = re.match(r"^\s*package\s+([\w.]+)\s*;", line) + if m: + return f"package {m.group(1)};" + return f"/* package {rel_path} */" + + +def strip_existing_header(text: str, suffix: str) -> tuple[str, str]: + """Returns (body without header/package, preserved leading e.g. = 0: + leading = work[: first_nl + 1] + work = work[first_nl + 1 :] + else: + leading = work + "\n" + work = "" + + lines = work.splitlines(keepends=True) + i = 0 + if i < len(lines) and ( + lines[i].startswith("package ") + or lines[i].startswith("/* package ") + ): + i += 1 + if i < len(lines) and lines[i].strip() == "": + i += 1 + + if i < len(lines) and BANNER_START in lines[i]: + while i < len(lines) and BANNER_END not in lines[i]: + i += 1 + if i < len(lines): + i += 1 + if i < len(lines) and lines[i].strip() == "": + i += 1 + + body = "".join(lines[i:]).lstrip("\n") + if body.startswith("package "): + first_nl = body.find("\n") + if first_nl >= 0: + body = body[first_nl + 1 :].lstrip("\n") + return body, leading + + +def repo_relative(path: Path) -> str: + root = REPO_ROOT.resolve() + try: + return path.resolve().relative_to(root).as_posix() + except ValueError: + return path.name + + +def build_meta(path: Path, body: str, source_text: str = "") -> FileMeta: + rel = repo_relative(path) + suffix = path.suffix.lower() + full_source = source_text if source_text else body + created, updated, author = git_created_updated(path, body) + rows = git_contributors(path, max(1, len(body.splitlines())), body) + if not any(parse_identity(r[0])[0] == ASSISTANT_NAME for r in rows): + rows.append((ASSISTANT_NAME, 0, 0)) + + pkg = package_line_for_file(full_source, rel, suffix) + lang = "java" if suffix in {".java", ".aidl"} else ("php" if suffix == ".php" else "c") + + class_line = detect_class_line(body, suffix) + return FileMeta( + rel_path=rel, + filename=path.name, + package_line=pkg, + class_line=class_line, + created_at=created, + updated_at=updated, + last_contributor=author, + contributors_block=contributors_block(rows), + language=lang, + ) + + +def render_header(meta: FileMeta, digest_hex: str | None) -> str: + lines = [ + meta.package_line, + "", + BANNER_START, + f" * {meta.filename}", + f" * {MARKER_CREATED} {meta.created_at}", + f" * {MARKER_UPDATED} {meta.updated_at} by {meta.last_contributor}", + ] + if meta.class_line: + lines.append(meta.class_line) + lines.append(f" * {MARKER_CONTRIBUTORS}") + lines.append(meta.contributors_block) + if digest_hex: + lines.append(f" * {MARKER_DIGEST} SHA256\t{digest_hex}") + lines.append(BANNER_END) + lines.append("") + return "\n".join(lines) + + +def compute_digest(prefix: str, body: str) -> str: + payload = prefix + body + return hashlib.sha256(payload.encode("utf-8")).hexdigest() + + +def apply_header_to_content(path: Path, text: str, update_only: bool = False) -> str: + suffix = path.suffix.lower() + body, leading = strip_existing_header(text, suffix) + meta = build_meta(path, body, text) + + if update_only and MARKER_CREATED in text: + m = re.search(r"\* Created at: (.+)", text) + if m: + meta.created_at = m.group(1).strip() + + prefix_without_digest = render_header(meta, None) + digest = compute_digest(prefix_without_digest, body) + prefix = render_header(meta, digest) + return leading + prefix + body + + +def has_valid_header(text: str) -> bool: + return MARKER_CREATED in text and BANNER_START in text and BANNER_END in text + + +def header_needs_identity_refresh(text: str, path: Path) -> bool: + """True when a known author appears without email but git has one.""" + if not has_valid_header(text): + return False + suffix = path.suffix.lower() + body, _ = strip_existing_header(text, suffix) + id_map = git_identity_map(path, body) + + updated = re.search(r"\* Updated at: .+ by (.+)$", text, re.MULTILINE) + if updated: + name, email = parse_identity(updated.group(1).strip()) + if name != ASSISTANT_NAME and not email and id_map.get(name): + return True + + for line in text.splitlines(): + stripped = line.strip() + if not stripped.startswith("* - "): + continue + label = stripped[7:].split(" (", 1)[0].strip() + name, email = parse_identity(label) + if name != ASSISTANT_NAME and not email and id_map.get(name): + return True + return False + + +def update_header_timestamps(text: str, path: Path, contributor: str | None = None) -> str: + suffix = path.suffix.lower() + body, leading = strip_existing_header(text, suffix) + if contributor: + who = contributor + else: + who = resolve_header_contributor() + if who == ASSISTANT_NAME: + who = git_created_updated(path, body)[2] + updated_line = datetime.now().astimezone().strftime("%a %d %b %Y %H:%M:%S %z") + m_created = re.search(r"\* Created at: (.+)", text) + created = m_created.group(1).strip() if m_created else git_created_updated(path)[0] + + meta = build_meta(path, body, text) + meta.created_at = created + meta.updated_at = updated_line + meta.last_contributor = who + + prefix_without_digest = render_header(meta, None) + digest = compute_digest(prefix_without_digest, body) + prefix = render_header(meta, digest) + return leading + prefix + body diff --git a/scripts/install-git-hooks.sh b/scripts/install-git-hooks.sh new file mode 100755 index 0000000..2662996 --- /dev/null +++ b/scripts/install-git-hooks.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Install repo git hooks (header pre-commit). +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +git -C "$ROOT" config core.hooksPath .githooks +chmod +x "$ROOT/.githooks/pre-commit" +chmod +x "$ROOT/scripts/header-pre-commit.py" +chmod +x "$ROOT/scripts/apply-project-headers.py" +echo "Installed hooks via core.hooksPath=.githooks" diff --git a/scripts/test_header_lib.py b/scripts/test_header_lib.py new file mode 100755 index 0000000..15af3f3 --- /dev/null +++ b/scripts/test_header_lib.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Unit tests for header_lib (run: python3 scripts/test_header_lib.py).""" +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from header_lib import ( + apply_header_to_content, + format_identity, + has_valid_header, + is_excluded_path, + parse_identity, + resolve_header_contributor, + strip_existing_header, +) +from pathlib import Path +import header_lib + + +class HeaderLibTest(unittest.TestCase): + def test_strip_and_apply_java(self) -> None: + src = """package com.example; + +public class Foo { +} +""" + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "Foo.java" + path.write_text(src, encoding="utf-8") + out = apply_header_to_content(path, src) + self.assertTrue(has_valid_header(out)) + self.assertIn("package com.example;", out) + self.assertIn(" * class Foo", out) + self.assertIn("Digest: SHA256", out) + self.assertIn("Cursor Agent", out) + body, _ = strip_existing_header(out, ".java") + self.assertIn("public class Foo", body) + self.assertNotIn("package com.example", body.split("public class")[0]) + + def test_strip_php_opener(self) -> None: + src = " None: + self.assertEqual("Ada ", format_identity("Ada", "a@b.c")) + self.assertEqual("Ada", format_identity("Ada", "")) + name, mail = parse_identity("Ada ") + self.assertEqual(("Ada", "a@b.c"), (name, mail)) + + def test_excluded_third_party(self) -> None: + p = header_lib.REPO_ROOT / "third-party/libvpx/foo.c" + self.assertTrue(is_excluded_path(p)) + + def test_resolve_header_contributor_env(self) -> None: + import os + old = os.environ.get("HEADER_CONTRIBUTOR") + old_mail = os.environ.get("HEADER_CONTRIBUTOR_EMAIL") + try: + os.environ["HEADER_CONTRIBUTOR"] = "Test User" + os.environ.pop("HEADER_CONTRIBUTOR_EMAIL", None) + ident = resolve_header_contributor() + self.assertTrue(ident.startswith("Test User")) + finally: + if old is None: + os.environ.pop("HEADER_CONTRIBUTOR", None) + else: + os.environ["HEADER_CONTRIBUTOR"] = old + if old_mail is None: + os.environ.pop("HEADER_CONTRIBUTOR_EMAIL", None) + else: + os.environ["HEADER_CONTRIBUTOR_EMAIL"] = old_mail + + +if __name__ == "__main__": + unittest.main()