android-emulator-webrtc 1.0.18 → 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 (69) 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 -20
  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 -17
  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/simple_png_view.js +0 -110
  43. package/dist/proto/emulator_controller_grpc_web_pb.js +0 -1601
  44. package/dist/proto/emulator_web_client.js +0 -176
  45. package/dist/proto/rtc_service_grpc_web_pb.js +0 -231
  46. package/dist/proto/rtc_service_pb.js +0 -338
  47. package/emulator/index.js +0 -1
  48. package/eslint_prefix.py +0 -37
  49. package/gen_md_doc.js +0 -40
  50. package/npmrc.enc +0 -0
  51. package/proto/rtc_service.proto +0 -117
  52. package/protoc-plugin/Makefile +0 -31
  53. package/protoc-plugin/grpc_generator.cc +0 -1755
  54. package/src/components/emulator/emulator.js +0 -217
  55. package/src/components/emulator/net/emulator_status.js +0 -94
  56. package/src/components/emulator/net/jsep_protocol_driver.js +0 -364
  57. package/src/components/emulator/net/logcat.js +0 -155
  58. package/src/components/emulator/views/event_handler.js +0 -268
  59. package/src/components/emulator/views/simple_png_view.js +0 -105
  60. package/src/components/emulator/views/webrtc_view.js +0 -142
  61. package/src/index.js +0 -20
  62. package/src/proto/emulator_web_client.js +0 -140
  63. package/test/cloudbuild.yaml +0 -41
  64. package/test/emulator.test.js +0 -125
  65. package/test/event_handler.test.js +0 -91
  66. package/test/fake_events.js +0 -50
  67. package/test/jsep_protocol_driver.test.js +0 -228
  68. package/test/simple_png_view.test.js +0 -145
  69. package/test/touch_event_handler.test.js +0 -118
