From eff5b0c3d8db7fb95fd3d2f95f56fbd62e3d9698 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Thu, 3 Oct 2024 16:38:32 +0200 Subject: [PATCH 1/9] init --- .../src/devices/AndroidEmulatorDevice.ts | 111 +++++++++++++++++- .../src/devices/DeviceBase.ts | 2 +- .../components/DeviceSettingsDropdown.tsx | 2 +- 3 files changed, 107 insertions(+), 8 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index 1b8d5516f..e1e5a5541 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -12,7 +12,7 @@ import { ChildProcess, exec, lineReader } from "../utilities/subprocess"; import { BuildResult } from "../builders/BuildManager"; import { AndroidSystemImageInfo, DeviceInfo, DevicePlatform } from "../common/DeviceManager"; import { Logger } from "../Logger"; -import { AppPermissionType, DeviceSettings } from "../common/Project"; +import { AppPermissionType, DeviceSettings, Locale } from "../common/Project"; import { getAndroidSystemImages } from "../utilities/sdkmanager"; import { EXPO_GO_PACKAGE_NAME, fetchExpoLaunchDeeplink } from "../builders/expoGo"; import { Platform } from "../utilities/platform"; @@ -70,7 +70,89 @@ export class AndroidEmulatorDevice extends DeviceBase { }, DISPOSE_TIMEOUT); } + private async shouldUpdateLocale(newLocale: Locale) { + const locale = newLocale.replace("_", "-"); + const { stdout } = await exec(ADB_PATH, [ + "-s", + this.serial!, + "shell", + "settings", + "get", + "system", + "system_locales", + ]); + + // if user did not use the device before it might not have system_locales property + // as en-US is the default locale we assume that no value is the same as en-US + if ((stdout ?? "en-US") === locale) { + return false; + } + return true; + } + + // this method changes device locale in two ways, firstly it modifies system_locales setting, + // which in most cases is enough, to change locale. Unfortunately if persist.sys.locale exist + // it will conflict with system_locales and make device behavior unpredictable, so in that case + // we need to modify if as well. persist.sys.locale is added to the device when a user changes locale + // in the settings. Unfortunately this method does not handle all possible scenarios. + // If the device uses google mobile services persist.sys.locale can not be changed, as it requires a root access + // TODO: Find a way to change or remove persist.sys.locale without root access. note: removing the whole + // data/property/persistent_properties file would also work as we persist device settings globally in Radon IDE + private async changeLocale(newLocale: Locale): Promise { + const locale = newLocale.replace("_", "-"); + + await exec(ADB_PATH, [ + "-s", + this.serial!, + "shell", + "settings", + "put", + "system", + "system_locales", + locale, + ]); + + const { stdout } = await exec(ADB_PATH, [ + "-s", + this.serial!, + "shell", + "getprop", + "persist.sys.locale", + ]); + + if (!stdout) { + return true; + } + + // If persist.sys.locale exist try to set it to match the newLocale. + try { + await exec(ADB_PATH, [ + "-s", + this.serial!, + "shell", + "su", + "0", + "setprop", + "persist.sys.locale", + locale, + ]); + } catch (e) { + // this is expected if device is using google mobile services + Logger.debug( + "CHANGE LOCALE - Device is not allowing root access, moving on without modifying persist.sys.locale" + ); + } + + return true; + } + async changeSettings(settings: DeviceSettings) { + let shouldRestart = false; + if (await this.shouldUpdateLocale(settings.locale)) { + shouldRestart = true; + await this.changeLocale(settings.locale); + } + await exec(ADB_PATH, [ "-s", this.serial!, @@ -117,10 +199,29 @@ export class AndroidEmulatorDevice extends DeviceBase { settings.location.latitude.toString(), ]); } - return false; + return shouldRestart; + } + + // it is necessary to use SIGTERM 9 as it would take to much time otherwise and would degrade user experience + // having said that use this function with caution only in scenarios when you are sure that no user data will be lost + private async resetDevice() { + this.emulatorProcess?.kill(9); + await this.internalBootDevice(); + } + + async bootDevice(deviceSettings: DeviceSettings): Promise { + // We have to initially boot the device because we use adb shell to change the devices locale + // alternative would be to use -change-locale option on the emulator, but that option restarts the device too + // the -change-locale option is not covering all cases read more about it in this.changeLocale + await this.internalBootDevice(); + + let shouldRestart = await this.changeSettings(deviceSettings); + if (shouldRestart) { + await this.resetDevice(); + } } - async bootDevice(settings: DeviceSettings) { + async internalBootDevice() { // this prevents booting device with the same AVD twice await ensureOldEmulatorProcessExited(this.avdId); @@ -134,7 +235,7 @@ export class AndroidEmulatorDevice extends DeviceBase { "-no-audio", "-no-boot-anim", "-grpc-use-token", - "-no-snapshot-save", + "-no-snapshot", ], { env: { ANDROID_AVD_HOME: avdDirectory } } ); @@ -163,8 +264,6 @@ export class AndroidEmulatorDevice extends DeviceBase { }); this.serial = await initPromise; - - await this.changeSettings(settings); } async openDevMenu() { diff --git a/packages/vscode-extension/src/devices/DeviceBase.ts b/packages/vscode-extension/src/devices/DeviceBase.ts index ca388f7b5..66b450810 100644 --- a/packages/vscode-extension/src/devices/DeviceBase.ts +++ b/packages/vscode-extension/src/devices/DeviceBase.ts @@ -2,7 +2,7 @@ import fs from "fs"; import { Disposable } from "vscode"; import { Preview } from "./preview"; import { BuildResult } from "../builders/BuildManager"; -import { AppPermissionType, DeviceSettings, TouchPoint, Locale } from "../common/Project"; +import { AppPermissionType, DeviceSettings, TouchPoint } from "../common/Project"; import { DeviceInfo, DevicePlatform } from "../common/DeviceManager"; import { tryAcquiringLock } from "../utilities/common"; diff --git a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx index f121c90dd..c5c2c6280 100644 --- a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx +++ b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx @@ -129,7 +129,7 @@ function DeviceSettingsDropdown({ children, disabled }: DeviceSettingsDropdownPr Set Device Location - {projectState.selectedDevice?.platform === DevicePlatform.IOS && } + {true && } From 5c932599ce8286631c3ffc279bf88227f5fef589 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Thu, 3 Oct 2024 16:50:05 +0200 Subject: [PATCH 2/9] init2 --- .../src/webview/components/DeviceSettingsDropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx index c5c2c6280..c42e95ec2 100644 --- a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx +++ b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx @@ -129,7 +129,7 @@ function DeviceSettingsDropdown({ children, disabled }: DeviceSettingsDropdownPr Set Device Location - {true && } + From cd2a1bcc44b33519b38d4a433ce1a22dad6ab61a Mon Sep 17 00:00:00 2001 From: filip131311 Date: Fri, 4 Oct 2024 15:14:44 +0200 Subject: [PATCH 3/9] changes after CR --- .../src/devices/AndroidEmulatorDevice.ts | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index e1e5a5541..678afae82 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -92,13 +92,14 @@ export class AndroidEmulatorDevice extends DeviceBase { // this method changes device locale in two ways, firstly it modifies system_locales setting, // which in most cases is enough, to change locale. Unfortunately if persist.sys.locale exist - // it will conflict with system_locales and make device behavior unpredictable, so in that case - // we need to modify if as well. persist.sys.locale is added to the device when a user changes locale - // in the settings. Unfortunately this method does not handle all possible scenarios. - // If the device uses google mobile services persist.sys.locale can not be changed, as it requires a root access + // it will conflict with system_locales and make device behavior unpredictable. so in that case + // we would like to modify if as well. Unfortunately ass of right now we don't have a reliable + // method of doing that, because If the device uses google mobile services persist.sys.locale can not be changed, + // as it requires a root access persist.sys.locale is added to the device when a user changes locale + // in the settings. // TODO: Find a way to change or remove persist.sys.locale without root access. note: removing the whole // data/property/persistent_properties file would also work as we persist device settings globally in Radon IDE - private async changeLocale(newLocale: Locale): Promise { + private async changeLocale(newLocale: Locale): Promise { const locale = newLocale.replace("_", "-"); await exec(ADB_PATH, [ @@ -120,30 +121,11 @@ export class AndroidEmulatorDevice extends DeviceBase { "persist.sys.locale", ]); - if (!stdout) { - return true; - } - - // If persist.sys.locale exist try to set it to match the newLocale. - try { - await exec(ADB_PATH, [ - "-s", - this.serial!, - "shell", - "su", - "0", - "setprop", - "persist.sys.locale", - locale, - ]); - } catch (e) { - // this is expected if device is using google mobile services - Logger.debug( - "CHANGE LOCALE - Device is not allowing root access, moving on without modifying persist.sys.locale" + if (stdout) { + Logger.warn( + "persist.sys.locale detected while changing locale. It might indicate that the user has changed locale settings in the settings application, which will prevent localization change." ); } - - return true; } async changeSettings(settings: DeviceSettings) { From eb14f0cbf01ed66d3c2471300dadc5d5248db5cf Mon Sep 17 00:00:00 2001 From: filip131311 Date: Fri, 4 Oct 2024 15:21:11 +0200 Subject: [PATCH 4/9] changes after CR --- .../vscode-extension/src/devices/AndroidEmulatorDevice.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index 678afae82..102811f08 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -186,7 +186,7 @@ export class AndroidEmulatorDevice extends DeviceBase { // it is necessary to use SIGTERM 9 as it would take to much time otherwise and would degrade user experience // having said that use this function with caution only in scenarios when you are sure that no user data will be lost - private async resetDevice() { + private async forcefullyResetDevice() { this.emulatorProcess?.kill(9); await this.internalBootDevice(); } @@ -199,7 +199,7 @@ export class AndroidEmulatorDevice extends DeviceBase { let shouldRestart = await this.changeSettings(deviceSettings); if (shouldRestart) { - await this.resetDevice(); + await this.forcefullyResetDevice(); } } From 1cc4a2fb739068fa237ed016dfe410ed01b11387 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Thu, 10 Oct 2024 11:07:17 +0200 Subject: [PATCH 5/9] setTimeout workaround --- .../src/devices/AndroidEmulatorDevice.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index 102811f08..7f6adc55a 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -113,6 +113,12 @@ export class AndroidEmulatorDevice extends DeviceBase { locale, ]); + await new Promise((res)=>{ + setTimeout(()=>{ + res() + }, 1000) + }) + const { stdout } = await exec(ADB_PATH, [ "-s", this.serial!, @@ -217,7 +223,9 @@ export class AndroidEmulatorDevice extends DeviceBase { "-no-audio", "-no-boot-anim", "-grpc-use-token", - "-no-snapshot", + "-no-snapshot-save", + "-writable-system", + "-verbose" ], { env: { ANDROID_AVD_HOME: avdDirectory } } ); From f2eaba184539e8e1638e3476501e8a1425268c15 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Thu, 10 Oct 2024 12:20:27 +0200 Subject: [PATCH 6/9] add qemu.img syncronisation --- .../src/devices/AndroidEmulatorDevice.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index 7f6adc55a..b1e7c036f 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -113,12 +113,6 @@ export class AndroidEmulatorDevice extends DeviceBase { locale, ]); - await new Promise((res)=>{ - setTimeout(()=>{ - res() - }, 1000) - }) - const { stdout } = await exec(ADB_PATH, [ "-s", this.serial!, @@ -127,6 +121,9 @@ export class AndroidEmulatorDevice extends DeviceBase { "persist.sys.locale", ]); + // this is needed to make sure that changes will persist + await exec(ADB_PATH, ["shell", "sync"]); + if (stdout) { Logger.warn( "persist.sys.locale detected while changing locale. It might indicate that the user has changed locale settings in the settings application, which will prevent localization change." @@ -225,7 +222,6 @@ export class AndroidEmulatorDevice extends DeviceBase { "-grpc-use-token", "-no-snapshot-save", "-writable-system", - "-verbose" ], { env: { ANDROID_AVD_HOME: avdDirectory } } ); From 2e54c3f909b31199eeb68a6f51793851ed1caa3e Mon Sep 17 00:00:00 2001 From: filip131311 Date: Fri, 11 Oct 2024 18:14:10 +0200 Subject: [PATCH 7/9] changes after CR --- .../vscode-extension/src/devices/AndroidEmulatorDevice.ts | 6 +++--- .../src/webview/components/DeviceSettingsDropdown.tsx | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index b1e7c036f..f88375f81 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -113,6 +113,9 @@ export class AndroidEmulatorDevice extends DeviceBase { locale, ]); + // this is needed to make sure that changes will persist + await exec(ADB_PATH, ["-s", this.serial!, "shell", "sync"]); + const { stdout } = await exec(ADB_PATH, [ "-s", this.serial!, @@ -121,9 +124,6 @@ export class AndroidEmulatorDevice extends DeviceBase { "persist.sys.locale", ]); - // this is needed to make sure that changes will persist - await exec(ADB_PATH, ["shell", "sync"]); - if (stdout) { Logger.warn( "persist.sys.locale detected while changing locale. It might indicate that the user has changed locale settings in the settings application, which will prevent localization change." diff --git a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx index c42e95ec2..a8d1e95ae 100644 --- a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx +++ b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx @@ -161,10 +161,12 @@ function DeviceSettingsDropdown({ children, disabled }: DeviceSettingsDropdownPr const LocalizationItem = () => { const { openModal } = useModal(); + const { projectState } = useProject(); return ( <> { openModal("Localization", ); From 4cced636662353fa7a4935175f3abb0f01c1d5c3 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Wed, 23 Oct 2024 16:22:28 +0200 Subject: [PATCH 8/9] changes in coments --- .../src/devices/AndroidEmulatorDevice.ts | 20 ++++++------------- .../components/DeviceSettingsDropdown.tsx | 2 -- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index f88375f81..4ca63fcaa 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -90,15 +90,7 @@ export class AndroidEmulatorDevice extends DeviceBase { return true; } - // this method changes device locale in two ways, firstly it modifies system_locales setting, - // which in most cases is enough, to change locale. Unfortunately if persist.sys.locale exist - // it will conflict with system_locales and make device behavior unpredictable. so in that case - // we would like to modify if as well. Unfortunately ass of right now we don't have a reliable - // method of doing that, because If the device uses google mobile services persist.sys.locale can not be changed, - // as it requires a root access persist.sys.locale is added to the device when a user changes locale - // in the settings. - // TODO: Find a way to change or remove persist.sys.locale without root access. note: removing the whole - // data/property/persistent_properties file would also work as we persist device settings globally in Radon IDE + /** This method changes device locale by modifying system_locales system setting. */ private async changeLocale(newLocale: Locale): Promise { const locale = newLocale.replace("_", "-"); @@ -116,6 +108,8 @@ export class AndroidEmulatorDevice extends DeviceBase { // this is needed to make sure that changes will persist await exec(ADB_PATH, ["-s", this.serial!, "shell", "sync"]); + // TODO: Find a way to change or remove persist.sys.locale without root access. note: removing the whole + // data/property/persistent_properties file would also work as we persist device settings globally in Radon IDE const { stdout } = await exec(ADB_PATH, [ "-s", this.serial!, @@ -187,17 +181,15 @@ export class AndroidEmulatorDevice extends DeviceBase { return shouldRestart; } - // it is necessary to use SIGTERM 9 as it would take to much time otherwise and would degrade user experience - // having said that use this function with caution only in scenarios when you are sure that no user data will be lost + /** This method restarts the emulator process using SIGKILL signal. + * Should be used for the situations when quick reboot is necessary + * and when we don't care about the emulator's process state */ private async forcefullyResetDevice() { this.emulatorProcess?.kill(9); await this.internalBootDevice(); } async bootDevice(deviceSettings: DeviceSettings): Promise { - // We have to initially boot the device because we use adb shell to change the devices locale - // alternative would be to use -change-locale option on the emulator, but that option restarts the device too - // the -change-locale option is not covering all cases read more about it in this.changeLocale await this.internalBootDevice(); let shouldRestart = await this.changeSettings(deviceSettings); diff --git a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx index a8d1e95ae..c42e95ec2 100644 --- a/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx +++ b/packages/vscode-extension/src/webview/components/DeviceSettingsDropdown.tsx @@ -161,12 +161,10 @@ function DeviceSettingsDropdown({ children, disabled }: DeviceSettingsDropdownPr const LocalizationItem = () => { const { openModal } = useModal(); - const { projectState } = useProject(); return ( <> { openModal("Localization", ); From 22e981cb9a027b9989747cdaaca3be612cf26613 Mon Sep 17 00:00:00 2001 From: filip131311 Date: Wed, 23 Oct 2024 20:03:19 +0200 Subject: [PATCH 9/9] fixes after CR --- .../src/devices/AndroidEmulatorDevice.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts index 73221cee5..4bfaeb4ee 100644 --- a/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts +++ b/packages/vscode-extension/src/devices/AndroidEmulatorDevice.ts @@ -91,14 +91,17 @@ export class AndroidEmulatorDevice extends DeviceBase { ]); // if user did not use the device before it might not have system_locales property - // as en-US is the default locale we assume that no value is the same as en-US + // as en-US is the default locale, used by the system, when no setting is provided + // we assume that no value in stdout is the same as en-US if ((stdout ?? "en-US") === locale) { return false; } return true; } - /** This method changes device locale by modifying system_locales system setting. */ + /** + * This method changes device locale by modifying system_locales system setting. + */ private async changeLocale(newLocale: Locale): Promise { const locale = newLocale.replace("_", "-"); @@ -128,7 +131,7 @@ export class AndroidEmulatorDevice extends DeviceBase { if (stdout) { Logger.warn( - "persist.sys.locale detected while changing locale. It might indicate that the user has changed locale settings in the settings application, which will prevent localization change." + "Updating locale will not take effect as the device has altered locale via system settings which always takes precedence over the device setting the IDE uses." ); } } @@ -189,9 +192,11 @@ export class AndroidEmulatorDevice extends DeviceBase { return shouldRestart; } - /** This method restarts the emulator process using SIGKILL signal. - * Should be used for the situations when quick reboot is necessary - * and when we don't care about the emulator's process state */ + /** + * This method restarts the emulator process using SIGKILL signal. + * Should be used for the situations when quick reboot is necessary + * and when we don't care about the emulator's process state + */ private async forcefullyResetDevice() { this.emulatorProcess?.kill(9); await this.internalBootDevice();