android-emulator-webrtc 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/api_descriptor.pb +0 -0
  3. package/dist/components/emulator/emulator.js +43 -56
  4. package/dist/components/emulator/net/emulator_status.js +15 -23
  5. package/dist/components/emulator/net/jsep_protocol_driver.js +55 -105
  6. package/dist/components/emulator/net/logcat.js +34 -34
  7. package/dist/components/emulator/views/event_handler.js +57 -75
  8. package/dist/components/emulator/views/resizing_component.js +86 -0
  9. package/dist/components/emulator/views/simple_png_view.js +90 -206
  10. package/dist/components/emulator/views/webrtc_view.js +110 -174
  11. package/dist/index.js +4 -8
  12. package/dist/proto/emulator_controller_grpc_web_pb.js +454 -634
  13. package/dist/proto/emulator_controller_pb.js +4620 -3945
  14. package/dist/proto/emulator_web_client.js +26 -56
  15. package/dist/proto/rtc_service_grpc_web_pb.js +35 -101
  16. package/dist/proto/rtc_service_pb.js +31 -88
  17. package/package.json +25 -21
  18. package/proto/README.MD +1 -1
  19. package/proto/emulator_controller.proto +1090 -804
  20. package/protoc-plugin/grpc_generator.cc +661 -549
  21. package/src/components/emulator/emulator.js +3 -10
  22. package/src/components/emulator/net/jsep_protocol_driver.js +1 -3
  23. package/src/components/emulator/views/resizing_component.js +65 -0
  24. package/src/components/emulator/views/simple_png_view.js +81 -134
  25. package/src/components/emulator/views/webrtc_view.js +87 -95
  26. package/test/emulator.test.js +7 -7
  27. package/test/event_handler.test.js +3 -0
  28. package/test/jsep_protocol_driver.test.js +3 -0
  29. package/test/resizing_component.test.js +37 -0
  30. package/test/simple_png_view.test.js +54 -42
  31. package/test/touch_event_handler.test.js +3 -1
@@ -1,30 +1,17 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports["default"] = void 0;
9
-
10
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
-
12
9
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
-
14
10
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
15
-
16
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
17
-
18
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
19
-
20
13
  var _events = require("events");
21
-
22
14
  var _empty_pb = require("google-protobuf/google/protobuf/empty_pb");
23
-
24
- var _core = require("@material-ui/core");
25
-
26
- var _buffer = require("buffer");
27
-
28
15
  /*
29
16
  * Copyright 2019 The Android Open Source Project
30
17
  *
@@ -40,7 +27,6 @@ var _buffer = require("buffer");
40
27
  * See the License for the specific language governing permissions and
41
28
  * limitations under the License.
42
29
  */
