android-emulator-webrtc 1.0.17 → 2.0.1

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 (72) hide show
  1. package/README.md +93 -204
  2. package/dist/components/emulator/emulator.d.ts +64 -0
  3. package/dist/components/emulator/emulator.js +161 -173
  4. package/dist/components/emulator/net/emulator_status.d.ts +45 -0
  5. package/dist/components/emulator/net/emulator_status.js +35 -42
  6. package/dist/components/emulator/net/logcat.js +37 -54
  7. package/dist/components/emulator/net/logger.d.ts +7 -0
  8. package/dist/components/emulator/net/logger.js +20 -0
  9. package/dist/components/emulator/net/ws_jsep_protocol_driver.d.ts +213 -0
  10. package/dist/components/emulator/net/ws_jsep_protocol_driver.js +640 -0
  11. package/dist/components/emulator/views/event_handler.d.ts +37 -0
  12. package/dist/components/emulator/views/event_handler.js +274 -260
  13. package/dist/components/emulator/views/webrtc_view.d.ts +27 -0
  14. package/dist/components/emulator/views/webrtc_view.js +42 -25
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.js +0 -7
  17. package/dist/proto/emulator_controller_pb.d.ts +1 -0
  18. package/dist/proto/emulator_controller_pb.js +146 -287
  19. package/dist/src/components/emulator/emulator.d.ts +64 -0
  20. package/dist/src/components/emulator/net/emulator_status.d.ts +45 -0
  21. package/dist/src/components/emulator/net/logger.d.ts +7 -0
  22. package/dist/src/components/emulator/net/ws_jsep_protocol_driver.d.ts +213 -0
  23. package/dist/src/components/emulator/views/event_handler.d.ts +37 -0
  24. package/dist/src/components/emulator/views/webrtc_view.d.ts +27 -0
  25. package/dist/src/index.d.ts +8 -0
  26. package/dist/src/proto/emulator_controller_pb.d.ts +1 -0
  27. package/package.json +17 -18
  28. package/proto/emulator_controller.proto +746 -181
  29. package/.vscode/launch.json +0 -21
  30. package/.vscode/settings.json +0 -3
  31. package/CONTRIBUTING.md +0 -28
  32. package/Makefile +0 -123
  33. package/android-emulator-webrtc.code-workspace +0 -7
  34. package/api_descriptor.pb +0 -0
  35. package/babel.config.js +0 -16
  36. package/cloudbuild.yaml +0 -41
  37. package/cloudbuilders/.gcloudignore +0 -1
  38. package/cloudbuilders/Dockerfile +0 -20
  39. package/cloudbuilders/README.md +0 -29
  40. package/cloudbuilders/cloudbuild.yaml +0 -19
  41. package/dist/components/emulator/net/jsep_protocol_driver.js +0 -365
  42. package/dist/components/emulator/views/resizing_component.js +0 -86
  43. package/dist/components/emulator/views/simple_png_view.js +0 -111
  44. package/dist/proto/emulator_controller_grpc_web_pb.js +0 -1601
  45. package/dist/proto/emulator_web_client.js +0 -176
  46. package/dist/proto/rtc_service_grpc_web_pb.js +0 -231
  47. package/dist/proto/rtc_service_pb.js +0 -338
  48. package/emulator/index.js +0 -1
  49. package/eslint_prefix.py +0 -37
  50. package/gen_md_doc.js +0 -40
  51. package/npmrc.enc +0 -0
  52. package/proto/rtc_service.proto +0 -117
  53. package/protoc-plugin/Makefile +0 -31
  54. package/protoc-plugin/grpc_generator.cc +0 -1755
  55. package/src/components/emulator/emulator.js +0 -217
  56. package/src/components/emulator/net/emulator_status.js +0 -94
  57. package/src/components/emulator/net/jsep_protocol_driver.js +0 -364
  58. package/src/components/emulator/net/logcat.js +0 -155
  59. package/src/components/emulator/views/event_handler.js +0 -268
  60. package/src/components/emulator/views/resizing_component.js +0 -65
  61. package/src/components/emulator/views/simple_png_view.js +0 -106
  62. package/src/components/emulator/views/webrtc_view.js +0 -146
  63. package/src/index.js +0 -20
  64. package/src/proto/emulator_web_client.js +0 -140
  65. package/test/cloudbuild.yaml +0 -41
  66. package/test/emulator.test.js +0 -125
  67. package/test/event_handler.test.js +0 -91
  68. package/test/fake_events.js +0 -50
  69. package/test/jsep_protocol_driver.test.js +0 -228
  70. package/test/resizing_component.test.js +0 -37
  71. package/test/simple_png_view.test.js +0 -145
  72. package/test/touch_event_handler.test.js +0 -118
