// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../android/android_builder.dart';
import '../android/android_sdk.dart';
import '../application_package.dart';
import '../base/common.dart' show throwToolExit, unawaited;
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../convert.dart';
import '../device.dart';
import '../device_port_forwarder.dart';
import '../project.dart';
import '../protocol_discovery.dart';

import 'android.dart';
import 'android_console.dart';
import 'android_sdk.dart';
import 'application_package.dart';

/// Whether the [AndroidDevice] is believed to be a physical device or an emulator.
enum HardwareType { emulator, physical }

/// Map to help our `isLocalEmulator` detection.
///
/// See [AndroidDevice] for more explanation of why this is needed.
const Map<String, HardwareType> kKnownHardware = <String, HardwareType>{
  'goldfish': HardwareType.emulator,
  'qcom': HardwareType.physical,
  'ranchu': HardwareType.emulator,
  'samsungexynos7420': HardwareType.physical,
  'samsungexynos7580': HardwareType.physical,
  'samsungexynos7870': HardwareType.physical,
  'samsungexynos7880': HardwareType.physical,
  'samsungexynos8890': HardwareType.physical,
  'samsungexynos8895': HardwareType.physical,
  'samsungexynos9810': HardwareType.physical,
  'samsungexynos7570': HardwareType.physical,
};

/// A physical Android device or emulator.
///
/// While [isEmulator] attempts to distinguish between the device categories,
/// this is a best effort process and not a guarantee; certain physical devices
/// identify as emulators. These device identifiers may be added to the [kKnownHardware]
/// map to specify that they are actually physical devices.
class AndroidDevice extends Device {
  AndroidDevice(
    String id, {
    this.productID,
    required this.modelID,
    this.deviceCodeName,
    required Logger logger,
    required ProcessManager processManager,
    required Platform platform,
    required AndroidSdk androidSdk,
    required FileSystem fileSystem,
    AndroidConsoleSocketFactory androidConsoleSocketFactory = kAndroidConsoleSocketFactory,
  }) : _logger = logger,
       _processManager = processManager,
       _androidSdk = androidSdk,
       _platform = platform,
       _fileSystem = fileSystem,
       _androidConsoleSocketFactory = androidConsoleSocketFactory,
       _processUtils = ProcessUtils(logger: logger, processManager: processManager),
       super(
         id,
         category: Category.mobile,
         platformType: PlatformType.android,
         ephemeral: true,
       );

  final Logger _logger;
  final ProcessManager _processManager;
  final AndroidSdk _androidSdk;
  final Platform _platform;
  final FileSystem _fileSystem;
  final ProcessUtils _processUtils;
  final AndroidConsoleSocketFactory _androidConsoleSocketFactory;

  final String? productID;
  final String modelID;
  final String? deviceCodeName;

  late final Future<Map<String, String>> _properties = () async {
    Map<String, String> properties = <String, String>{};

    final List<String> propCommand = adbCommandForDevice(<String>['shell', 'getprop']);
    _logger.printTrace(propCommand.join(' '));

    try {
      // We pass an encoding of latin1 so that we don't try and interpret the
      // `adb shell getprop` result as UTF8.
      final ProcessResult result = await _processManager.run(
        propCommand,
        stdoutEncoding: latin1,
        stderrEncoding: latin1,
      );
      if (result.exitCode == 0 || _allowHeapCorruptionOnWindows(result.exitCode, _platform)) {
        properties = parseAdbDeviceProperties(result.stdout as String);
      } else {
        _logger.printError('Error ${result.exitCode} retrieving device properties for $name:');
        _logger.printError(result.stderr as String);
      }
    } on ProcessException catch (error) {
      _logger.printError('Error retrieving device properties for $name: $error');
    }
    return properties;
  }();

  Future<String?> _getProperty(String name) async {
    return (await _properties)[name];
  }

  @override
  late final Future<bool> isLocalEmulator = () async {
    final String? hardware = await _getProperty('ro.hardware');
    _logger.printTrace('ro.hardware = $hardware');
    if (kKnownHardware.containsKey(hardware)) {
      // Look for known hardware models.
      return kKnownHardware[hardware] == HardwareType.emulator;
    }
    // Fall back to a best-effort heuristic-based approach.
    final String? characteristics = await _getProperty('ro.build.characteristics');
    _logger.printTrace('ro.build.characteristics = $characteristics');
    return characteristics != null && characteristics.contains('emulator');
  }();

  /// The unique identifier for the emulator that corresponds to this device, or
  /// null if it is not an emulator.
  ///
  /// The ID returned matches that in the output of `flutter emulators`. Fetching
  /// this name may require connecting to the device and if an error occurs null
  /// will be returned.
  @override
  Future<String?> get emulatorId async {
    if (!(await isLocalEmulator)) {
      return null;
    }

    // Emulators always have IDs in the format emulator-(port) where port is the
    // Android Console port number.
    final RegExp emulatorPortRegex = RegExp(r'emulator-(\d+)');

    final Match? portMatch = emulatorPortRegex.firstMatch(id);
    if (portMatch == null || portMatch.groupCount < 1) {
      return null;
    }

    const String host = 'localhost';
    final int port = int.parse(portMatch.group(1)!);
    _logger.printTrace('Fetching avd name for $name via Android console on $host:$port');

    try {
      final Socket socket = await _androidConsoleSocketFactory(host, port);
      final AndroidConsole console = AndroidConsole(socket);

      try {
        await console
            .connect()
            .timeout(const Duration(seconds: 2),
                onTimeout: () => throw TimeoutException('Connection timed out'));

        return await console
            .getAvdName()
            .timeout(const Duration(seconds: 2),
                onTimeout: () => throw TimeoutException('"avd name" timed out'));
      } finally {
        console.destroy();
      }
    } on Exception catch (e) {
      _logger.printTrace('Failed to fetch avd name for emulator at $host:$port: $e');
      // If we fail to connect to the device, we should not fail so just return
      // an empty name. This data is best-effort.
      return null;
    }
  }

  @override
  late final Future<TargetPlatform> targetPlatform = () async {
    // http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...)
    switch (await _getProperty('ro.product.cpu.abi')) {
      case 'arm64-v8a':
        // Perform additional verification for 64 bit ABI. Some devices,
        // like the Kindle Fire 8, misreport the abilist. We might not
        // be able to retrieve this property, in which case we fall back
        // to assuming 64 bit.
        final String? abilist = await _getProperty('ro.product.cpu.abilist');
        if (abilist == null || abilist.contains('arm64-v8a')) {
          return TargetPlatform.android_arm64;
        } else {
          return TargetPlatform.android_arm;
        }
      case 'x86_64':
        return TargetPlatform.android_x64;
      case 'x86':
        return TargetPlatform.android_x86;
      default:
        return TargetPlatform.android_arm;
    }
  }();

  @override
  Future<bool> supportsRuntimeMode(BuildMode buildMode) async {
    switch (await targetPlatform) {
      case TargetPlatform.android_arm:
      case TargetPlatform.android_arm64:
      case TargetPlatform.android_x64:
        return buildMode != BuildMode.jitRelease;
      case TargetPlatform.android_x86:
        return buildMode == BuildMode.debug;
      case TargetPlatform.android:
      case TargetPlatform.darwin:
      case TargetPlatform.fuchsia_arm64:
      case TargetPlatform.fuchsia_x64:
      case TargetPlatform.ios:
      case TargetPlatform.linux_arm64:
      case TargetPlatform.linux_x64:
      case TargetPlatform.tester:
      case TargetPlatform.web_javascript:
      case TargetPlatform.windows_uwp_x64:
      case TargetPlatform.windows_x64:
        throw UnsupportedError('Invalid target platform for Android');
    }
  }

  @override
  Future<String> get sdkNameAndVersion async => 'Android ${await _sdkVersion} (API ${await apiVersion})';

  Future<String?> get _sdkVersion => _getProperty('ro.build.version.release');

  @visibleForTesting
  Future<String?> get apiVersion => _getProperty('ro.build.version.sdk');

  AdbLogReader? _logReader;
  AdbLogReader? _pastLogReader;

  List<String> adbCommandForDevice(List<String> args) {
    return <String>[_androidSdk.adbPath!, '-s', id, ...args];
  }

  Future<RunResult> runAdbCheckedAsync(
    List<String> params, {
    String? workingDirectory,
    bool allowReentrantFlutter = false,
  }) async {
    return _processUtils.run(
      adbCommandForDevice(params),
      throwOnError: true,
      workingDirectory: workingDirectory,
      allowReentrantFlutter: allowReentrantFlutter,
      allowedFailures: (int value) => _allowHeapCorruptionOnWindows(value, _platform),
    );
  }

  bool _isValidAdbVersion(String adbVersion) {
    // Sample output: 'Android Debug Bridge version 1.0.31'
    final Match? versionFields = RegExp(r'(\d+)\.(\d+)\.(\d+)').firstMatch(adbVersion);
    if (versionFields != null) {
      final int majorVersion = int.parse(versionFields[1]!);
      final int minorVersion = int.parse(versionFields[2]!);
      final int patchVersion = int.parse(versionFields[3]!);
      if (majorVersion > 1) {
        return true;
      }
      if (majorVersion == 1 && minorVersion > 0) {
        return true;
      }
      if (majorVersion == 1 && minorVersion == 0 && patchVersion >= 39) {
        return true;
      }
      return false;
    }
    _logger.printError(
        'Unrecognized adb version string $adbVersion. Skipping version check.');
    return true;
  }

  Future<bool> _checkForSupportedAdbVersion() async {
    final String? adbPath = _androidSdk.adbPath;
    if (adbPath == null) {
      return false;
    }

    try {
      final RunResult adbVersion = await _processUtils.run(
        <String>[adbPath, 'version'],
        throwOnError: true,
      );
      if (_isValidAdbVersion(adbVersion.stdout)) {
        return true;
      }
      _logger.printError('The ADB at "$adbPath" is too old; please install version 1.0.39 or later.');
    } on Exception catch (error, trace) {
      _logger.printError('Error running ADB: $error', stackTrace: trace);
    }

    return false;
  }

  Future<bool> _checkForSupportedAndroidVersion() async {
    final String? adbPath = _androidSdk.adbPath;
    if (adbPath == null) {
      return false;
    }
    try {
      // If the server is automatically restarted, then we get irrelevant
      // output lines like this, which we want to ignore:
      //   adb server is out of date.  killing..
      //   * daemon started successfully *
      await _processUtils.run(
        <String>[adbPath, 'start-server'],
        throwOnError: true,
      );

      // This has been reported to return null on some devices. In this case,
      // assume the lowest supported API to still allow Flutter to run.
      // Sample output: '22'
      final String sdkVersion = await _getProperty('ro.build.version.sdk')
        ?? minApiLevel.toString();

      final int? sdkVersionParsed = int.tryParse(sdkVersion);
      if (sdkVersionParsed == null) {
        _logger.printError('Unexpected response from getprop: "$sdkVersion"');
        return false;
      }

      if (sdkVersionParsed < minApiLevel) {
        _logger.printError(
          'The Android version ($sdkVersion) on the target device is too old. Please '
          'use a $minVersionName (version $minApiLevel / $minVersionText) device or later.');
        return false;
      }

      return true;
    } on Exception catch (e, stacktrace) {
      _logger.printError('Unexpected failure from adb: $e');
      _logger.printError('Stacktrace: $stacktrace');
      return false;
    }
  }

