blob: e626e2eff0bf4cf1298378195f9dabe4bf4216cc [file] [log] [blame]
// 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 '../base/process.dart';
import '../globals.dart' as globals;
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;
final Map<int, String>? runningApps = await tilesCtl.list(device);
if (runningApps == null) {
globals.printTrace('tiles_ctl is not running');
return -1;
}
for (final MapEntry<int, String> entry in runningApps.entries) {
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;
final Map<int, String>? runningApps = await tilesCtl.list(device);
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;
}
/// Returns a mapping of tile keys to app URLs.
///
/// Returns an empty mapping if tiles_ctl is running but no apps are running.
/// Returns null if tiles_ctl is not running.
Future<Map<int, String>?> list(FuchsiaDevice device) async {
// 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'
for (final String line in result.stdout.split('\n')) {
final List<String> words = line.split(' ');
if (words.isNotEmpty && words[0] == 'Tile') {
final int? key = int.tryParse(words[2]);
if (key != null) {
final String url = words[4];
tiles[key] = url;
}
}
}
return tiles;
}
/// Instructs tiles on the device to begin running the app at [url] in a new
/// tile.
///
/// The app is passed the arguments in [args]. Flutter apps receive these
/// arguments as arguments to `main()`. [url] should be formatted as a
/// Fuchsia-style package URL, e.g.:
/// 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;
}
}