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 { ...@@ -513,6 +513,28 @@ class AndroidDevice extends Device {
return new Future<bool>.value(true); 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 // 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
......
...@@ -237,6 +237,23 @@ class DaemonDomain extends Domain { ...@@ -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]. /// This domain responds to methods like [start] and [stop].
/// ///
/// It'll be extended to fire events for when applications start, stop, and /// It'll be extended to fire events for when applications start, stop, and
...@@ -245,14 +262,11 @@ class AppDomain extends Domain { ...@@ -245,14 +262,11 @@ class AppDomain extends Domain {
AppDomain(Daemon daemon) : super(daemon, 'app') { AppDomain(Daemon daemon) : super(daemon, 'app') {
registerHandler('start', start); registerHandler('start', start);
registerHandler('stop', stop); registerHandler('stop', stop);
registerHandler('discover', discover);
} }
Future<dynamic> start(Map<String, dynamic> args) async { Future<dynamic> start(Map<String, dynamic> args) async {
if (args == null || args['deviceId'] is! String) Device device = await _getDevice(daemon, args);
throw "deviceId is required";
Device device = await _getDevice(args['deviceId']);
if (device == null)
throw "device '${args['deviceId']}' not found";
if (args['projectDirectory'] is! String) if (args['projectDirectory'] is! String)
throw "projectDirectory is required"; throw "projectDirectory is required";
...@@ -282,12 +296,8 @@ class AppDomain extends Domain { ...@@ -282,12 +296,8 @@ class AppDomain extends Domain {
return null; return null;
} }
Future<bool> stop(dynamic args) async { Future<bool> stop(Map<String, dynamic> args) async {
if (args == null || args['deviceId'] is! String) Device device = await _getDevice(daemon, args);
throw "deviceId is required";
Device device = await _getDevice(args['deviceId']);
if (device == null)
throw "device '${args['deviceId']}' not found";
if (args['projectDirectory'] is! String) if (args['projectDirectory'] is! String)
throw "projectDirectory is required"; throw "projectDirectory is required";
...@@ -306,9 +316,12 @@ class AppDomain extends Domain { ...@@ -306,9 +316,12 @@ class AppDomain extends Domain {
} }
} }
Future<Device> _getDevice(String deviceId) async { Future<List<Map<String, dynamic>>> discover(Map<String, dynamic> args) async {
List<Device> devices = await daemon.deviceDomain.getDevices(); Device device = await _getDevice(daemon, args);
return devices.firstWhere((Device device) => device.id == deviceId, orElse: () => null); 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 { ...@@ -321,6 +334,8 @@ class DeviceDomain extends Domain {
registerHandler('getDevices', getDevices); registerHandler('getDevices', getDevices);
registerHandler('enable', enable); registerHandler('enable', enable);
registerHandler('disable', disable); registerHandler('disable', disable);
registerHandler('forward', forward);
registerHandler('unforward', unforward);
PollingDeviceDiscovery deviceDiscovery = new AndroidDevices(); PollingDeviceDiscovery deviceDiscovery = new AndroidDevices();
if (deviceDiscovery.supportsPlatform) if (deviceDiscovery.supportsPlatform)
...@@ -369,6 +384,36 @@ class DeviceDomain extends Domain { ...@@ -369,6 +384,36 @@ class DeviceDomain extends Domain {
return new Future<Null>.value(); 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 @override
void dispose() { void dispose() {
for (PollingDeviceDiscovery discoverer in _discoverers) { for (PollingDeviceDiscovery discoverer in _discoverers) {
......
...@@ -205,6 +205,10 @@ abstract class Device { ...@@ -205,6 +205,10 @@ abstract class Device {
Future<bool> takeScreenshot(File outputFile) => new Future<bool>.error('unimplemented'); 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 @override
int get hashCode => id.hashCode; int get hashCode => id.hashCode;
...@@ -333,3 +337,10 @@ abstract class DeviceLogReader { ...@@ -333,3 +337,10 @@ abstract class DeviceLogReader {
@override @override
String toString() => name; 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