  String _getDeviceSha1Path(AndroidApk apk) {
    return '/data/local/tmp/sky.${apk.id}.sha1';
  }

  Future<String> _getDeviceApkSha1(AndroidApk apk) async {
    final RunResult result = await _processUtils.run(
      adbCommandForDevice(<String>['shell', 'cat', _getDeviceSha1Path(apk)]));
    return result.stdout;
  }

  String _getSourceSha1(AndroidApk apk) {
    final File shaFile = _fileSystem.file('${apk.applicationPackage.path}.sha1');
    return shaFile.existsSync() ? shaFile.readAsStringSync() : '';
  }

  @override
  String get name => modelID;

  @override
  Future<bool> isAppInstalled(
    AndroidApk app, {
    String? userIdentifier,
  }) async {
    // This call takes 400ms - 600ms.
    try {
      final RunResult listOut = await runAdbCheckedAsync(<String>[
        'shell',
        'pm',
        'list',
        'packages',
        if (userIdentifier != null)
          ...<String>['--user', userIdentifier],
        app.id
      ]);
      return LineSplitter.split(listOut.stdout).contains('package:${app.id}');
    } on Exception catch (error) {
      _logger.printTrace('$error');
      return false;
    }
  }

  @override
  Future<bool> isLatestBuildInstalled(AndroidApk app) async {
    final String installedSha1 = await _getDeviceApkSha1(app);
    return installedSha1.isNotEmpty && installedSha1 == _getSourceSha1(app);
  }

  @override
  Future<bool> installApp(
    AndroidApk app, {
    String? userIdentifier,
  }) async {
    if (!await _adbIsValid) {
      return false;
    }
    final bool wasInstalled = await isAppInstalled(app, userIdentifier: userIdentifier);
    if (wasInstalled && await isLatestBuildInstalled(app)) {
      _logger.printTrace('Latest build already installed.');
      return true;
    }
    _logger.printTrace('Installing APK.');
    if (await _installApp(app, userIdentifier: userIdentifier)) {
      return true;
    }
    _logger.printTrace('Warning: Failed to install APK.');
    if (!wasInstalled) {
      return false;
    }
    _logger.printStatus('Uninstalling old version...');
    if (!await uninstallApp(app, userIdentifier: userIdentifier)) {
      _logger.printError('Error: Uninstalling old version failed.');
      return false;
    }
    if (!await _installApp(app, userIdentifier: userIdentifier)) {
      _logger.printError('Error: Failed to install APK again.');
      return false;
    }
    return true;
  }

