Sounds: survive an audio device that crashes the app on open

A Windows friend's 1.3.0 dies about a second in on every start, right
around the 2 s audio warm-up (no Dart error, no close lines). Opening the
device is now logged and leaves audio-init.pending until it returns; a
start that finds it skips sounds instead of crashing again, and a sound
preview in Settings tries once more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-17 00:50:26 +03:00
1 parent 22ce40a488
commit c91d57633f
5 files changed
+92 -3

No files matched your search

+43
View File
@@ -1,3 +1,4 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
@@ -147,4 +148,46 @@ void main() {
expect(b.deinits, 1);
});
});
group('crash mark', () {
late Directory dir;
setUp(() => dir = Directory.systemTemp.createTempSync('sound_mark'));
tearDown(() => dir.deleteSync(recursive: true));
test('exists only while the device opens', () async {
final mark = '${dir.path}/audio-init.pending';
var seen = false;
final b = _MarkBackend(() => seen = File(mark).existsSync());
final e = SoundEngine(backend: b)..crashMark = mark;
expect(await e.warmUp(), isTrue);
expect(seen, isTrue, reason: 'there while opening');
expect(File(mark).existsSync(), isFalse, reason: 'gone once open');
});
test('left by a crash: sounds stay off, a preview tries again', () async {
final mark = '${dir.path}/audio-init.pending';
File(mark).writeAsStringSync('opening the audio device');
final b = _FakeBackend();
final e = SoundEngine(backend: b)..crashMark = mark;
await e.play('chat', 'k', _bytes, volume: 1);
expect(b.inits, 0, reason: 'never opened after a crash');
expect(b.plays, isEmpty);
e.retry();
await e.play('chat', 'k', _bytes, volume: 1);
expect(b.inits, 1);
expect(b.plays, hasLength(1));
expect(File(mark).existsSync(), isFalse);
});
});
}
class _MarkBackend extends _FakeBackend {
final void Function() onInit;
_MarkBackend(this.onInit);
@override
Future<void> init() async {
onInit();
await super.init();
}
}