123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import "dart:async";
- import "dart:io";
- import "package:battery_info/battery_info_plugin.dart";
- import "package:battery_info/model/android_battery_info.dart";
- import "package:logging/logging.dart";
- import "package:photos/core/event_bus.dart";
- import "package:photos/events/machine_learning_control_event.dart";
- class MachineLearningController {
- MachineLearningController._privateConstructor();
- static final MachineLearningController instance =
- MachineLearningController._privateConstructor();
- final _logger = Logger("MachineLearningController");
- static const kMaximumTemperature = 42; // 42 degree celsius
- static const kMinimumBatteryLevel = 20; // 20%
- static const kDefaultInteractionTimeout = Duration(seconds: 15);
- static const kUnhealthyStates = ["over_heat", "over_voltage", "dead"];
- bool _isDeviceHealthy = true;
- bool _isUserInteracting = true;
- bool _isRunningML = false;
- late Timer _userInteractionTimer;
- get canRunML => _isDeviceHealthy && !_isUserInteracting;
- void init() {
- if (Platform.isAndroid) {
- _startInteractionTimer();
- BatteryInfoPlugin()
- .androidBatteryInfoStream
- .listen((AndroidBatteryInfo? batteryInfo) {
- _onBatteryStateUpdate(batteryInfo);
- });
- } else {
- // Always run Machine Learning on iOS
- Bus.instance.fire(MachineLearningControlEvent(true));
- }
- }
- void onUserInteraction() {
- if (Platform.isIOS) {
- return;
- }
- if (!_isUserInteracting) {
- _logger.info("User is interacting with the app");
- _isUserInteracting = true;
- _fireControlEvent();
- }
- _resetTimer();
- }
- void _fireControlEvent() {
- final shouldRunML = canRunML;
- if (shouldRunML != _isRunningML) {
- _isRunningML = shouldRunML;
- _logger.info(
- "Firing event with device health: $_isDeviceHealthy and user interaction: $_isUserInteracting",
- );
- Bus.instance.fire(MachineLearningControlEvent(shouldRunML));
- }
- }
- void _startInteractionTimer({Duration timeout = kDefaultInteractionTimeout}) {
- _userInteractionTimer = Timer(timeout, () {
- _logger.info("User is not interacting with the app");
- _isUserInteracting = false;
- _fireControlEvent();
- });
- }
- void _resetTimer() {
- _userInteractionTimer.cancel();
- _startInteractionTimer();
- }
- void _onBatteryStateUpdate(AndroidBatteryInfo? batteryInfo) {
- _logger.info("Battery info: ${batteryInfo!.toJson()}");
- _isDeviceHealthy = _computeIsDeviceHealthy(batteryInfo);
- _fireControlEvent();
- }
- bool _computeIsDeviceHealthy(AndroidBatteryInfo info) {
- return _hasSufficientBattery(info.batteryLevel ?? kMinimumBatteryLevel) &&
- _isAcceptableTemperature(info.temperature ?? kMaximumTemperature) &&
- _isBatteryHealthy(info.health ?? "");
- }
- bool _hasSufficientBattery(int batteryLevel) {
- return batteryLevel >= kMinimumBatteryLevel;
- }
- bool _isAcceptableTemperature(int temperature) {
- return temperature <= kMaximumTemperature;
- }
- bool _isBatteryHealthy(String health) {
- return !kUnhealthyStates.contains(health);
- }
- }
|