Commit 00c7734c authored by Jason Simmons's avatar Jason Simmons

Tools daemon handlers for discovering apps and forwarding device ports (#4324)

parent 8ec26f02
......@@ -513,6 +513,28 @@ class AndroidDevice extends Device {
return new Future<bool>.value(true);
}
@override
Future<List<DiscoveredApp>> discoverApps() {
RegExp discoverExp = new RegExp(r'DISCOVER: (.*)');
List<DiscoveredApp> result = <DiscoveredApp>[];
StreamSubscription<String> logs = logReader.logLines.listen((String line) {
Match match = discoverExp.firstMatch(line);
if (match != null) {
Map<String, dynamic> app = JSON.decode(match.group(1));
result.add(new DiscoveredApp(app['id'], app['observatoryPort']));
}
});
runCheckedSync(adbCommandForDevice(<String>[
'shell', 'am', 'broadcast', '-a', 'io.flutter.view.DISCOVER'
]));
return new Future<List<DiscoveredApp>>.delayed(new Duration(seconds: 1), () {
logs.cancel();
return result;
});
}
}
// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
......
......@@ -237,6 +237,23 @@ class DaemonDomain extends Domain {
}
}
/// Return the device matching the deviceId field in the args.
Future<Device> _getDevice(Daemon daemon, Map<String, dynamic> args) async {
if (args == null || args['deviceId'] is! String)
throw 'deviceId is required';
List<Device> devices = await daemon.deviceDomain.getDevices();
Device device = devices.firstWhere(
(Device device) => device.id == args['deviceId'],
orElse: () => null
);
if (device == null)
throw "device '${args['deviceId']}' not found";
return device;
}
/// This domain responds to methods like [start] and [stop].
///
/// It'll be extended to fire events for when applications start, stop, and
......@@ -245,14 +262,11 @@ class AppDomain extends Domain {
AppDomain(Daemon daemon) : super(daemon, 'app') {
registerHandler('start', start);
registerHandler('stop', stop);
registerHandler('discover', discover);
}
Future<dynamic> start(Map<String, dynamic> args) async {
if (args == null || args['deviceId'] is! String)
throw "deviceId is required";
Device device = await _getDevice(args['deviceId']);
if (device == null)
throw "device '${args['deviceId']}' not found";
Device device = await _getDevice(daemon, args);
if (args['projectDirectory'] is! String)
throw "projectDirectory is required";
......@@ -282,12 +296,8 @@ class AppDomain extends Domain {
return null;
}
Future<bool> stop(dynamic args) async {
if (args == null || args['deviceId'] is! String)
throw "deviceId is required";
Device device = await _getDevice(args['deviceId']);
if (device == null)
throw "device '${args['deviceId']}' not found";
Future<bool> stop(Map<String, dynamic> args) async {
Device device = await _getDevice(daemon, args);
if (args['projectDirectory'] is! String)
throw "projectDirectory is required";
......@@ -306,9 +316,12 @@ class AppDomain extends Domain {
}
}
Future<Device> _getDevice(String deviceId) async {
List<Device> devices = await daemon.deviceDomain.getDevices();
return devices.firstWhere((Device device) => device.id == deviceId, orElse: () => null);
Future<List<Map<String, dynamic>>> discover(Map<String, dynamic> args) async {
Device device = await _getDevice(daemon, args);
List<DiscoveredApp> apps = await device.discoverApps();
return apps.map((DiscoveredApp app) =>
<String, dynamic>{'id': app.id, 'observatoryDevicePort': app.observatoryPort}
).toList();
}
}
......@@ -321,6 +334,8 @@ class DeviceDomain extends Domain {
registerHandler('getDevices', getDevices);
registerHandler('enable', enable);
registerHandler('disable', disable);
registerHandler('forward', forward);
registerHandler('unforward', unforward);
PollingDeviceDiscovery deviceDiscovery = new AndroidDevices();
if (deviceDiscovery.supportsPlatform)
......@@ -369,6 +384,36 @@ class DeviceDomain extends Domain {
return new Future<Null>.value();
}
/// Forward a host port to a device port.
Future<Map<String, dynamic>> forward(Map<String, dynamic> args) async {
Device device = await _getDevice(daemon, args);
if (args['devicePort'] is! int)
throw 'devicePort is required';
int devicePort = args['devicePort'];
int hostPort = args['hostPort'];
hostPort = await device.portForwarder.forward(devicePort, hostPort: hostPort);
return <String, dynamic>{'hostPort': hostPort};
}
/// Removes a forwarded port.
Future<Null> unforward(Map<String, dynamic> args) async {
Device device = await _getDevice(daemon, args);
if (args['devicePort'] is! int)
throw 'devicePort is required';
int devicePort = args['devicePort'];
if (args['hostPort'] is! int)
throw 'hostPort is required';
int hostPort = args['hostPort'];
device.portForwarder.unforward(new ForwardedPort(hostPort, devicePort));
}
@override
void dispose() {
for (PollingDeviceDiscovery discoverer in _discoverers) {
......
......@@ -205,6 +205,10 @@ abstract class Device {
Future<bool> takeScreenshot(File outputFile) => new Future<bool>.error('unimplemented');
/// Find the apps that are currently running on this device.
Future<List<DiscoveredApp>> discoverApps() =>
new Future<List<DiscoveredApp>>.value(<DiscoveredApp>[]);
@override
int get hashCode => id.hashCode;
......@@ -333,3 +337,10 @@ abstract class DeviceLogReader {
@override
String toString() => name;
}
/// Describes an app running on the device.
class DiscoveredApp {
DiscoveredApp(this.id, this.observatoryPort);
final String id;
final int observatoryPort;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment