Files
ch34/.planning/codebase/CONCERNS.md
2026-04-21 12:57:40 +08:00

168 lines
13 KiB
Markdown

# Codebase Concerns
**Analysis Date:** 2026-04-16
## Technical Debt
### Placeholder Content in LICENSE and CHANGELOG
- Issue: `LICENSE` contains "TODO: Add your license here" and `CHANGELOG.md` contains "TODO: Describe initial release." No license or changelog content exists.
- Files: `D:\code\new_git_code\flutter\ch34\LICENSE`, `D:\code\new_git_code\flutter\ch34\CHANGELOG.md`
- Impact: Legal risk - the package has no defined license. No version history for consumers.
- Fix approach: Add an appropriate open-source license (e.g., MIT). Document release history in CHANGELOG.
### Unimplemented Modem Error Callbacks
- Issue: In `registerModemStatusCallback`, the `IModemStatus` interface has three error callbacks (`onOverrunError`, `onParityError`, `onFrameError`) with empty bodies - they silently discard errors.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 667-677)
- Impact: Serial communication errors are invisible to the Flutter layer. Users cannot detect data corruption.
- Fix approach: Forward these errors through the EventChannel or the data callback, or expose a separate error stream.
### GPIO Status Map Always Returns Hardcoded Values
- Issue: `Ch34TypeConverter.gpioStatusToMap()` hardcodes `index` and `value` to 0, regardless of the actual `GPIO_Status` object. Only `enabled` and `direction` are read from the status.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34TypeConverter.java` (lines 28-29)
- Impact: Dart side `queryGpioStatus()` and `queryAllGpioStatus()` always return incorrect `index` and `value` fields.
- Fix approach: Read `status.getIndex()` and `status.getValue()` from the WCH `GPIO_Status` object.
## Known Bugs
### Data Callback Only Supports Single Device Per Serial Number
- Issue: `Ch34DataStreamHandler` uses a single `_dataCallback` field. When multiple devices register data callbacks, each new registration overwrites the previous one. Only the last registered device's data is received.
- Files: `D:\code\new_git_code\flutter\ch34\lib\src\ch34_method_channel.dart` (line 44), `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 388-407)
- Impact: Multi-device scenarios lose data from all but the most recently registered device.
- Fix approach: Use a map keyed by `(deviceName, serialNumber)` to manage multiple independent subscriptions.
### Hardcoded USB Permission Wait Time
- Issue: In `openDevice`, when the initial open fails, a `Handler.postDelayed` waits 2000ms and retries. This is a magic number that may be insufficient on slow devices or excessive on fast ones.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (line 278)
- Impact: Permission may not be granted in time on some devices, leading to false failure.
- Fix approach: Use a proper permission result callback or `PendingIntent` instead of a fixed delay.
### `tryOpenDevice` Swallows Non-Permission Exceptions
- Issue: In `tryOpenDevice`, any non-`NoPermissionException` error logs the error but returns `true`, treating it as success.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 291-300)
- Impact: Failed device opens are reported as successful, leading to downstream errors that are harder to debug.
- Fix approach: Return `false` for any exception and let the caller handle the error properly.
## Security Concerns
### No Input Validation on Native Method Arguments
- Issue: The Java plugin directly casts method call arguments without null checks or type validation (e.g., `call.argument("deviceName")` cast to `String` without null guards).
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (throughout)
- Impact: Malformed or malicious method call arguments from Flutter can cause `ClassCastException` or `NullPointerException` on the Android side.
- Fix approach: Add null/type checks before using arguments. Return error results for invalid inputs.
### `pubspec.lock` Ignored for Library Packages
- Issue: `pubspec.lock` is in `.gitignore`, which is correct for library packages. However, `example/pubspec.lock` is not explicitly tracked, meaning the example app's dependency versions are not pinned.
- Files: `D:\code\new_git_code\flutter\ch34\.gitignore` (line 26)
- Impact: Example app may resolve to different dependency versions on different machines, causing inconsistent test results.
- Fix approach: Consider committing `example/pubspec.lock` for reproducible example builds.
## Performance Bottlenecks
### Synchronous `enumDevice` in `getDeviceOrThrow`
- Issue: `getDeviceOrThrow` calls `manager.enumDevice()` to enumerate all devices just to find one by name. This is called for nearly every method invocation.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 772-787)
- Impact: USB enumeration is slow and repeated unnecessarily. Every method call (read, write, set parameters) triggers this scan if the device is not in `openedDevices`.
- Fix approach: Cache device references when they are discovered, or maintain a device lookup map.
### Blocking `readData` Without Timeout
- Issue: `readData` calls `manager.readData(device, serialNumber)` synchronously with no timeout. If no data arrives, the method blocks indefinitely.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 373-385), `D:\code\new_git_code\flutter\ch34\lib\src\ch34_method_channel.dart` (lines 176-185)
- Impact: Flutter UI thread could freeze if a `readData` call blocks on a quiet serial line.
- Fix approach: Use the async callback-based approach for reading, or enforce a configurable timeout.
## Fragile Areas
### Single Global WCHUARTManager Instance
- Issue: The entire plugin uses a single `WCHUARTManager` instance stored as a field. It is lazily initialized in `ensureManagerInitialized()` and never reset except on engine detach.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 57, 757-770)
- Impact: If the WCH library is in a bad state (e.g., after an unhandled error), there is no recovery mechanism. Hot restart during development may cause initialization issues.
- Fix approach: Add a `reset()` or `reinitialize()` method for recovery scenarios.
### EventChannel Single Instance for All Devices
- Issue: Each EventChannel (`ch34/data`, `ch34/modem`, `ch34/usb_state`) has a single StreamHandler instance for all devices. The data handler must multiplex all device data through one channel.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 66-76), `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34DataStreamHandler.java`
- Impact: Adding device identification to each data event is the responsibility of the consumer. No per-device stream isolation.
- Fix approach: Include `deviceName` and `serialNumber` in each data event payload, or create per-device EventChannels.
### `removeDataCallback` Ignores `serialNumber`
- Issue: The Dart API `removeDataCallback` takes only `deviceName`, but `registerDataCallback` takes both `deviceName` and `serialNumber`. If a device has multiple serial ports, removing the callback for one serial number removes all.
- Files: `D:\code\new_git_code\flutter\ch34\lib\src\ch34_platform_interface.dart` (line 166), `D:\code\new_git_code\flutter\ch34\lib\src\ch34_manager.dart` (lines 160-162)
- Impact: Multi-port devices cannot independently manage callbacks per serial port.
- Fix approach: Add `serialNumber` parameter to `removeDataCallback`.
### Swallowed Exceptions in `enumDevice` Loop
- Issue: In `enumDevice`, exceptions during `getSerialCount` or `getChipType` are silently caught and ignored. The device is still reported but with incomplete data.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (lines 215)
- Impact: Consumers may receive devices with `serialCount = -1` and `chipType = null` with no indication of what went wrong.
- Fix approach: At minimum log the exception, or distinguish between "no data available" and "error reading data".
## Missing Patterns
### No Structured Error Handling
- Issue: The plugin uses `result.error(code, message, null)` with string codes for error reporting. The Dart side never throws typed exceptions (except `Ch34Exception` which is only used for GPIO failures). Most errors silently return `false` or `0`.
- Files: `D:\code\new_git_code\flutter\ch34\lib\src\ch34_method_channel.dart` (throughout), `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java` (throughout)
- Impact: Consumers cannot distinguish between different failure modes. Debugging requires enabling debug mode and reading logcat.
- Fix approach: Throw `Ch34Exception` with error code and message from all `result.error` responses. Define error code constants.
### No Lifecycle Management
- Issue: The plugin does not handle Android lifecycle events (e.g., app going to background). Active USB connections may be left open or become invalid.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\main\java\com\example\ch34\Ch34Plugin.java`
- Impact: When the app resumes, existing connections may be in an undefined state.
- Fix approach: Implement `ActivityAware` or use `AppLifecycleState` in Dart to pause/resume or clean up connections.
### No Unit Test Coverage for Core Logic
- Issue: The only unit tests cover `getPlatformVersion` and `enumDevice` with stub returns. None of the data conversion, parameter handling, or error paths are tested.
- Files: `D:\code\new_git_code\flutter\ch34\test\ch34_test.dart`, `D:\code\new_git_code\flutter\ch34\test\ch34_method_channel_test.dart`, `D:\code\new_git_code\flutter\ch34\android\src\test\java\com\example\ch34\Ch34PluginTest.java`
- Impact: Refactoring or bug fixes risk introducing regressions with no automated detection.
- Fix approach: Add tests for type conversion, error handling, and the mock platform covering all API methods.
## Dependencies Risk
### Bundled JAR Dependency Without Version Pinning
- Issue: The WCH `CH34XUARTDriver.jar` is included as a local JAR file in `android/libs/` with no version information in the build file. It is loaded via `flatDir` repository.
- Files: `D:\code\new_git_code\flutter\ch34\android\build.gradle` (line 47)
- Impact: No easy way to track which version of the WCH library is used. Cannot update to newer versions without manual replacement. No transitive dependency management.
- Fix approach: Document the JAR version used. Consider hosting in a Maven repository for proper version management.
### Android Gradle Plugin Version is Outdated
- Issue: The build uses `com.android.tools.build:gradle:7.3.0` which is significantly outdated. Current versions are 8.x.
- Files: `D:\code\new_git_code\flutter\ch34\android\build.gradle` (line 11)
- Impact: May not be compatible with newer Flutter/Android SDK versions. Missing bug fixes and performance improvements.
- Fix approach: Update to AGP 8.x and test thoroughly. Update `compileSdk` and `targetSdk` accordingly.
### Java 8 Target Compatibility
- Issue: The plugin compiles with `JavaVersion.VERSION_1_8` as source and target.
- Files: `D:\code\new_git_code\flutter\ch34\android\build.gradle` (lines 35-36)
- Impact: Cannot use modern Java language features. May limit compatibility with future Android tooling.
- Fix approach: Consider updating to Java 11+ if the minimum SDK and tooling support it.
## Test Coverage Gaps
### No Integration Tests for USB Operations
- Issue: The single integration test only checks `getPlatformVersion`. No tests for actual USB device operations.
- Files: `D:\code\new_git_code\flutter\ch34\example\integration_test\plugin_integration_test.dart`
- Risk: USB-specific bugs are only caught through manual testing.
- Priority: High
### No Tests for Type Conversions
- Issue: `Ch34TypeConverter` has zero test coverage. The GPIO and error type conversions are not verified.
- Files: `D:\code\new_git_code\flutter\ch34\android\src\test\java\com\example\ch34\Ch34PluginTest.java`
- Risk: Conversion bugs (like the hardcoded GPIO values) go undetected.
- Priority: High
### No Tests for EventChannel Streams
- Issue: No tests verify that data callbacks, modem status, or USB state events flow correctly from native to Dart.
- Files: `D:\code\new_git_code\flutter\ch34\test\ch34_method_channel_test.dart`, `D:\code\new_git_code\flutter\ch34\test\ch34_test.dart`
- Risk: Stream subscription and cancellation logic may have bugs that only manifest at runtime.
- Priority: Medium
### No Tests for Exception Paths
- Issue: All tests use happy-path mock returns. No tests simulate errors, timeouts, or null responses.
- Files: `D:\code\new_git_code\flutter\ch34\test\ch34_test.dart`
- Risk: Error handling code is untested and may fail silently or crash.
- Priority: Medium
---
*Concerns audit: 2026-04-16*