microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.8.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/android/androidTargetManager.ts

192lines · modeblame

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