@@ -0,0 +1,64 @@
1
+ import React from "react";
2
+ export interface EmulatorProps {
3
+ /** Endpoint where we can reach the emulator gateway (host:port or http(s)://host:port). */
4
+ uri: string;
5
+ /** The authentication service to use, or null for no authentication. */
6
+ auth?: any;
7
+ /** True if the audio should be disabled. */
8
+ muted?: boolean;
9
+ /** Volume between [0, 1] when audio is enabled. 0 is muted, 1.0 is 100% */
10
+ volume?: number;
11
+ /** Called upon state change, one of ["connecting", "connected", "disconnected"] */
12
+ onStateChange?: (state: string) => void;
13
+ /** Called when the audio becomes (un)available. True if audio is available, false otherwise. */
14
+ onAudioStateChange?: (audio: boolean) => void;
15
+ /** The width of the component */
16
+ width?: number;
17
+ /** The height of the component */
18
+ height?: number;
19
+ /** A [GeolocationCoordinates](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates) like object indicating where the device is. */
20
+ gps?: {
21
+ latitude: number;
22
+ longitude: number;
23
+ altitude?: number;
24
+ heading?: number;
25
+ speed?: number;
26
+ };
27
+ /** Callback that will be invoked in case of errors. */
28
+ onError?: (error: any) => void;
29
+ }
30
+ export interface EmulatorRef {
31
+ sendKey(key: string): void;
32
+ }
33
+ /**
34
+ * A React component that displays a remote android emulator.
35
+ *
36
+ * The emulator will mount a webrtc view component to display the current state
37
+ * of the emulator. It will translate mouse and touch events on this component and send them
38
+ * to the actual emulator over WebRTC Data Channels.
39
+ *
40
+ * #### Authentication Service
41
+ *
42
+ * The authentication service should implement the following methods:
43
+ *
44
+ * - `authHeader()` which must return a set of headers that should be send along with a request.
45
+ * - `unauthorized()` a function that gets called when a 401 was received.
46
+ *
47
+ * Note that chrome will not autoplay the video if it is not muted and no interaction
48
+ * with the page has taken place. See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes.
49
+ *
50
+ * #### Pressing hardware buttons
51
+ *
52
+ * This component has a method `sendKey` that sends a key to the emulator.
53
+ * You can use this to send physical button events to the emulator for example:
54
+ *
55
+ * "AudioVolumeDown" - Decreases the audio volume.
56
+ * "AudioVolumeUp" - Increases the audio volume.
57
+ * "Power" - The Power button or key, turn off the device.
58
+ * "AppSwitch" - Should bring up the application switcher dialog.
59
+ * "GoHome" - Go to the home screen.
60
+ * "GoBack" - Open the previous screen you were looking at.
61
+ *
62
+ */
63
+ declare const Emulator: React.ForwardRefExoticComponent<EmulatorProps & React.RefAttributes<EmulatorRef>>;
64
+ export default Emulator;
@@ -0,0 +1,45 @@
1
+ export interface AuthService {
2
+ authHeader?(): Record<string, string>;
3
+ unauthorized?(): void;
4
+ }
5
+ export interface EmulatorStatusData {
6
+ status?: string;
7
+ hardwareConfig?: Record<string, string>;
8
+ [key: string]: any;
9
+ }
10
+ /**
11
+ * Utility class to query and manage the emulator's status by communicating
12
+ * with its REST configuration endpoint. It parses the hardware configuration
13
+ * and caches the status.
14
+ *
15
+ * @export
16
+ * @class EmulatorStatus
17
+ */
18
+ declare class EmulatorStatus {
19
+ statusUrl: string;
20
+ auth: AuthService | null;
21
+ status: EmulatorStatusData | null;
22
+ /**
23
+ * Creates an EmulatorStatus object that can retrieve the status of the running emulator.
24
+ *
25
+ * @param statusUrl The REST endpoint to retrieve status.
26
+ * @param auth The authentication service to use, or null for no authentication.
27
+ */
28
+ constructor(statusUrl: string, auth?: AuthService | null);
29
+ /**
30
+ * Gets the cached status object.
31
+ *
32
+ * @returns The cached emulator status or null if not yet loaded.
33
+ * @memberof EmulatorStatus
34
+ */
35
+ getStatus: () => EmulatorStatusData | null;
36
+ /**
37
+ * Retrieves the current status from the emulator REST endpoint.
38
+ *
39
+ * @param fnNotify Callback invoked when the status is retrieved. Receives the status object.
40
+ * @param cache If true, uses the cached status if available instead of fetching.
41
+ * @memberof EmulatorStatus
42
+ */
43
+ updateStatus: (fnNotify: (status: EmulatorStatusData) => void, cache?: boolean) => EmulatorStatusData;
44
+ }
45
+ export default EmulatorStatus;
@@ -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,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
+ }
@@ -0,0 +1,37 @@
1
+ import React from "react";
2
+ import WsJsepProtocol from "../net/ws_jsep_protocol_driver";
3
+ export interface MouseKeyHandlerProps {
4
+ /** The REST endpoint to retrieve status. */
5
+ statusUrl: string;
6
+ /** Jsep protocol driver, used to send mouse & touch events. */
7
+ jsep: WsJsepProtocol;
8
+ /** The authentication service to use. */
9
+ auth?: any;
10
+ /** The width of the component. */
11
+ width?: number;
12
+ /** The height of the component. */
13
+ height?: number;
14
+ [key: string]: any;
15
+ }
16
+ export interface MouseKeyHandlerRef {
17
+ scaleCoordinates(xp: number, yp: number): {
18
+ x: number;
19
+ y: number;
20
+ scaleX: number;
21
+ scaleY: number;
22
+ };
23
+ setDeviceWidth: React.Dispatch<React.SetStateAction<number>>;
24
+ setDeviceHeight: React.Dispatch<React.SetStateAction<number>>;
25
+ handlerRef: React.RefObject<HTMLDivElement>;
26
+ }
27
+ /**
28
+ * A handler that extends a view to send key/mouse events to the emulator.
29
+ * It wraps the inner component in a div, and will use the jsep handler
30
+ * to send key/mouse/touch events over the proper channel.
31
+ *
32
+ * It will translate the mouse events based upon the returned display size of
33
+ * the emulator.
34
+ *
35
+ * You usually want to wrap a EmulatorRtcview, or EmulatorPngView in it.
36
+ */
37
+ export default function withMouseKeyHandler<P extends object>(WrappedComponent: React.ComponentType<P>): React.ForwardRefExoticComponent<React.PropsWithoutRef<MouseKeyHandlerProps & P> & React.RefAttributes<MouseKeyHandlerRef>>;
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ import WsJsepProtocol from "../net/ws_jsep_protocol_driver";
3
+ export interface EmulatorWebrtcViewProps {
4
+ /** The JSEP protocol driver instance. */
5
+ jsep: WsJsepProtocol;
6
+ /** Callback for connection state changes ("connecting", "connected", "disconnected"). */
7
+ onStateChange?: (state: string) => void;
8
+ /** Callback when audio track status changes. */
9
+ onAudioStateChange?: (audio: boolean) => void;
10
+ /** Whether the audio should be muted. */
11
+ muted?: boolean;
12
+ /** Audio volume (between 0.0 and 1.0). */
13
+ volume?: number;
14
+ /** Callback invoked on signaling or playback errors. */
15
+ onError?: (error: Error) => void;
16
+ /** Component width. */
17
+ width?: number;
18
+ /** Component height. */
19
+ height?: number;
20
+ }
21
+ /**
22
+ * A React component that renders the WebRTC video stream of the emulator.
23
+ * Handles establishing the stream via the JSEP protocol driver and managing
24
+ * local playback (including handling autoplay constraints).
25
+ */
26
+ declare const EmulatorWebrtcView: React.FC<EmulatorWebrtcViewProps>;
27
+ export default EmulatorWebrtcView;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @fileoverview Main entry point for the android-emulator-webrtc package.
3
+ * Exports the primary Emulator React component and the EmulatorStatus utility.
4
+ */
5
+ import Emulator from "./components/emulator/emulator";
6
+ import EmulatorStatus from "./components/emulator/net/emulator_status";
7
+ import logger from "./components/emulator/net/logger";
8
+ export { Emulator, EmulatorStatus, logger };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,29 +1,23 @@
1
1
  {
2
2
  "name": "android-emulator-webrtc",
3
- "version": "1.0.18",
3
+ "version": "2.0.1",
4
4
  "description": "Android Emulator WebRTC module",
5
+ "files": [
6
+ "dist",
7
+ "proto",
8
+ "README.md",
9
+ "LICENSE"
10
+ ],
5
11
  "scripts": {
6
- "build": "babel src -d dist",
12
+ "build": "babel src -d dist && tsc",
7
13
  "test": "jest"
8
14
  },
9
- "babel": {
10
- "presets": [
11
- "@babel/preset-env",
12
- "@babel/preset-react"
13
- ],
14
- "plugins": [
15
- "@babel/plugin-proposal-class-properties"
16
- ]
17
- },
18
15
  "jest": {
19
- "verbose": true,
20
- "transformIgnorePatterns": [
21
- "/node_modules/@juggle/resize-observer/"
22
- ]
16
+ "verbose": true
23
17
  },
24
18
  "dependencies": {
25
19
  "google-protobuf": "^3.21.2",
26
- "grpc-web": "^1.4.2",
20
+ "loglevel": "^1.9.2",
27
21
  "prop-types": "^15.8.1"
28
22
  },
29
23
  "peerDependencies": {
@@ -37,23 +31,29 @@
37
31
  "@babel/plugin-transform-runtime": "^7.21.4",
38
32
  "@babel/preset-env": "^7.21.5",
39
33
  "@babel/preset-react": "^7.18.6",
34
+ "@babel/preset-typescript": "^7.29.7",
40
35
  "@testing-library/jest-dom": "^5.16.5",
41
36
  "@testing-library/react": "^14.0.0",
37
+ "@types/jest": "^30.0.0",
38
+ "@types/react": "^19.2.17",
39
+ "@types/react-dom": "^19.2.3",
42
40
  "babel-core": "7.0.0-bridge.0",
43
41
  "babel-jest": "^29.5.0",
44
42
  "babel-loader": "^9.1.2",
45
43
  "babel-polyfill": "^6.26.0",
46
44
  "jest": "^29.5.0",
47
45
  "jest-environment-jsdom": "^29.5.0",
46
+ "protoc-gen-js": "^3.21.4-4",
48
47
  "react": "^18.2.0",
49
48
  "react-docgen-markdown-renderer": "^2.1.3",
50
49
  "react-dom": "^18.2.0",
51
50
  "resize-observer-polyfill": "^1.5.1",
51
+ "typescript": "^6.0.3",
52
52
  "yalc": "^1.0.0-pre.53"
53
53
  },
54
54
  "repository": {
55
55
  "type": "git",
56
- "url": "git+https://github.com/google/android-emulator-webrtc.git"
56
+ "url": "git+https://github.com/pokowaka/android-emulator-webrtc.git"
57
57
  },
58
58
  "keywords": [
59
59
  "webrtc",