machine_learning_controller.dart 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import "dart:async";
  2. import "dart:io";
  3. import "package:battery_info/battery_info_plugin.dart";
  4. import "package:battery_info/model/android_battery_info.dart";
  5. import "package:battery_info/model/iso_battery_info.dart";
  6. import "package:flutter/foundation.dart" show kDebugMode;
  7. import "package:logging/logging.dart";
  8. import "package:photos/core/event_bus.dart";
  9. import "package:photos/events/machine_learning_control_event.dart";
  10. class MachineLearningController {
  11. MachineLearningController._privateConstructor();
  12. static final MachineLearningController instance =
  13. MachineLearningController._privateConstructor();
  14. final _logger = Logger("MachineLearningController");
  15. static const kMaximumTemperature = 42; // 42 degree celsius
  16. static const kMinimumBatteryLevel = 20; // 20%
  17. static const kDefaultInteractionTimeout =
  18. kDebugMode ? Duration(seconds: 3) : Duration(seconds: 5);
  19. static const kUnhealthyStates = ["over_heat", "over_voltage", "dead"];
  20. bool _isDeviceHealthy = true;
  21. bool _isUserInteracting = true;
  22. bool _canRunML = false;
  23. late Timer _userInteractionTimer;
  24. void init() {
  25. if (Platform.isAndroid) {
  26. _startInteractionTimer();
  27. BatteryInfoPlugin()
  28. .androidBatteryInfoStream
  29. .listen((AndroidBatteryInfo? batteryInfo) {
  30. _onAndroidBatteryStateUpdate(batteryInfo);
  31. });
  32. }
  33. if (Platform.isIOS) {
  34. BatteryInfoPlugin()
  35. .iosBatteryInfoStream
  36. .listen((IosBatteryInfo? batteryInfo) {
  37. _oniOSBatteryStateUpdate(batteryInfo);
  38. });
  39. }
  40. _fireControlEvent();
  41. }
  42. void onUserInteraction() {
  43. if (Platform.isIOS) {
  44. return;
  45. }
  46. if (!_isUserInteracting) {
  47. _logger.info("User is interacting with the app");
  48. _isUserInteracting = true;
  49. _fireControlEvent();
  50. }
  51. _resetTimer();
  52. }
  53. void _fireControlEvent() {
  54. final shouldRunML =
  55. _isDeviceHealthy && (Platform.isAndroid ? !_isUserInteracting : true);
  56. if (shouldRunML != _canRunML) {
  57. _canRunML = shouldRunML;
  58. _logger.info(
  59. "Firing event with $shouldRunML, device health: $_isDeviceHealthy and user interaction: $_isUserInteracting",
  60. );
  61. Bus.instance.fire(MachineLearningControlEvent(shouldRunML));
  62. }
  63. }
  64. void _startInteractionTimer({Duration timeout = kDefaultInteractionTimeout}) {
  65. _userInteractionTimer = Timer(timeout, () {
  66. _logger.info("User is not interacting with the app");
  67. _isUserInteracting = false;
  68. _fireControlEvent();
  69. });
  70. }
  71. void _resetTimer() {
  72. _userInteractionTimer.cancel();
  73. _startInteractionTimer();
  74. }
  75. void _onAndroidBatteryStateUpdate(AndroidBatteryInfo? batteryInfo) {
  76. _logger.info("Battery info: ${batteryInfo!.toJson()}");
  77. _isDeviceHealthy = _computeIsAndroidDeviceHealthy(batteryInfo);
  78. _fireControlEvent();
  79. }
  80. void _oniOSBatteryStateUpdate(IosBatteryInfo? batteryInfo) {
  81. _logger.info("Battery info: ${batteryInfo!.toJson()}");
  82. _isDeviceHealthy = _computeIsiOSDeviceHealthy(batteryInfo);
  83. _fireControlEvent();
  84. }
  85. bool _computeIsAndroidDeviceHealthy(AndroidBatteryInfo info) {
  86. return _hasSufficientBattery(info.batteryLevel ?? kMinimumBatteryLevel) &&
  87. _isAcceptableTemperature(info.temperature ?? kMaximumTemperature) &&
  88. _isBatteryHealthy(info.health ?? "");
  89. }
  90. bool _computeIsiOSDeviceHealthy(IosBatteryInfo info) {
  91. return _hasSufficientBattery(info.batteryLevel ?? kMinimumBatteryLevel);
  92. }
  93. bool _hasSufficientBattery(int batteryLevel) {
  94. return batteryLevel >= kMinimumBatteryLevel;
  95. }
  96. bool _isAcceptableTemperature(int temperature) {
  97. return temperature <= kMaximumTemperature;
  98. }
  99. bool _isBatteryHealthy(String health) {
  100. return !kUnhealthyStates.contains(health);
  101. }
  102. }