  Future<bool> _installApp(
    AndroidApk app, {
    String? userIdentifier,
  }) async {
    if (!app.applicationPackage.existsSync()) {
      _logger.printError('"${_fileSystem.path.relative(app.applicationPackage.path)}" does not exist.');
      return false;
    }

    final Status status = _logger.startProgress(
      'Installing ${_fileSystem.path.relative(app.applicationPackage.path)}...',
    );
    final RunResult installResult = await _processUtils.run(
      adbCommandForDevice(<String>[
        'install',
        '-t',
        '-r',
        if (userIdentifier != null)
          ...<String>['--user', userIdentifier],
        app.applicationPackage.path
      ]));
    status.stop();
    // Some versions of adb exit with exit code 0 even on failure :(
    // Parsing the output to check for failures.
    final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true);
    final String? failure = failureExp.stringMatch(installResult.stdout);
    if (failure != null) {
      _logger.printError('Package install error: $failure');
      return false;
    }
    if (installResult.exitCode != 0) {
      if (installResult.stderr.contains('Bad user number')) {
        _logger.printError('Error: User "$userIdentifier" not found. Run "adb shell pm list users" to see list of available identifiers.');
      } else {
        _logger.printError('Error: ADB exited with exit code ${installResult.exitCode}');
        _logger.printError('$installResult');
      }
      return false;
    }
    try {
      await runAdbCheckedAsync(<String>[
        'shell', 'echo', '-n', _getSourceSha1(app), '>', _getDeviceSha1Path(app),
      ]);
    } on ProcessException catch (error) {
      _logger.printError('adb shell failed to write the SHA hash: $error.');
      return false;
    }
    return true;
  }

  @override
  Future<bool> uninstallApp(
    AndroidApk app, {
    String? userIdentifier,
  }) async {
    if (!await _adbIsValid) {
      return false;
    }

    String uninstallOut;
    try {
      final RunResult uninstallResult = await _processUtils.run(
        adbCommandForDevice(<String>[
          'uninstall',
          if (userIdentifier != null)
            ...<String>['--user', userIdentifier],
          app.id]),
        throwOnError: true,
      );
      uninstallOut = uninstallResult.stdout;
    } on Exception catch (error) {
      _logger.printError('adb uninstall failed: $error');
      return false;
    }
    final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true);
    final String? failure = failureExp.stringMatch(uninstallOut);
    if (failure != null) {
      _logger.printError('Package uninstall error: $failure');
      return false;
    }
    return true;
  }

  // Whether the adb and Android versions are aligned.
  late final Future<bool> _adbIsValid = () async {
    return await _checkForSupportedAdbVersion() && await _checkForSupportedAndroidVersion();
  }();

  AndroidApk? _package;

  @override
  Future<LaunchResult> startApp(
    AndroidApk package, {
    String? mainPath,
    String? route,
    required DebuggingOptions debuggingOptions,
    Map<String, Object?> platformArgs = const <String, Object>{},
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String? userIdentifier,
  }) async {
    if (!await _adbIsValid) {
      return LaunchResult.failed();
    }

    final TargetPlatform devicePlatform = await targetPlatform;
    if (devicePlatform == TargetPlatform.android_x86 &&
       !debuggingOptions.buildInfo.isDebug) {
      _logger.printError('Profile and release builds are only supported on ARM/x64 targets.');
      return LaunchResult.failed();
    }

    AndroidApk? builtPackage = package;
    AndroidArch androidArch;
    switch (devicePlatform) {
      case TargetPlatform.android_arm:
        androidArch = AndroidArch.armeabi_v7a;
        break;
      case TargetPlatform.android_arm64:
        androidArch = AndroidArch.arm64_v8a;
        break;
      case TargetPlatform.android_x64:
        androidArch = AndroidArch.x86_64;
        break;
      case TargetPlatform.android_x86:
        androidArch = AndroidArch.x86;
        break;
      case TargetPlatform.android:
      case TargetPlatform.darwin:
      case TargetPlatform.fuchsia_arm64:
      case TargetPlatform.fuchsia_x64:
      case TargetPlatform.ios:
      case TargetPlatform.linux_arm64:
      case TargetPlatform.linux_x64:
      case TargetPlatform.tester:
      case TargetPlatform.web_javascript:
      case TargetPlatform.windows_uwp_x64:
      case TargetPlatform.windows_x64:
        _logger.printError('Android platforms are only supported.');
        return LaunchResult.failed();
    }

    if (!prebuiltApplication || _androidSdk.licensesAvailable && _androidSdk.latestVersion == null) {
      _logger.printTrace('Building APK');
      final FlutterProject project = FlutterProject.current();
      await androidBuilder!.buildApk(
          project: project,
          target: mainPath ?? 'lib/main.dart',
          androidBuildInfo: AndroidBuildInfo(
            debuggingOptions.buildInfo,
            targetArchs: <AndroidArch>[androidArch],
            fastStart: debuggingOptions.fastStart,
            multidexEnabled: (platformArgs['multidex'] as bool?) ?? false,
          ),
      );
      // Package has been built, so we can get the updated application ID and
      // activity name from the .apk.
      builtPackage = await ApplicationPackageFactory.instance!
        .getPackageForPlatform(devicePlatform, buildInfo: debuggingOptions.buildInfo) as AndroidApk?;
    }
    // There was a failure parsing the android project information.
    if (builtPackage == null) {
      throwToolExit('Problem building Android application: see above error(s).');
    }

    _logger.printTrace("Stopping app '${builtPackage.name}' on $name.");
    await stopApp(builtPackage, userIdentifier: userIdentifier);

    if (!await installApp(builtPackage, userIdentifier: userIdentifier)) {
      return LaunchResult.failed();
    }

    final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
    ProtocolDiscovery? observatoryDiscovery;

    if (debuggingOptions.debuggingEnabled) {
      observatoryDiscovery = ProtocolDiscovery.observatory(
        // Avoid using getLogReader, which returns a singleton instance, because the
        // observatory discovery will dipose at the end. creating a new logger here allows
        // logs to be surfaced normally during `flutter drive`.
        await AdbLogReader.createLogReader(
          this,
          _processManager,
        ),
        portForwarder: portForwarder,
        hostPort: debuggingOptions.hostVmServicePort,
        devicePort: debuggingOptions.deviceVmServicePort,
        ipv6: ipv6,
        logger: _logger,
      );
    }

    final String dartVmFlags = computeDartVmFlags(debuggingOptions);
    final String? traceAllowlist = debuggingOptions.traceAllowlist;
    final String? traceSkiaAllowlist = debuggingOptions.traceSkiaAllowlist;
    final List<String> cmd = <String>[
      'shell', 'am', 'start',
      '-a', 'android.intent.action.RUN',
      '-f', '0x20000000', // FLAG_ACTIVITY_SINGLE_TOP
      '--ez', 'enable-dart-profiling', 'true',
      if (traceStartup)
        ...<String>['--ez', 'trace-startup', 'true'],
      if (route != null)
        ...<String>['--es', 'route', route],
      if (debuggingOptions.enableSoftwareRendering)
        ...<String>['--ez', 'enable-software-rendering', 'true'],
      if (debuggingOptions.skiaDeterministicRendering)
        ...<String>['--ez', 'skia-deterministic-rendering', 'true'],
      if (debuggingOptions.traceSkia)
        ...<String>['--ez', 'trace-skia', 'true'],
      if (traceAllowlist != null)
        ...<String>['--es', 'trace-allowlist', traceAllowlist],
      if (traceSkiaAllowlist != null)
        ...<String>['--es', 'trace-skia-allowlist', traceSkiaAllowlist],
      if (debuggingOptions.traceSystrace)
        ...<String>['--ez', 'trace-systrace', 'true'],
      if (debuggingOptions.endlessTraceBuffer)
        ...<String>['--ez', 'endless-trace-buffer', 'true'],
      if (debuggingOptions.dumpSkpOnShaderCompilation)
        ...<String>['--ez', 'dump-skp-on-shader-compilation', 'true'],
      if (debuggingOptions.cacheSkSL)
      ...<String>['--ez', 'cache-sksl', 'true'],
      if (debuggingOptions.purgePersistentCache)
        ...<String>['--ez', 'purge-persistent-cache', 'true'],
      if (debuggingOptions.debuggingEnabled) ...<String>[
        if (debuggingOptions.buildInfo.isDebug) ...<String>[
          ...<String>['--ez', 'enable-checked-mode', 'true'],
          ...<String>['--ez', 'verify-entry-points', 'true'],
        ],
        if (debuggingOptions.startPaused)
          ...<String>['--ez', 'start-paused', 'true'],
        if (debuggingOptions.disableServiceAuthCodes)
          ...<String>['--ez', 'disable-service-auth-codes', 'true'],
        if (dartVmFlags.isNotEmpty)
          ...<String>['--es', 'dart-flags', dartVmFlags],
        if (debuggingOptions.useTestFonts)
          ...<String>['--ez', 'use-test-fonts', 'true'],
        if (debuggingOptions.verboseSystemLogs)
          ...<String>['--ez', 'verbose-logging', 'true'],
        if (userIdentifier != null)
          ...<String>['--user', userIdentifier],
      ],
      builtPackage.launchActivity,
    ];
    final String result = (await runAdbCheckedAsync(cmd)).stdout;
    // This invocation returns 0 even when it fails.
    if (result.contains('Error: ')) {
      _logger.printError(result.trim(), wrap: false);
      return LaunchResult.failed();
    }

    _package = builtPackage;
    if (!debuggingOptions.debuggingEnabled) {
      return LaunchResult.succeeded();
    }

    // Wait for the service protocol port here. This will complete once the
    // device has printed "Observatory is listening on...".
    _logger.printTrace('Waiting for observatory port to be available...');
    try {
      Uri? observatoryUri;
      if (debuggingOptions.buildInfo.isDebug || debuggingOptions.buildInfo.isProfile) {
        observatoryUri = await observatoryDiscovery?.uri;
        if (observatoryUri == null) {
          _logger.printError(
            'Error waiting for a debug connection: '
            'The log reader stopped unexpectedly',
          );
          return LaunchResult.failed();
        }
      }
      return LaunchResult.succeeded(observatoryUri: observatoryUri);
    } on Exception catch (error) {
      _logger.printError('Error waiting for a debug connection: $error');
      return LaunchResult.failed();
    } finally {
      await observatoryDiscovery?.cancel();
    }
  }

  @override
  bool get supportsHotReload => true;

  @override
  bool get supportsHotRestart => true;

  @override
  bool get supportsFastStart => true;

  @override
  Future<bool> stopApp(
    AndroidApk app, {
    String? userIdentifier,
  }) {
    if (app == null) {
      return Future<bool>.value(false);
    }
    final List<String> command = adbCommandForDevice(<String>[
      'shell',
      'am',
      'force-stop',
      if (userIdentifier != null)
        ...<String>['--user', userIdentifier],
      app.id,
    ]);
    return _processUtils.stream(command).then<bool>(
        (int exitCode) => exitCode == 0 || _allowHeapCorruptionOnWindows(exitCode, _platform));
  }

  @override
  Future<MemoryInfo> queryMemoryInfo() async {
    final AndroidApk? package = _package;
    if (package == null) {
      _logger.printError('Android package unknown, skipping dumpsys meminfo.');
      return const MemoryInfo.empty();
    }
    final RunResult runResult = await _processUtils.run(adbCommandForDevice(<String>[
      'shell',
      'dumpsys',
      'meminfo',
      package.id,
      '-d',
    ]));

    if (runResult.exitCode != 0) {
      return const MemoryInfo.empty();
    }
    return parseMeminfoDump(runResult.stdout);
  }

  @override
  void clearLogs() {
    _processUtils.runSync(adbCommandForDevice(<String>['logcat', '-c']));
  }

  @override
  FutureOr<DeviceLogReader> getLogReader({
    AndroidApk? app,
    bool includePastLogs = false,
  }) async {
    // The Android log reader isn't app-specific. The `app` parameter isn't used.
    if (includePastLogs) {
      return _pastLogReader ??= await AdbLogReader.createLogReader(
        this,
        _processManager,
        includePastLogs: true,
      );
    } else {
      return _logReader ??= await AdbLogReader.createLogReader(
        this,
        _processManager,
      );
    }
  }

  @override
  late final DevicePortForwarder? portForwarder = () {
    final String? adbPath = _androidSdk.adbPath;
    if (adbPath == null) {
      return null;
    }
    return AndroidDevicePortForwarder(
      processManager: _processManager,
      logger: _logger,
      deviceId: id,
      adbPath: adbPath,
    );
  }();

  static final RegExp _timeRegExp = RegExp(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}', multiLine: true);

  /// Return the most recent timestamp in the Android log or [null] if there is
  /// no available timestamp. The format can be passed to logcat's -T option.
  @visibleForTesting
  Future<String?> lastLogcatTimestamp() async {
    RunResult output;
    try {
      output = await runAdbCheckedAsync(<String>[
        'shell', '-x', 'logcat', '-v', 'time', '-t', '1'
      ]);
    } on Exception catch (error) {
      _logger.printError('Failed to extract the most recent timestamp from the Android log: $error.');
      return null;
    }
    final Match? timeMatch = _timeRegExp.firstMatch(output.stdout);
    return timeMatch?.group(0);
  }

  @override
  bool isSupported() => true;

  @override
  bool get supportsScreenshot => true;

  @override
  Future<void> takeScreenshot(File outputFile) async {
    const String remotePath = '/data/local/tmp/flutter_screenshot.png';
    await runAdbCheckedAsync(<String>['shell', 'screencap', '-p', remotePath]);
    await _processUtils.run(
      adbCommandForDevice(<String>['pull', remotePath, outputFile.path]),
      throwOnError: true,
    );
    await runAdbCheckedAsync(<String>['shell', 'rm', remotePath]);
  }

  @override
  bool isSupportedForProject(FlutterProject flutterProject) {
    return flutterProject.android.existsSync();
  }

  @override
  Future<void> dispose() async {
    _logReader?._stop();
    _pastLogReader?._stop();
  }
}

