tiles_ctl.dart 3.95 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../base/process.dart';
6
import '../globals.dart' as globals;
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

import 'fuchsia_device.dart';

// Usage: tiles_ctl <command>
//   Supported commands:
//     start
//     add [--disable-focus] <url> [<args>...]
//     remove <key>
//     list
//     quit

/// A simple wrapper around the 'tiles_ctl' tool running on the Fuchsia device.
class FuchsiaTilesCtl {
  /// Finds the key for the app called [appName], or returns -1 if it can't be
  /// found.
  static Future<int> findAppKey(FuchsiaDevice device, String appName) async {
    final FuchsiaTilesCtl tilesCtl = fuchsiaDeviceTools.tilesCtl;
24
    final Map<int, String>? runningApps = await tilesCtl.list(device);
25
    if (runningApps == null) {
26
      globals.printTrace('tiles_ctl is not running');
27 28
      return -1;
    }
29
    for (final MapEntry<int, String> entry in runningApps.entries) {
30 31 32 33 34 35 36 37 38 39
      if (entry.value.contains('$appName#meta')) {
        return entry.key;
      }
    }
    return -1;
  }

  /// Ensures that tiles is running on the device.
  static Future<bool> ensureStarted(FuchsiaDevice device) async {
    final FuchsiaTilesCtl tilesCtl = fuchsiaDeviceTools.tilesCtl;
40
    final Map<int, String>? runningApps = await tilesCtl.list(device);
41 42 43 44 45 46 47 48 49 50 51 52 53 54
    if (runningApps == null) {
      return tilesCtl.start(device);
    }
    return true;
  }

  /// Instructs 'tiles' to start on the device.
  ///
  /// Returns true on success and false on failure.
  Future<bool> start(FuchsiaDevice device) async {
    final RunResult result = await device.shell('tiles_ctl start');
    return result.exitCode == 0;
  }

55
  /// Returns a mapping of tile keys to app URLs.
56 57 58
  ///
  /// Returns an empty mapping if tiles_ctl is running but no apps are running.
  /// Returns null if tiles_ctl is not running.
59
  Future<Map<int, String>?> list(FuchsiaDevice device) async {
60 61 62 63 64 65 66 67 68 69 70 71 72
    // Output of tiles_ctl list has the format:
    // Found 1 tiles:
    // Tile key 1 url fuchsia-pkg://fuchsia.com/stocks#meta/stocks.cmx ...
    final Map<int, String> tiles = <int, String>{};
    final RunResult result = await device.shell('tiles_ctl list');
    if (result.exitCode != 0) {
      return null;
    }
    // Look for evidence that tiles_ctl is not running.
    if (result.stdout.contains("Couldn't find tiles component in realm")) {
      return null;
    }
    // Find lines beginning with 'Tile'
73
    for (final String line in result.stdout.split('\n')) {
74 75
      final List<String> words = line.split(' ');
      if (words.isNotEmpty && words[0] == 'Tile') {
76 77 78 79 80
        final int? key = int.tryParse(words[2]);
        if (key != null) {
          final String url = words[4];
          tiles[key] = url;
        }
81 82 83 84 85 86 87 88
      }
    }
    return tiles;
  }

  /// Instructs tiles on the device to begin running the app at [url] in a new
  /// tile.
  ///
Chris Bracken's avatar
Chris Bracken committed
89
  /// The app is passed the arguments in [args]. Flutter apps receive these
90
  /// arguments as arguments to `main()`. [url] should be formatted as a
91
  /// Fuchsia-style package URL, e.g.:
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
  ///     fuchsia-pkg://fuchsia.com/flutter_gallery#meta/flutter_gallery.cmx
  /// Returns true on success and false on failure.
  Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
    final RunResult result = await device.shell(
        'tiles_ctl add $url ${args.join(" ")}');
    return result.exitCode == 0;
  }

  /// Instructs tiles on the device to remove the app with key [key].
  ///
  /// Returns true on success and false on failure.
  Future<bool> remove(FuchsiaDevice device, int key) async {
    final RunResult result = await device.shell('tiles_ctl remove $key');
    return result.exitCode == 0;
  }

  /// Instructs tiles on the device to quit.
  ///
  /// Returns true on success and false on failure.
  Future<bool> quit(FuchsiaDevice device) async {
    final RunResult result = await device.shell('tiles_ctl quit');
    return result.exitCode == 0;
  }
}