43
-
44
30
  /**
45
31
  * This drives the jsep protocol with the emulator, and can be used to
46
32
  * send key/mouse/touch events to the emulator. Events will be send
@@ -78,21 +64,22 @@ var JsepProtocol = /*#__PURE__*/function () {
78
64
  */
79
65
  function JsepProtocol(emulator, rtc, poll, onConnect, onDisconnect) {
80
66
  var _this = this;
81
-
82
67
  (0, _classCallCheck2["default"])(this, JsepProtocol);
83
68
  (0, _defineProperty2["default"])(this, "on", function (name, fn) {
84
69
  _this.events.on(name, fn);
85
70
  });
71
+ /**
72
+ * Disconnects the stream. This will stop the message pump as well.
73
+ *
74
+ * @memberof JsepProtocol
75
+ */
86
76
  (0, _defineProperty2["default"])(this, "disconnect", function () {
87
77
  _this.connected = false;
88
78
  if (_this.peerConnection) _this.peerConnection.close();
89
-
90
79
  if (_this.stream) {
91
80
  _this.stream.cancel();
92
-
93
81
  _this.stream = null;
94
82
  }
95
-
96
83
  _this.active = false;
97
84
  _this.old_emu_patch = {
98
85
  candidates: [],
@@ -100,9 +87,13 @@ var JsepProtocol = /*#__PURE__*/function () {
100
87
  haveOffer: false,
101
88
  answer: false
102
89
  };
103
-
104
90
  _this.events.emit("disconnected", _this);
105
91
  });
92
+ /**
93
+ * Initiates the JSEP protocol.
94
+ *
95
+ * @memberof JsepProtocol
96
+ */
106
97
  (0, _defineProperty2["default"])(this, "startStream", function () {
107
98
  var self = _this;
108
99
  _this.connected = false;
@@ -115,42 +106,33 @@ var JsepProtocol = /*#__PURE__*/function () {
115
106
  answer: false
116
107
  };
117
108
  var request = new _empty_pb.Empty();
118
-
119
109
  _this.rtc.requestRtcStream(request, {}, function (err, response) {
120
110
  if (err) {
121
111
  console.error("Failed to configure rtc stream: " + JSON.stringify(err));
122
-
123
112
  _this.disconnect();
124
-
125
113
  return;
126
- } // Configure
127
-
114
+ }
128
115
 
116
+ // Configure
129
117
  self.guid = response;
130
118
  self.connected = true;
131
-
132
119
  if (!_this.poll) {
133
120
  // Streaming envoy based.
134
121
  self._streamJsepMessage();
135
122
  } else {
136
123
  // Poll pump messages, go/envoy based proxy.
137
124
  console.debug("Polling jsep messages.");
138
-
139
125
  self._receiveJsepMessage();
140
126
  }
141
127
  });
142
128
  });
143
129
  (0, _defineProperty2["default"])(this, "cleanup", function () {
144
130
  _this.disconnect();
145
-
146
131
  if (_this.peerConnection) {
147
132
  _this.peerConnection.removeEventListener("track", _this._handlePeerConnectionTrack);
148
-
149
133
  _this.peerConnection.removeEventListener("icecandidate", _this._handlePeerIceCandidate);
150
-
151
134
  _this.peerConnection = null;
152
135
  }
153
-
154
136
  _this.event_forwarders = {};
155
137
  });
156
138
  (0, _defineProperty2["default"])(this, "_handlePeerConnectionTrack", function (e) {
@@ -158,21 +140,19 @@ var JsepProtocol = /*#__PURE__*/function () {
158
140
  });
159
141
  (0, _defineProperty2["default"])(this, "_handlePeerConnectionStateChange", function (e) {
160
142
  switch (_this.peerConnection.connectionState) {
161
- case "disconnected": // At least one of the ICE transports for the connection is in the "disconnected" state
143
+ case "disconnected":
144
+ // At least one of the ICE transports for the connection is in the "disconnected" state
162
145
  // and none of the other transports are in the state "failed", "connecting",
163
146
  // or "checking".
164
-
165
- case "failed": // One or more of the ICE transports on the connection is in the "failed" state.
166
-
147
+ case "failed":
148
+ // One or more of the ICE transports on the connection is in the "failed" state.
167
149
  case "closed":
168
150
  //The RTCPeerConnection is closed.
169
151
  _this.disconnect();
170
-
171
152
  }
172
153
  });
173
154
  (0, _defineProperty2["default"])(this, "_handlePeerIceCandidate", function (e) {
174
155
  if (e.candidate === null) return;
175
-
176
156
  _this._sendJsep({
177
157
  candidate: e.candidate
178
158
  });
@@ -193,15 +173,12 @@ var JsepProtocol = /*#__PURE__*/function () {
193
173
  if (!_this.peerConnection) {
194
174
  console.log("Peerconnection no longer available, ignoring signal state.");
195
175
  }
196
-
197
176
  switch (_this.peerConnection.signalingState) {
198
177
  case "have-remote-offer":
199
178
  _this.old_emu_patch.haveOffer = true;
200
-
201
179
  while (_this.old_emu_patch.candidates.length > 0) {
202
180
  _this._handleCandidate(_this.old_emu_patch.candidates.shift());
203
181
  }
204
-
205
182
  break;
206
183
  }
207
184
  });
@@ -209,44 +186,34 @@ var JsepProtocol = /*#__PURE__*/function () {
209
186
  var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(signal) {
210
187
  var answer;
211
188
  return _regenerator["default"].wrap(function _callee$(_context) {
212
- while (1) {
213
- switch (_context.prev = _context.next) {
214
- case 0:
215
- // We should not call this more than once..
216
- _this.old_emu_patch.sdp = null;
217
-
218
- _this.peerConnection.setRemoteDescription(new RTCSessionDescription(signal));
219
-
220
- _context.next = 4;
221
- return _this.peerConnection.createAnswer();
222
-
223
- case 4:
224
- answer = _context.sent;
225
-
226
- if (answer) {
227
- // Older emulators cannot handle multiple answers, so make sure we do not send one
228
- // again.
229
- if (!_this.old_emu_patch.answer) {
230
- _this.old_emu_patch.answer = true;
231
-
232
- _this.peerConnection.setLocalDescription(answer);
233
-
234
- _this._sendJsep({
235
- sdp: answer
236
- });
237
- }
238
- } else {
239
- _this.disconnect();
189
+ while (1) switch (_context.prev = _context.next) {
190
+ case 0:
191
+ // We should not call this more than once..
192
+ _this.old_emu_patch.sdp = null;
193
+ _this.peerConnection.setRemoteDescription(new RTCSessionDescription(signal));
194
+ _context.next = 4;
195
+ return _this.peerConnection.createAnswer();
196
+ case 4:
197
+ answer = _context.sent;
198
+ if (answer) {
199
+ // Older emulators cannot handle multiple answers, so make sure we do not send one
200
+ // again.
201
+ if (!_this.old_emu_patch.answer) {
202
+ _this.old_emu_patch.answer = true;
203
+ _this.peerConnection.setLocalDescription(answer);
204
+ _this._sendJsep({
205
+ sdp: answer
206
+ });
240
207
  }
241
-
242
- case 6:
243
- case "end":
244
- return _context.stop();
245
- }
208
+ } else {
209
+ _this.disconnect();
210
+ }
211
+ case 6:
212
+ case "end":
213
+ return _context.stop();
246
214
  }
247
215
  }, _callee);
248
216
  }));
249
-
250
217
  return function (_x) {
251
218
  return _ref.apply(this, arguments);
252
219
  };
@@ -258,26 +225,21 @@ var JsepProtocol = /*#__PURE__*/function () {
258
225
  if (signal.start) {
259
226
  _this._handleStart(signal);
260
227
  }
261
-
262
228
  if (signal.bye) {
263
229
  _this._handleBye();
264
230
  }
265
-
266
231
  if (signal.sdp && !_this.old_emu_patch.sdp) {
267
232
  _this.old_emu_patch.sdp = signal;
268
233
  }
269
-
270
234
  if (signal.candidate) {
271
235
  _this.old_emu_patch.candidates.push(signal);
272
236
  }
273
-
274
237
  if (!!_this.peerConnection) {
275
238
  // We have created a peer connection..
276
239
  if (_this.old_emu_patch.sdp) {
277
240
  _this._handleSDP(_this.old_emu_patch.sdp);
278
241
  }
279
-
280
- if (_this.haveOffer) {
242
+ if (_this.old_emu_patch.haveOffer) {
281
243
  // We have a remote peer, add the candidates in.
282
244
  while (_this.old_emu_patch.candidates.length > 0) {
283
245
  _this._handleCandidate(_this.old_emu_patch.candidates.shift());
@@ -288,7 +250,6 @@ var JsepProtocol = /*#__PURE__*/function () {
288
250
  (0, _defineProperty2["default"])(this, "_handleJsepMessage", function (message) {
289
251
  try {
290
252
  var signal = JSON.parse(message);
291
-
292
253
  _this._handleSignal(signal);
293
254
  } catch (e) {
294
255
  console.error("Failed to handle message: [" + message + "], due to: " + JSON.stringify(e));
@@ -304,60 +265,52 @@ var JsepProtocol = /*#__PURE__*/function () {
304
265
  var request = new proto.android.emulation.control.JsepMsg();
305
266
  request.setId(_this.guid);
306
267
  request.setMessage(JSON.stringify(jsonObject));
307
-
308
268
  _this.rtc.sendJsepMessage(request);
309
269
  });
310
270
  (0, _defineProperty2["default"])(this, "_streamJsepMessage", function () {
311
271
  if (!_this.connected) return;
312
272
  var self = _this;
313
273
  _this.stream = _this.rtc.receiveJsepMessages(_this.guid, {});
314
-
315
274
  _this.stream.on("data", function (response) {
316
275
  var msg = response.getMessage();
317
-
318
276
  self._handleJsepMessage(msg);
319
277
  });
320
-
321
278
  _this.stream.on("error", function (e) {
322
279
  console.log("Jsep message stream error:", e);
323
-
324
280
  if (self.connected) {
325
281
  console.log("Attempting to reconnect to jsep message stream.");
326
-
327
282
  self._streamJsepMessage();
328
283
  }
329
284
  });
330
-
331
285
  _this.stream.on("end", function (e) {
332
286
  if (self.connected) {
333
287
  console.log("Stream end while still connected.. Reconnecting");
334
-
335
288
  self._streamJsepMessage();
336
289
  }
337
290
  });
338
291
  });
292
+ // This function is a fallback for v1 (go based proxy), that does not support streaming.
339
293
  (0, _defineProperty2["default"])(this, "_receiveJsepMessage", function () {
340
294
  if (!_this.connected) return;
341
- var self = _this; // This is a blocking call, that will return as soon as a series
342
- // of messages have been made available, or if we reach a timeout
295
+ var self = _this;
343
296
 
297
+ // This is a blocking call, that will return as soon as a series
298
+ // of messages have been made available, or if we reach a timeout
344
299
  _this.rtc.receiveJsepMessage(_this.guid, {}, function (err, response) {
345
300
  if (err) {
346
301
  console.error("Failed to receive jsep message, disconnecting: " + JSON.stringify(err));
347
-
348
302
  _this.disconnect();
349
303
  }
350
-
351
- var msg = response.getMessage(); // Handle only if we received a useful message.
304
+ var msg = response.getMessage();
305
+ // Handle only if we received a useful message.
352
306
  // it is possible to get nothing if the server decides
353
307
  // to kick us out.
354
-
355
308
  if (msg) {
356
309
  self._handleJsepMessage(response.getMessage());
357
- } // And pump messages. Note we must continue the message pump as we
358
- // can receive new ICE candidates at any point in time.
359
-
310
+ }
360
311
 
312
+ // And pump messages. Note we must continue the message pump as we
313
+ // can receive new ICE candidates at any point in time.
361
314
  if (self.active) {
362
315
  self._receiveJsepMessage();
363
316
  }
@@ -365,9 +318,10 @@ var JsepProtocol = /*#__PURE__*/function () {
365
318
  });
366
319
  this.emulator = emulator;
367
320
  this.rtc = rtc;
368
- this.events = new _events.EventEmitter(); // Workaround for older emulators that send messages out of order
369
- // and do not handle all answers properly.
321
+ this.events = new _events.EventEmitter();
370
322
 
323
+ // Workaround for older emulators that send messages out of order
324
+ // and do not handle all answers properly.
371
325
  this.old_emu_patch = {
372
326
  candidates: [],
373
327
  sdp: null,
@@ -381,14 +335,13 @@ var JsepProtocol = /*#__PURE__*/function () {
381
335
  if (onConnect) this.events.on("connected", onConnect);
382
336
  if (onDisconnect) this.events.on("disconnected", onDisconnect);
383
337
  }
384
-
385
338
  (0, _createClass2["default"])(JsepProtocol, [{
386
339
  key: "send",
387
340
  value: function send(label, msg) {
388
341
  var bytes = msg.serializeBinary();
389
342
  var forwarder = this.event_forwarders[label];
390
- console.log("Send " + label + " " + JSON.stringify(msg.toObject())); // Send via data channel/gRPC bridge.
391
-
343
+ console.log("Send " + label + " " + JSON.stringify(msg.toObject()));
344
+ // Send via data channel/gRPC bridge.
392
345
  if (this.connected && forwarder && forwarder.readyState == "open") {
393
346
  this.event_forwarders[label].send(bytes);
394
347
  } else {
@@ -397,11 +350,9 @@ var JsepProtocol = /*#__PURE__*/function () {
397
350
  case "mouse":
398
351
  this.emulator.sendMouse(msg);
399
352
  break;
400
-
401
353
  case "keyboard":
402
354
  this.emulator.sendKey(msg);
403
355
  break;
404
-
405
356
  case "touch":
406
357
  this.emulator.sendTouch(msg);
407
358
  break;
@@ -411,5 +362,4 @@ var JsepProtocol = /*#__PURE__*/function () {
411
362
  }]);
412
363
  return JsepProtocol;
413
364
  }();
414
-
415
365
  exports["default"] = JsepProtocol;
@@ -1,22 +1,16 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports["default"] = void 0;
9
-
8
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
9
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
-
12
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
-
14
11
  var _events = require("events");
15
-
16
12
  require("../../../proto/emulator_controller_pb");
17
-
18
13
  var _emulator_web_client = require("../../../proto/emulator_web_client");
19
-
20
14
  /*
21
15
  * Copyright 2019 The Android Open Source Project
22
16
  *
@@ -32,7 +26,6 @@ var _emulator_web_client = require("../../../proto/emulator_web_client");
32
26
  * See the License for the specific language governing permissions and
33
27
  * limitations under the License.
34
28
  */
35
-
36
29
  /**
37
30
  * Observe the logcat stream from the emulator.
38
31
  *
@@ -44,7 +37,7 @@ var _emulator_web_client = require("../../../proto/emulator_web_client");
44
37
  * - `data` whenever new data became available.
45
38
  * - `end` whenever the stream is finished, either because it was stopped, or due to an error.
46
39
  */
47
- var Logcat =
40
+ var Logcat = /*#__PURE__*/(0, _createClass2["default"])(
48
41
  /**
49
42
  * Creates a logcat stream.
50
43
  *
@@ -58,41 +51,53 @@ var Logcat =
58
51
  */
59
52
  function Logcat(uriOrEmulator, auth) {
60
53
  var _this = this;
61
-
62
54
  (0, _classCallCheck2["default"])(this, Logcat);
55
+ /**
56
+ * Register a listener.
57
+ *
58
+ * @param {string} name Name of the event.
59
+ * @param {Callback} fn Function to notify on the given event.
60
+ * @memberof Logcat
61
+ */
63
62
  (0, _defineProperty2["default"])(this, "on", function (name, fn) {
64
63
  _this.events.on(name, fn);
65
64
  });
65
+ /**
66
+ * Removes a listener.
67
+ *
68
+ * @param {string} name Name of the event.
69
+ * @param {Callback} fn Function to notify on the given event.
70
+ * @memberof Logcat
71
+ */
66
72
  (0, _defineProperty2["default"])(this, "off", function (name, fn) {
67
73
  _this.events.off(name, fn);
68
74
  });
75
+ /**
76
+ * Cancel the currently active logcat stream.
77
+ *
78
+ * @memberof Logcat
79
+ */
69
80
  (0, _defineProperty2["default"])(this, "stop", function () {
70
81
  if (_this.stream) {
71
82
  _this.stream.cancel();
72
83
  }
73
-
74
84
  if (_this.timerID) {
75
85
  clearInterval(_this.timerID);
76
86
  _this.timerID = null;
77
87
  }
78
-
79
88
  _this.events.emit("end");
80
89
  });
81
90
  (0, _defineProperty2["default"])(this, "pollStream", function () {
82
91
  var self = _this;
83
92
  /* eslint-disable */
84
-
85
93
  var request = new proto.android.emulation.control.LogMessage();
86
94
  request.setStart(_this.offset);
87
-
88
95
  _this.emulator.getLogcat(request, {}, function (err, response) {
89
96
  if (err) {
90
97
  _this.stop();
91
98
  }
92
-
93
99
  if (response) {
94
100
  var nextOffset = response.getNext();
95
-
96
101
  if (nextOffset > self.offset) {
97
102
  self.offset = response.getNext();
98
103
  self.events.emit("data", response.getContents());
@@ -100,30 +105,37 @@ function Logcat(uriOrEmulator, auth) {
100
105
  }
101
106
  });
102
107
  });
108
+ // Uses streaming, this really locks up the ui, so best not to use for now.
103
109
  (0, _defineProperty2["default"])(this, "stream", function () {
104
110
  var self = _this;
105
111
  /* eslint-disable */
106
-
107
112
  var request = new proto.android.emulation.control.LogMessage();
108
113
  request.setStart(_this.offset);
109
114
  _this.stream = _this.emulator.streamLogcat(request);
110
-
111
115
  _this.stream.on("data", function (response) {
112
116
  self.offset = response.getNext();
113
117
  var contents = response.getContents();
114
118
  self.events.emit("data", contents);
115
119
  });
116
-
117
120
  _this.stream.on("error", function (error) {
118
- if (error.code = 1) {// Ignore we got cancelled.
121
+ if (error.code = 1) {
122
+ // Ignore we got cancelled.
119
123
  }
120
124
  });
121
125
  });
126
+ /**
127
+ * Requests the logcat stream, invoking the callback when a log line arrives.
128
+ *
129
+ * *Note:* Streaming can cause serious UI delays, so best not to use it.
130
+ *
131
+ * @param {Callback} fnNotify when a new log line arrives.
132
+ * @param {number} refreshRate polling interval, or 0 if you wish to use streaming.
133
+ * @memberof Logcat
134
+ */
122
135
  (0, _defineProperty2["default"])(this, "start", function (fnNotify) {
123
136
  var refreshRate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
124
137
  if (fnNotify) _this.on("data", fnNotify);
125
138
  _this.refreshRate = refreshRate;
126
-
127
139
  if (_this.refreshRate > 0) {
128
140
  _this.timerID = setInterval(function () {
129
141
  return _this.pollStream();
@@ -131,31 +143,19 @@ function Logcat(uriOrEmulator, auth) {
131
143
  } else {
132
144
  _this.stream();
133
145
  }
134
-
135
146
  _this.events.emit("start");
136
147
  });
137
-
138
148
  if (uriOrEmulator instanceof _emulator_web_client.EmulatorControllerService) {
139
149
  this.emulator = uriOrEmulator;
140
150
  } else {
141
151
  this.emulator = new _emulator_web_client.EmulatorControllerService(uriOrEmulator, auth);
142
152
  }
143
-
144
153
  this.offset = 0;
145
154
  this.lastline = "";
146
155
  this.stream = null;
147
156
  this.events = new _events.EventEmitter();
148
157
  this.refreshRate = 1000;
149
158
  this.timerID = null;
150
- }
151
- /**
152
- * Register a listener.
153
- *
154
- * @param {string} name Name of the event.
155
- * @param {Callback} fn Function to notify on the given event.
156
- * @memberof Logcat
157
- */
158
- ;
159
-
159
+ });
160
160
  var _default = Logcat;
161
161
  exports["default"] = _default;