Map<String, String> parseAdbDeviceProperties(String str) {
  final Map<String, String> properties = <String, String>{};
  final RegExp propertyExp = RegExp(r'\[(.*?)\]: \[(.*?)\]');
  for (final Match match in propertyExp.allMatches(str)) {
    properties[match.group(1)!] = match.group(2)!;
  }
  return properties;
}

/// Process the dumpsys info formatted in a table-like structure.
///
/// Currently this only pulls information from the  "App Summary" subsection.
///
/// Example output:
///
/// ```
/// Applications Memory Usage (in Kilobytes):
/// Uptime: 441088659 Realtime: 521464097
///
/// ** MEMINFO in pid 16141 [io.flutter.demo.gallery] **
///                    Pss  Private  Private  SwapPss     Heap     Heap     Heap
///                  Total    Dirty    Clean    Dirty     Size    Alloc     Free
///                 ------   ------   ------   ------   ------   ------   ------
///   Native Heap     8648     8620        0       16    20480    12403     8076
///   Dalvik Heap      547      424       40       18     2628     1092     1536
///  Dalvik Other      464      464        0        0
///         Stack      496      496        0        0
///        Ashmem        2        0        0        0
///       Gfx dev      212      204        0        0
///     Other dev       48        0       48        0
///      .so mmap    10770      708     9372       25
///     .apk mmap      240        0        0        0
///     .ttf mmap       35        0       32        0
///     .dex mmap     2205        4     1172        0
///     .oat mmap       64        0        0        0
///     .art mmap     4228     3848       24        2
///    Other mmap    20713        4    20704        0
///     GL mtrack     2380     2380        0        0
///       Unknown    43971    43968        0        1
///         TOTAL    95085    61120    31392       62    23108    13495     9612
///
///  App Summary
///                        Pss(KB)
///                         ------
///            Java Heap:     4296
///          Native Heap:     8620
///                 Code:    11288
///                Stack:      496
///             Graphics:     2584
///        Private Other:    65228
///               System:     2573
///
///                TOTAL:    95085       TOTAL SWAP PSS:       62
///
///  Objects
///                Views:        9         ViewRootImpl:        1
///          AppContexts:        3           Activities:        1
///              Assets:        4        AssetManagers:        3
///        Local Binders:       10        Proxy Binders:       18
///        Parcel memory:        6         Parcel count:       24
///     Death Recipients:        0      OpenSSL Sockets:        0
///             WebViews:        0
///
///  SQL
///          MEMORY_USED:        0
///   PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0
/// ...
/// ```
///
/// For more information, see https://developer.android.com/studio/command-line/dumpsys.
@visibleForTesting
AndroidMemoryInfo parseMeminfoDump(String input) {
  final AndroidMemoryInfo androidMemoryInfo = AndroidMemoryInfo();

  final List<String> lines = input.split('\n');

  final String timelineData = lines.firstWhere((String line) =>
    line.startsWith('${AndroidMemoryInfo._kUpTimeKey}: '));
  final List<String> times = timelineData.trim().split('${AndroidMemoryInfo._kRealTimeKey}:');
  androidMemoryInfo.realTime = int.tryParse(times.last.trim()) ?? 0;

  lines
    .skipWhile((String line) => !line.contains('App Summary'))
    .takeWhile((String line) => !line.contains('TOTAL'))
    .where((String line) => line.contains(':'))
    .forEach((String line) {
      final List<String> sections = line.trim().split(':');
      final String key = sections.first.trim();
      final int value = int.tryParse(sections.last.trim()) ?? 0;
      switch (key) {
        case AndroidMemoryInfo._kJavaHeapKey:
          androidMemoryInfo.javaHeap = value;
          break;
        case AndroidMemoryInfo._kNativeHeapKey:
          androidMemoryInfo.nativeHeap = value;
          break;
        case AndroidMemoryInfo._kCodeKey:
          androidMemoryInfo.code = value;
          break;
        case AndroidMemoryInfo._kStackKey:
          androidMemoryInfo.stack = value;
          break;
        case AndroidMemoryInfo._kGraphicsKey:
          androidMemoryInfo.graphics = value;
          break;
        case AndroidMemoryInfo._kPrivateOtherKey:
          androidMemoryInfo.privateOther = value;
          break;
        case AndroidMemoryInfo._kSystemKey:
          androidMemoryInfo.system = value;
          break;
      }
  });
  return androidMemoryInfo;
}

