• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import '../base/process.dart';
6import '../globals.dart';
7
8import 'fuchsia_device.dart';
9
10// Usage: tiles_ctl <command>
11//   Supported commands:
12//     start
13//     add [--disable-focus] <url> [<args>...]
14//     remove <key>
15//     list
16//     quit
17
18/// A simple wrapper around the 'tiles_ctl' tool running on the Fuchsia device.
19class FuchsiaTilesCtl {
20  /// Finds the key for the app called [appName], or returns -1 if it can't be
21  /// found.
22  static Future<int> findAppKey(FuchsiaDevice device, String appName) async {
23    final FuchsiaTilesCtl tilesCtl = fuchsiaDeviceTools.tilesCtl;
24    final Map<int, String> runningApps = await tilesCtl.list(device);
25    if (runningApps == null) {
26      printTrace('tiles_ctl is not running');
27      return -1;
28    }
29    for (MapEntry<int, String> entry in runningApps.entries) {
30      if (entry.value.contains('$appName#meta')) {
31        return entry.key;
32      }
33    }
34    return -1;
35  }
36
37  /// Ensures that tiles is running on the device.
38  static Future<bool> ensureStarted(FuchsiaDevice device) async {
39    final FuchsiaTilesCtl tilesCtl = fuchsiaDeviceTools.tilesCtl;
40    final Map<int, String> runningApps = await tilesCtl.list(device);
41    if (runningApps == null) {
42      return tilesCtl.start(device);
43    }
44    return true;
45  }
46
47  /// Instructs 'tiles' to start on the device.
48  ///
49  /// Returns true on success and false on failure.
50  Future<bool> start(FuchsiaDevice device) async {
51    final RunResult result = await device.shell('tiles_ctl start');
52    return result.exitCode == 0;
53  }
54
55  /// Returns a mapping of tile keys to app urls.
56  ///
57  /// Returns an empty mapping if tiles_ctl is running but no apps are running.
58  /// Returns null if tiles_ctl is not running.
59  Future<Map<int, String>> list(FuchsiaDevice device) async {
60    // Output of tiles_ctl list has the format:
61    // Found 1 tiles:
62    // Tile key 1 url fuchsia-pkg://fuchsia.com/stocks#meta/stocks.cmx ...
63    final Map<int, String> tiles = <int, String>{};
64    final RunResult result = await device.shell('tiles_ctl list');
65    if (result.exitCode != 0) {
66      return null;
67    }
68    // Look for evidence that tiles_ctl is not running.
69    if (result.stdout.contains("Couldn't find tiles component in realm")) {
70      return null;
71    }
72    // Find lines beginning with 'Tile'
73    for (String line in result.stdout.split('\n')) {
74      final List<String> words = line.split(' ');
75      if (words.isNotEmpty && words[0] == 'Tile') {
76        final int key = int.tryParse(words[2]);
77        final String url = words[4];
78        tiles[key] = url;
79      }
80    }
81    return tiles;
82  }
83
84  /// Instructs tiles on the device to begin running the app at [url] in a new
85  /// tile.
86  ///
87  /// The app is passed the arguments in [args]. Flutter apps receive these
88  /// arguments as arguments to `main()`. [url] should be formatted as a
89  /// Fuchsia-style package url, e.g.:
90  ///     fuchsia-pkg://fuchsia.com/flutter_gallery#meta/flutter_gallery.cmx
91  /// Returns true on success and false on failure.
92  Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
93    final RunResult result = await device.shell(
94        'tiles_ctl add $url ${args.join(" ")}');
95    return result.exitCode == 0;
96  }
97
98  /// Instructs tiles on the device to remove the app with key [key].
99  ///
100  /// Returns true on success and false on failure.
101  Future<bool> remove(FuchsiaDevice device, int key) async {
102    final RunResult result = await device.shell('tiles_ctl remove $key');
103    return result.exitCode == 0;
104  }
105
106  /// Instructs tiles on the device to quit.
107  ///
108  /// Returns true on success and false on failure.
109  Future<bool> quit(FuchsiaDevice device) async {
110    final RunResult result = await device.shell('tiles_ctl quit');
111    return result.exitCode == 0;
112  }
113}
114