fix: harden OriginOS recognition tracking

This commit is contained in:
2026-08-31 11:29:04 +08:00
parent 9ccbdfead4
commit 477f83c5b1
17 changed files with 980 additions and 108 deletions
+17
View File
@@ -183,6 +183,14 @@ void main() {
'accessibilityConnected': false,
'accessibilityConnectionState': 'reconnecting',
'accessibilityLastConnectedAt': 1724472000000,
'keepAliveExpected': true,
'keepAliveRunning': false,
'keepAliveError': '系统限制了后台保护启动',
'recentsProtectionExpected': true,
'recentsProtectionActive': true,
'lastRecognitionExitAt': 1788077518000,
'lastRecognitionExitReason': 'low_memory: single-cleaner',
'taskCleanerRecoveryNeeded': true,
'settings': jsonEncode({'accessibilityEvents': true}),
});
final connected = RecognitionStatus.fromMap({
@@ -204,6 +212,15 @@ void main() {
);
expect(reconnecting.accessibilityConnectionLabel, '正在重连');
expect(reconnecting.accessibilityLastConnectedAt, isNotNull);
expect(reconnecting.keepAliveExpected, isTrue);
expect(reconnecting.keepAliveRunning, isFalse);
expect(reconnecting.keepAliveNeedsRecovery, isTrue);
expect(reconnecting.keepAliveError, '系统限制了后台保护启动');
expect(reconnecting.recentsProtectionExpected, isTrue);
expect(reconnecting.recentsProtectionActive, isTrue);
expect(reconnecting.lastRecognitionExitAt, isNotNull);
expect(reconnecting.lastRecognitionExitReason, contains('single-cleaner'));
expect(reconnecting.taskCleanerRecoveryNeeded, isTrue);
expect(connected.accessibilityConnectionLabel, '已连接');
expect(disconnected.accessibilityConnectionLabel, '服务未连接');
expect(disconnected.accessibilityNeedsRecovery, isTrue);
+14 -2
View File
@@ -153,9 +153,21 @@ void main() {
);
expect(
RecognitionDiagnosticDisplay.from(
diagnostic('rejected', 'payment_input_page'),
diagnostic('waiting', 'payment_input_page'),
).summaryLabel,
'规则拒绝',
'等待结果页',
);
expect(
RecognitionDiagnosticDisplay.from(
diagnostic('waiting', 'payment_input_page'),
).reasonLabel,
'当前仍是付款输入或确认页面,等待结果页,不会提前入账',
);
expect(
RecognitionDiagnosticDisplay.from(
diagnostic('rejected', 'result_page_timeout'),
).reasonLabel,
'90 秒内未等到明确结果页,本次流程已停止追踪',
);
expect(
RecognitionDiagnosticDisplay.from(
+32 -4
View File
@@ -280,7 +280,7 @@ void main() {
expect(source, contains('_BackgroundKeepAliveCard'));
});
test('长期识别组件与系统绑定使用默认进程并支持重连状态', () {
test('长期识别组件使用独立保活进程并支持非阻塞重连', () {
final manifest = File(
'android/app/src/main/AndroidManifest.xml',
).readAsStringSync();
@@ -290,6 +290,12 @@ void main() {
final activity = File(
'android/app/src/main/kotlin/com/nx/miaoji/MainActivity.kt',
).readAsStringSync();
final settingsPage = File(
'lib/features/settings/screenshot_settings_page.dart',
).readAsStringSync();
final keepAlive = File(
'android/app/src/main/kotlin/com/nx/miaoji/RecognitionKeepAliveService.kt',
).readAsStringSync();
for (final component in [
'ScreenshotTileService',
@@ -301,18 +307,40 @@ void main() {
).firstMatch(manifest)?.group(0);
expect(declaration, isNotNull);
expect(declaration, contains('android:stopWithTask="false"'));
expect(declaration, isNot(contains('android:process=')));
expect(declaration, contains('android:process=":recognition"'));
}
final provider = RegExp(
'<provider\\s+android:name="\\.RecognitionBridgeProvider"[\\s\\S]*?/>',
).firstMatch(manifest)?.group(0);
expect(provider, isNotNull);
expect(provider, isNot(contains('android:process=')));
expect(provider, contains('android:process=":recognition"'));
expect(manifest, contains('android:name=".OneShotProjectionService"'));
expect(manifest, contains('android:process=":recognition"'));
final projection = RegExp(
'<service\\s+android:name="\\.OneShotProjectionService"[\\s\\S]*?/>',
).firstMatch(manifest)?.group(0);
expect(projection, isNotNull);
expect(projection, contains('android:process=":projection"'));
expect(manifest, contains('android:name=".RecognitionKeepAliveService"'));
expect(manifest, contains('android:foregroundServiceType="specialUse"'));
expect(manifest, contains('FOREGROUND_SERVICE_SPECIAL_USE'));
expect(manifest, contains('PROPERTY_SPECIAL_USE_FGS_SUBTYPE'));
expect(keepAlive, contains('START_STICKY'));
expect(keepAlive, contains('智能识别运行中'));
expect(channel, contains('waitForAccessibilityConnection'));
expect(channel, contains('_activeAccessibilityConnectionWait'));
expect(channel, contains('ensureRecognitionKeepAlive'));
expect(channel, contains('AccessibilityConnectionState.reconnecting'));
expect(activity, contains('"reconnecting"'));
expect(activity, contains('"disconnected"'));
expect(activity, contains('setExcludeFromRecents'));
expect(activity, contains('getHistoricalProcessExitReasons'));
expect(activity, contains('single-cleaner'));
expect(settingsPage, contains('_check();'));
expect(settingsPage, isNot(contains('_check(waitForConnection: true)')));
expect(settingsPage, contains('系统仍显示已授权,但 OriginOS 未重新绑定服务'));
expect(settingsPage, contains('启动后台保护'));
expect(settingsPage, contains('OriginOS 清理了识别进程'));
expect(settingsPage, contains('记之已从最近任务隐藏'));
expect(channel, contains('taskCleanerRecoveryNeeded'));
});
}