/// Android specific implementation of memory info.
class AndroidMemoryInfo extends MemoryInfo {
  static const String _kUpTimeKey = 'Uptime';
  static const String _kRealTimeKey = 'Realtime';
  static const String _kJavaHeapKey = 'Java Heap';
  static const String _kNativeHeapKey = 'Native Heap';
  static const String _kCodeKey = 'Code';
  static const String _kStackKey = 'Stack';
  static const String _kGraphicsKey = 'Graphics';
  static const String _kPrivateOtherKey = 'Private Other';
  static const String _kSystemKey = 'System';
  static const String _kTotalKey = 'Total';

  // Realtime is time since the system was booted includes deep sleep. Clock
  // is monotonic, and ticks even when the CPU is in power saving modes.
  int realTime = 0;

  // Each measurement has KB as a unit.
  int javaHeap = 0;
  int nativeHeap = 0;
  int code = 0;
  int stack = 0;
  int graphics = 0;
  int privateOther = 0;
  int system = 0;

  @override
  Map<String, Object> toJson() {
    return <String, Object>{
      'platform': 'Android',
      _kRealTimeKey: realTime,
      _kJavaHeapKey: javaHeap,
      _kNativeHeapKey: nativeHeap,
      _kCodeKey: code,
      _kStackKey: stack,
      _kGraphicsKey: graphics,
      _kPrivateOtherKey: privateOther,
      _kSystemKey: system,
      _kTotalKey: javaHeap + nativeHeap + code + stack + graphics + privateOther + system,
    };
  }
}