@@ -9,8 +9,6 @@ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/creat
9
9
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _events = require("events");
12
- require("../../../proto/emulator_controller_pb");
13
- var _emulator_web_client = require("../../../proto/emulator_web_client");
14
12
  /*
15
13
  * Copyright 2019 The Android Open Source Project
16
14
  *
@@ -29,7 +27,7 @@ var _emulator_web_client = require("../../../proto/emulator_web_client");
29
27
  /**
30
28
  * Observe the logcat stream from the emulator.
31
29
  *
32
- * Streaming is done by either polling the emulator endpoint or making a streaming call.
30
+ * Streaming is done by polling the emulator REST endpoint.
33
31
  *
34
32
  * It will send out the following events:
35
33
  *
@@ -46,10 +44,10 @@ var Logcat = /*#__PURE__*/(0, _createClass2["default"])(
46
44
  * - `unauthorized()` a function that gets called when a 401 was received.
47
45
  *
48
46
  * @constructor
49
- * @param {object} uriOrEmulator
50
- * @param {object} auth
47
+ * @param {string} logcatUrl Full REST URL to the logcat endpoint.
48
+ * @param {object} auth Authentication helper.
51
49
  */
52
- function Logcat(uriOrEmulator, auth) {
50
+ function Logcat(logcatUrl, auth) {
53
51
  var _this = this;
54
52
  (0, _classCallCheck2["default"])(this, Logcat);
55
53
  /**
@@ -78,9 +76,6 @@ function Logcat(uriOrEmulator, auth) {
78
76
  * @memberof Logcat
79
77
  */
80
78
  (0, _defineProperty2["default"])(this, "stop", function () {
81
- if (_this.stream) {
82
- _this.stream.cancel();
83
- }
84
79
  if (_this.timerID) {
85
80
  clearInterval(_this.timerID);
86
81
  _this.timerID = null;
@@ -89,70 +84,58 @@ function Logcat(uriOrEmulator, auth) {
89
84
  });
90
85
  (0, _defineProperty2["default"])(this, "pollStream", function () {
91
86
  var self = _this;
92
- /* eslint-disable */
93
- var request = new proto.android.emulation.control.LogMessage();
94
- request.setStart(_this.offset);
95
- _this.emulator.getLogcat(request, {}, function (err, response) {
96
- if (err) {
97
- _this.stop();
87
+ var url = new URL(_this.logcatUrl);
88
+ url.searchParams.append("start", _this.offset);
89
+ var headers = {
90
+ "Accept": "application/json"
91
+ };
92
+ if (_this.auth && _this.auth.authHeader) {
93
+ Object.assign(headers, _this.auth.authHeader());
94
+ }
95
+ fetch(url.toString(), {
96
+ headers: headers
97
+ }).then(function (res) {
98
+ if (res.status === 401 && _this.auth && _this.auth.unauthorized) {
99
+ _this.auth.unauthorized();
98
100
  }
99
- if (response) {
100
- var nextOffset = response.getNext();
101
- if (nextOffset > self.offset) {
102
- self.offset = response.getNext();
103
- self.events.emit("data", response.getContents());
104
- }
101
+ if (!res.ok) {
102
+ throw new Error("HTTP error " + res.status);
105
103
  }
106
- });
107
- });
108
- // Uses streaming, this really locks up the ui, so best not to use for now.
109
- (0, _defineProperty2["default"])(this, "stream", function () {
110
- var self = _this;
111
- /* eslint-disable */
112
- var request = new proto.android.emulation.control.LogMessage();
113
- request.setStart(_this.offset);
114
- _this.stream = _this.emulator.streamLogcat(request);
115
- _this.stream.on("data", function (response) {
116
- self.offset = response.getNext();
117
- var contents = response.getContents();
118
- self.events.emit("data", contents);
119
- });
120
- _this.stream.on("error", function (error) {
121
- if (error.code = 1) {
122
- // Ignore we got cancelled.
104
+ return res.json();
105
+ }).then(function (response) {
106
+ var nextOffset = response.next;
107
+ if (nextOffset > self.offset) {
108
+ self.offset = nextOffset;
109
+ self.events.emit("data", response.contents);
123
110
  }
111
+ })["catch"](function (err) {
112
+ console.error("Logcat error:", err);
113
+ _this.stop();
124
114
  });
125
115
  });
126
116
  /**
127
117
  * Requests the logcat stream, invoking the callback when a log line arrives.
128
118
  *
129
- * *Note:* Streaming can cause serious UI delays, so best not to use it.
130
- *
131
119
  * @param {Callback} fnNotify when a new log line arrives.
132
- * @param {number} refreshRate polling interval, or 0 if you wish to use streaming.
120
+ * @param {number} refreshRate polling interval. Must be > 0.
133
121
  * @memberof Logcat
134
122
  */
135
123
  (0, _defineProperty2["default"])(this, "start", function (fnNotify) {
136
124
  var refreshRate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;
137
125
  if (fnNotify) _this.on("data", fnNotify);
138
126
  _this.refreshRate = refreshRate;
139
- if (_this.refreshRate > 0) {
140
- _this.timerID = setInterval(function () {
141
- return _this.pollStream();
142
- }, _this.refreshRate);
143
- } else {
144
- _this.stream();
127
+ if (_this.refreshRate <= 0) {
128
+ console.warn("Streaming logcat is no longer supported. Falling back to 1000ms polling.");
129
+ _this.refreshRate = 1000;
145
130
  }
131
+ _this.timerID = setInterval(function () {
132
+ return _this.pollStream();
133
+ }, _this.refreshRate);
146
134
  _this.events.emit("start");
147
135
  });
148
- if (uriOrEmulator instanceof _emulator_web_client.EmulatorControllerService) {
149
- this.emulator = uriOrEmulator;
150
- } else {
151
- this.emulator = new _emulator_web_client.EmulatorControllerService(uriOrEmulator, auth);
152
- }
136
+ this.logcatUrl = logcatUrl;
137
+ this.auth = auth;
153
138
  this.offset = 0;
154
- this.lastline = "";
155
- this.stream = null;
156
139
  this.events = new _events.EventEmitter();
157
140
  this.refreshRate = 1000;
158
141
  this.timerID = null;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fileoverview Configures and exports a loglevel logger instance scoped to
3
+ * the 'android-emulator-webrtc' package.
4
+ */
5
+ import log from "loglevel";
6
+ declare const logger: log.Logger;
7
+ export default logger;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _loglevel = _interopRequireDefault(require("loglevel"));
9
+ /**
10
+ * @fileoverview Configures and exports a loglevel logger instance scoped to
11
+ * the 'android-emulator-webrtc' package.
12
+ */
13
+
14
+ // Create a logger specific to the emulator package
15
+ var logger = _loglevel["default"].getLogger("android-emulator-webrtc");
16
+
17
+ // Default to "info" level so that verbose signaling (debug) is hidden by default,
18
+ // but warnings and errors are still printed.
19
+ logger.setDefaultLevel("info");
20
+ var _default = exports["default"] = logger;
@@ -0,0 +1,213 @@
1
+ export interface WsJsepConfig {
2
+ enableLogging?: boolean;
3
+ onError?: (error: Error | Event) => void;
4
+ maxReconnectAttempts?: number;
5
+ reconnectDelay?: number;
6
+ reconnectBackoffFactor?: number;
7
+ [key: string]: any;
8
+ }
9
+ export interface StreamCallbacks {
10
+ onConnected?: (track: MediaStreamTrack) => void;
11
+ onDisconnected?: (driver: WsJsepProtocol) => void;
12
+ }
13
+ export interface EmulatorController {
14
+ sendMouse?(msg: any): void;
15
+ sendKey?(msg: any): void;
16
+ sendTouch?(msg: any): void;
17
+ }
18
+ export interface JsepSignal {
19
+ start?: RTCConfiguration;
20
+ type?: "offer" | "answer";
21
+ sdp?: RTCSessionDescriptionInit | string;
22
+ candidate?: RTCIceCandidateInit | string;
23
+ bye?: boolean;
24
+ }
25
+ /**
26
+ * A JSEP protocol driver that uses WebSockets for signaling.
27
+ *
28
+ * @export
29
+ * @class WsJsepProtocol
30
+ */
31
+ export default class WsJsepProtocol {
32
+ wsUrl: string;
33
+ emulator: EmulatorController | null;
34
+ config: WsJsepConfig;
35
+ onError?: (error: Error | Event) => void;
36
+ maxReconnectAttempts: number;
37
+ reconnectDelay: number;
38
+ reconnectBackoffFactor: number;
39
+ connected: boolean;
40
+ event_forwarders: Record<string, RTCDataChannel>;
41
+ peerConnection: RTCPeerConnection | null;
42
+ ws: WebSocket | null;
43
+ pendingCandidates: (RTCIceCandidateInit | string)[];
44
+ remoteDescriptionSet: boolean;
45
+ signalQueue: JsepSignal[];
46
+ isProcessingSignal: boolean;
47
+ onConnected: ((track: MediaStreamTrack) => void) | null;
48
+ onDisconnected: ((driver: WsJsepProtocol) => void) | null;
49
+ reconnectAttempts: number;
50
+ reconnectTimeoutId: any | null;
51
+ /**
52
+ * Creates an instance of WsJsepProtocol.
53
+ *
54
+ * @param wsUrl The WebSocket JSEP signaling URL.
55
+ * @param emulator Fallback emulator controller for sending events when WebRTC is unavailable.
56
+ * @param config Configuration options.
57
+ */
58
+ constructor(wsUrl: string, emulator?: EmulatorController | null, config?: WsJsepConfig);
59
+ /**
60
+ * Establishes the WebSocket connection and starts the signaling process.
61
+ * Cleans up any existing connection beforehand.
62
+ *
63
+ * @param callbacks Callbacks for stream lifecycle events.
64
+ */
65
+ startStream: (callbacks?: StreamCallbacks) => void;
66
+ /**
67
+ * Internal method to establish WebSocket connection.
68
+ *
69
+ * @private
70
+ */
71
+ _connect: () => void;
72
+ /**
73
+ * Queues a reconnection attempt with exponential backoff.
74
+ *
75
+ * @private
76
+ */
77
+ _queueReconnect: () => void;
78
+ /**
79
+ * Internal handler for incoming WebSocket messages. Parses the signal
80
+ * and queues it for sequential processing.
81
+ *
82
+ * @private
83
+ * @param event The WebSocket message event.
84
+ */
85
+ _handleWsMessage: (event: MessageEvent) => void;
86
+ /**
87
+ * Sequentially processes JSEP signals from the queue.
88
+ *
89
+ * @private
90
+ */
91
+ _processSignalQueue: () => Promise<void>;
92
+ /**
93
+ * Handles WebSocket connection close events.
94
+ *
95
+ * @private
96
+ * @param event The WebSocket close event.
97
+ */
98
+ _handleWsClose: (event: CloseEvent) => void;
99
+ /**
100
+ * Handles WebSocket error events.
101
+ *
102
+ * @private
103
+ * @param error The WebSocket error event.
104
+ */
105
+ _handleWsError: (error: Event) => void;
106
+ /**
107
+ * Processes a single JSEP signal (e.g., start, offer, answer, candidate, bye).
108
+ *
109
+ * @private
110
+ * @param signal The JSEP signaling message.
111
+ */
112
+ _handleSignal: (signal: JsepSignal) => Promise<void>;
113
+ /**
114
+ * Initializes the RTCPeerConnection and local data channels based on the start configuration.
115
+ *
116
+ * @private
117
+ * @param config The signaling start configuration.
118
+ */
119
+ _handleStart: (config: RTCConfiguration) => Promise<void>;
120
+ /**
121
+ * Handles incoming media track events from the RTCPeerConnection.
122
+ *
123
+ * @private
124
+ * @param e The track event.
125
+ */
126
+ _handlePeerConnectionTrack: (e: RTCTrackEvent) => void;
127
+ /**
128
+ * Handles ICE candidate generation from the local RTCPeerConnection.
129
+ *
130
+ * @private
131
+ * @param e The ICE candidate event.
132
+ */
133
+ _handlePeerIceCandidate: (e: RTCPeerConnectionIceEvent) => void;
134
+ /**
135
+ * Monitors connection state changes on the RTCPeerConnection to trigger disconnection.
136
+ *
137
+ * @private
138
+ * @param e The state change event.
139
+ */
140
+ _handlePeerConnectionStateChange: (e: Event) => void;
141
+ /**
142
+ * Registers a data channel for event forwarding.
143
+ *
144
+ * @private
145
+ * @param channel The data channel.
146
+ */
147
+ _setupDataChannel: (channel: RTCDataChannel) => void;
148
+ /**
149
+ * Handles remote data channel creation.
150
+ *
151
+ * @private
152
+ * @param e The data channel event.
153
+ */
154
+ _handleDataChannel: (e: RTCDataChannelEvent) => void;
155
+ /**
156
+ * Processes a remote SDP offer or answer, applying it to the RTCPeerConnection.
157
+ *
158
+ * @private
159
+ * @param sdp The session description.
160
+ */
161
+ _handleSDP: (sdp: RTCSessionDescriptionInit) => Promise<void>;
162
+ /**
163
+ * Adds a remote ICE candidate to the RTCPeerConnection.
164
+ *
165
+ * @private
166
+ * @param candidate The ICE candidate object or string.
167
+ */
168
+ _addIceCandidate: (candidate: RTCIceCandidateInit | string) => void;
169
+ /**
170
+ * Handles an incoming remote ICE candidate, queueing it if the remote description is not yet set.
171
+ *
172
+ * @private
173
+ * @param candidate The remote ICE candidate.
174
+ */
175
+ _handleCandidate: (candidate: RTCIceCandidateInit | string) => void;
176
+ /**
177
+ * Handles the 'bye' signal from the remote side, triggering disconnection.
178
+ *
179
+ * @private
180
+ */
181
+ _handleBye: () => void;
182
+ /**
183
+ * Serializes and sends a JSEP JSON message over the WebSocket.
184
+ *
185
+ * @private
186
+ * @param jsonObject The JSON payload.
187
+ */
188
+ _sendJsep: (jsonObject: JsepSignal) => void;
189
+ /**
190
+ * Sends a control message (mouse, keyboard, touch) over either the corresponding
191
+ * WebRTC DataChannel or via the fallback emulator controller.
192
+ *
193
+ * @param label The channel label ("mouse", "keyboard", "touch").
194
+ * @param msg The protobuf message instance.
195
+ */
196
+ send: (label: string, msg: any) => void;
197
+ /**
198
+ * Cleans up the current connection's WebSocket and PeerConnection state,
199
+ * but does not mark the driver as permanently disconnected or trigger
200
+ * the onDisconnected callback. Used during reconnection.
201
+ *
202
+ * @private
203
+ */
204
+ _disconnectState: () => void;
205
+ /**
206
+ * Disconnects both the WebSocket signaling connection and the WebRTC PeerConnection.
207
+ */
208
+ disconnect: () => void;
209
+ /**
210
+ * Fully cleans up signaling and WebRTC state.
211
+ */
212
+ cleanup: () => void;
213
+ }