microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
866e020b2c664db8b8c5bf972901bc2fc25ddd93

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/android/androidTargetManager.ts

192lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as nls from "vscode-nls";
5import { MobileTargetManager } from "../mobileTargetManager";
6import { AdbHelper } from "./adb";
7import { ChildProcess } from "../../common/node/childProcess";
8import { OutputChannelLogger } from "../log/OutputChannelLogger";
9import { IDebuggableMobileTarget, IMobileTarget, MobileTarget } from "../mobileTarget";
10import { waitUntil } from "../../common/utils";
11import { TargetType } from "../generalPlatform";
12
13nls.config({
14 messageFormat: nls.MessageFormat.bundle,
15 bundleFormat: nls.BundleFormat.standalone,
16})();
17const localize = nls.loadMessageBundle();
18
19export class AndroidTarget extends MobileTarget {
20 public static fromInterface(obj: IDebuggableMobileTarget): AndroidTarget {
21 return new AndroidTarget(obj.isOnline, obj.isVirtualTarget, obj.id, obj.name);
22 }
23
24 constructor(isOnline: boolean, isVirtualTarget: boolean, id: string, name?: string) {
25 super(isOnline, isVirtualTarget, id, name ? name : id);
26 }
27}
28
29export class AndroidTargetManager extends MobileTargetManager {
30 private static readonly EMULATOR_COMMAND = "emulator";
31 private static readonly EMULATOR_AVD_START_COMMAND = "-avd";
32 private static readonly EMULATOR_START_TIMEOUT = 120;
33
34 private logger: OutputChannelLogger;
35 private adbHelper: AdbHelper;
36 private childProcess: ChildProcess;
37
38 constructor(adbHelper: AdbHelper) {
39 super();
40 this.adbHelper = adbHelper;
41 this.logger = OutputChannelLogger.getChannel(OutputChannelLogger.MAIN_CHANNEL_NAME, true);
42 this.childProcess = new ChildProcess();
43 }
44
45 public async isVirtualTarget(target: string): Promise<boolean> {
46 try {
47 if (target === TargetType.Device) {
48 return false;
49 } else if (
50 target === TargetType.Simulator ||
51 target.match(AdbHelper.AndroidSDKEmulatorPattern) ||
52 (await this.adbHelper.getAvdsNames()).includes(target)
53 ) {
54 return true;
55 } else {
56 const onlineTarget = await this.adbHelper.findOnlineTargetById(target);
57 if (onlineTarget) {
58 return onlineTarget.isVirtualTarget;
59 } else {
60 throw new Error("There is no any online target");
61 }
62 }
63 } catch {
64 throw new Error(
65 localize(
66 "CouldNotRecognizeTargetType",
67 "Could not recognize type of the target {0}",
68 target,
69 ),
70 );
71 }
72 }
73
74 public async selectAndPrepareTarget(
75 filter?: (el: IMobileTarget) => boolean,
76 ): Promise<AndroidTarget | undefined> {
77 const selectedTarget = await this.startSelection(filter);
78 if (selectedTarget) {
79 if (!selectedTarget.isOnline && selectedTarget.isVirtualTarget) {
80 return this.launchSimulator(selectedTarget);
81 } else {
82 if (selectedTarget.id) {
83 return AndroidTarget.fromInterface(<IDebuggableMobileTarget>selectedTarget);
84 }
85 }
86 }
87 return undefined;
88 }
89
90 public async collectTargets(): Promise<void> {
91 const targetList: IMobileTarget[] = [];
92
93 let emulatorsNames: string[] = await this.adbHelper.getAvdsNames();
94 targetList.push(
95 ...emulatorsNames.map(name => {
96 return { name, isOnline: false, isVirtualTarget: true };
97 }),
98 );
99
100 const onlineTargets = await this.adbHelper.getOnlineTargets();
101 for (let device of onlineTargets) {
102 if (device.isVirtualTarget) {
103 const avdName = await this.adbHelper.getAvdNameById(device.id);
104 const emulatorTarget = targetList.find(target => target.name === avdName);
105 if (emulatorTarget) {
106 emulatorTarget.isOnline = true;
107 emulatorTarget.id = device.id;
108 }
109 } else {
110 targetList.push({ id: device.id, isOnline: true, isVirtualTarget: false });
111 }
112 }
113
114 this.targets = targetList;
115 }
116
117 protected async startSelection(
118 filter?: (el: IMobileTarget) => boolean,
119 ): Promise<IMobileTarget | undefined> {
120 return this.selectTarget(filter);
121 }
122
123 protected async launchSimulator(emulatorTarget: IMobileTarget): Promise<AndroidTarget> {
124 return new Promise<AndroidTarget>((resolve, reject) => {
125 const emulatorProcess = this.childProcess.spawn(
126 AndroidTargetManager.EMULATOR_COMMAND,
127 [AndroidTargetManager.EMULATOR_AVD_START_COMMAND, emulatorTarget.name as string],
128 {
129 detached: true,
130 },
131 true,
132 );
133 emulatorProcess.outcome.catch(error => {
134 if (
135 process.platform == "win32" &&
136 process.env.SESSIONNAME &&
137 process.env.SESSIONNAME.toLowerCase().includes("rdp-tcp")
138 ) {
139 this.logger.warning(
140 localize(
141 "RDPEmulatorWarning",
142 "Android emulator was launched from the Windows RDP session, this might lead to failures.",
143 ),
144 );
145 }
146 reject(new Error(`Virtual device launch finished with an exception: ${error}`));
147 });
148 emulatorProcess.spawnedProcess.unref();
149
150 const condition = async () => {
151 const connectedDevices = await this.adbHelper.getOnlineTargets();
152 for (let target of connectedDevices) {
153 const onlineAvdName = await this.adbHelper.getAvdNameById(target.id);
154 if (onlineAvdName === emulatorTarget.name) {
155 return target.id;
156 }
157 }
158 return null;
159 };
160
161 return waitUntil<string>(
162 condition,
163 1000,
164 AndroidTargetManager.EMULATOR_START_TIMEOUT * 1000,
165 ).then(emulatorId => {
166 if (emulatorId) {
167 emulatorTarget.id = emulatorId;
168 emulatorTarget.isOnline = true;
169 this.logger.info(
170 localize(
171 "EmulatorLaunched",
172 "Launched Android emulator {0}",
173 emulatorTarget.name,
174 ),
175 );
176 resolve(AndroidTarget.fromInterface(<IDebuggableMobileTarget>emulatorTarget));
177 } else {
178 reject(
179 new Error(
180 `Virtual device launch finished with an exception: ${localize(
181 "EmulatorStartWarning",
182 "Could not start the emulator {0} within {1} seconds.",
183 emulatorTarget.name,
184 AndroidTargetManager.EMULATOR_START_TIMEOUT,
185 )}`,
186 ),
187 );
188 }
189 });
190 });
191 }
192}
193