/// A log reader that logs from `adb logcat`.
class AdbLogReader extends DeviceLogReader {
  AdbLogReader._(this._adbProcess, this.name);

  @visibleForTesting
  factory AdbLogReader.test(Process adbProcess, String name) = AdbLogReader._;

  /// Create a new [AdbLogReader] from an [AndroidDevice] instance.
  static Future<AdbLogReader> createLogReader(
    AndroidDevice device,
    ProcessManager processManager, {
    bool includePastLogs = false,
  }) async {
    // logcat -T is not supported on Android releases before Lollipop.
    const int kLollipopVersionCode = 21;
    final int? apiVersion = (String? v) {
      // If the API version string isn't found, conservatively assume that the
      // version is less recent than the one we're looking for.
      return v == null ? kLollipopVersionCode - 1 : int.tryParse(v);
    }(await device.apiVersion);

    // Start the adb logcat process and filter the most recent logs since `lastTimestamp`.
    // Some devices (notably LG) will only output logcat via shell
    // https://github.com/flutter/flutter/issues/51853
    final List<String> args = <String>[
      'shell',
      '-x',
      'logcat',
      '-v',
      'time',
    ];

    // If past logs are included then filter for 'flutter' logs only.
    if (includePastLogs) {
      args.addAll(<String>['-s', 'flutter']);
    } else if (apiVersion != null && apiVersion >= kLollipopVersionCode) {
      // Otherwise, filter for logs appearing past the present.
      // '-T 0` means the timestamp of the logcat command invocation.
      final String? lastLogcatTimestamp = await device.lastLogcatTimestamp();
      args.addAll(<String>[
        '-T',
        if (lastLogcatTimestamp != null) "'$lastLogcatTimestamp'" else '0',
      ]);
    }
    final Process process = await processManager.start(device.adbCommandForDevice(args));
    return AdbLogReader._(process, device.name);
  }

  final Process _adbProcess;

  @override
  final String name;

  late final StreamController<String> _linesController = StreamController<String>.broadcast(
    onListen: _start,
    onCancel: _stop,
  );

  @override
  Stream<String> get logLines => _linesController.stream;

  void _start() {
    // We expect logcat streams to occasionally contain invalid utf-8,
    // see: https://github.com/flutter/flutter/pull/8864.
    const Utf8Decoder decoder = Utf8Decoder(reportErrors: false);
    _adbProcess.stdout.transform<String>(decoder)
      .transform<String>(const LineSplitter())
      .listen(_onLine);
    _adbProcess.stderr.transform<String>(decoder)
      .transform<String>(const LineSplitter())
      .listen(_onLine);
    unawaited(_adbProcess.exitCode.whenComplete(() {
      if (_linesController.hasListener) {
        _linesController.close();
      }
    }));
  }

  // 'W/ActivityManager(pid): '
  static final RegExp _logFormat = RegExp(r'^[VDIWEF]\/.*?\(\s*(\d+)\):\s');

  static final List<RegExp> _allowedTags = <RegExp>[
    RegExp(r'^[VDIWEF]\/flutter[^:]*:\s+', caseSensitive: false),
    RegExp(r'^[IE]\/DartVM[^:]*:\s+'),
    RegExp(r'^[WEF]\/AndroidRuntime:\s+'),
    RegExp(r'^[WEF]\/AndroidRuntime\([0-9]+\):\s+'),
    RegExp(r'^[WEF]\/ActivityManager:\s+.*(\bflutter\b|\bdomokit\b|\bsky\b)'),
    RegExp(r'^[WEF]\/System\.err:\s+'),
    RegExp(r'^[F]\/[\S^:]+:\s+'),
  ];

  // 'F/libc(pid): Fatal signal 11'
  static final RegExp _fatalLog = RegExp(r'^F\/libc\s*\(\s*\d+\):\sFatal signal (\d+)');

  // 'I/DEBUG(pid): ...'
  static final RegExp _tombstoneLine = RegExp(r'^[IF]\/DEBUG\s*\(\s*\d+\):\s(.+)$');

  // 'I/DEBUG(pid): Tombstone written to: '
  static final RegExp _tombstoneTerminator = RegExp(r'^Tombstone written to:\s');

  // we default to true in case none of the log lines match
  bool _acceptedLastLine = true;

  // Whether a fatal crash is happening or not.
  // During a fatal crash only lines from the crash are accepted, the rest are
  // dropped.
  bool _fatalCrash = false;

  // The format of the line is controlled by the '-v' parameter passed to
  // adb logcat. We are currently passing 'time', which has the format:
  // mm-dd hh:mm:ss.milliseconds Priority/Tag( PID): ....
  void _onLine(String line) {
    // This line might be processed after the subscription is closed but before
    // adb stops streaming logs.
    if (_linesController.isClosed) {
      return;
    }
    final Match? timeMatch = AndroidDevice._timeRegExp.firstMatch(line);
    if (timeMatch == null || line.length == timeMatch.end) {
      _acceptedLastLine = false;
      return;
    }
    // Chop off the time.
    line = line.substring(timeMatch.end + 1);
    final Match? logMatch = _logFormat.firstMatch(line);
    if (logMatch != null) {
      bool acceptLine = false;

      if (_fatalCrash) {
        // While a fatal crash is going on, only accept lines from the crash
        // Otherwise the crash log in the console may get interrupted

        final Match? fatalMatch = _tombstoneLine.firstMatch(line);

        if (fatalMatch != null) {
          acceptLine = true;

          line = fatalMatch[1]!;

          if (_tombstoneTerminator.hasMatch(line)) {
            // Hit crash terminator, stop logging the crash info
            _fatalCrash = false;
          }
        }
      } else if (appPid != null && int.parse(logMatch.group(1)!) == appPid) {
        acceptLine = true;

        if (_fatalLog.hasMatch(line)) {
          // Hit fatal signal, app is now crashing
          _fatalCrash = true;
        }
      } else {
        // Filter on approved names and levels.
        acceptLine = _allowedTags.any((RegExp re) => re.hasMatch(line));
      }

      if (acceptLine) {
        _acceptedLastLine = true;
        _linesController.add(line);
        return;
      }
      _acceptedLastLine = false;
    } else if (line == '--------- beginning of system' ||
               line == '--------- beginning of main') {
      // hide the ugly adb logcat log boundaries at the start
      _acceptedLastLine = false;
    } else {
      // If it doesn't match the log pattern at all, then pass it through if we
      // passed the last matching line through. It might be a multiline message.
      if (_acceptedLastLine) {
        _linesController.add(line);
        return;
      }
    }
  }

  void _stop() {
    _linesController.close();
    _adbProcess.kill();
  }

  @override
  void dispose() {
    _stop();
  }
}

/// A [DevicePortForwarder] implemented for Android devices that uses adb.
class AndroidDevicePortForwarder extends DevicePortForwarder {
  AndroidDevicePortForwarder({
    required ProcessManager processManager,
    required Logger logger,
    required String deviceId,
    required String adbPath,
  }) : _deviceId = deviceId,
       _adbPath = adbPath,
       _logger = logger,
       _processUtils = ProcessUtils(logger: logger, processManager: processManager);

  final String _deviceId;
  final String _adbPath;
  final Logger _logger;
  final ProcessUtils _processUtils;

  static int? _extractPort(String portString) {
    return int.tryParse(portString.trim());
  }

  @override
  List<ForwardedPort> get forwardedPorts {
    final List<ForwardedPort> ports = <ForwardedPort>[];

    String stdout;
    try {
      stdout = _processUtils.runSync(
        <String>[
          _adbPath,
          '-s',
          _deviceId,
          'forward',
          '--list',
        ],
        throwOnError: true,
      ).stdout.trim();
    } on ProcessException catch (error) {
      _logger.printError('Failed to list forwarded ports: $error.');
      return ports;
    }

    final List<String> lines = LineSplitter.split(stdout).toList();
    for (final String line in lines) {
      if (!line.startsWith(_deviceId)) {
        continue;
      }
      final List<String> splitLine = line.split('tcp:');

      // Sanity check splitLine.
      if (splitLine.length != 3) {
        continue;
      }

      // Attempt to extract ports.
      final int? hostPort = _extractPort(splitLine[1]);
      final int? devicePort = _extractPort(splitLine[2]);

      // Failed, skip.
      if (hostPort == null || devicePort == null) {
        continue;
      }

      ports.add(ForwardedPort(hostPort, devicePort));
    }

    return ports;
  }

  @override
  Future<int> forward(int devicePort, { int? hostPort }) async {
    hostPort ??= 0;
    final RunResult process = await _processUtils.run(
      <String>[
        _adbPath,
        '-s',
        _deviceId,
        'forward',
        'tcp:$hostPort',
        'tcp:$devicePort',
      ],
      throwOnError: true,
    );

    if (process.stderr.isNotEmpty) {
      process.throwException('adb returned error:\n${process.stderr}');
    }

    if (process.exitCode != 0) {
      if (process.stdout.isNotEmpty) {
        process.throwException('adb returned error:\n${process.stdout}');
      }
      process.throwException('adb failed without a message');
    }

    if (hostPort == 0) {
      if (process.stdout.isEmpty) {
        process.throwException('adb did not report forwarded port');
      }
      hostPort = int.tryParse(process.stdout);
      if (hostPort == null) {
        process.throwException('adb returned invalid port number:\n${process.stdout}');
      }
    } else {
      // stdout may be empty or the port we asked it to forward, though it's
      // not documented (or obvious) what triggers each case.
      //
      // Observations are:
      //   - On MacOS it's always empty when Flutter spawns the process, but
      //   - On MacOS it prints the port number when run from the terminal, unless
      //     the port is already forwarded, when it also prints nothing.
      //   - On ChromeOS, the port appears to be printed even when Flutter spawns
      //     the process
      //
      // To cover all cases, we accept the output being either empty or exactly
      // the port number, but treat any other output as probably being an error
      // message.
      if (process.stdout.isNotEmpty && process.stdout.trim() != '$hostPort') {
        process.throwException('adb returned error:\n${process.stdout}');
      }
    }

    return hostPort!;
  }

  @override
  Future<void> unforward(ForwardedPort forwardedPort) async {
    final String tcpLine = 'tcp:${forwardedPort.hostPort}';
    final RunResult runResult = await _processUtils.run(
      <String>[
        _adbPath,
        '-s',
        _deviceId,
        'forward',
        '--remove',
        tcpLine,
      ],
    );
    if (runResult.exitCode == 0) {
      return;
    }
    _logger.printError('Failed to unforward port: $runResult');
  }

  @override
  Future<void> dispose() async {
    for (final ForwardedPort port in forwardedPorts) {
      await unforward(port);
    }
  }
}

// In platform tools 29.0.0 adb.exe seems to be ending with this heap
// corruption error code on seemingly successful termination. Ignore
// this error on windows.
bool _allowHeapCorruptionOnWindows(int exitCode, Platform platform) {
  return exitCode == -1073740940 && platform.isWindows;
}
