Skip to content

Current Observations on Emulator #696

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rupeshkumar22 opened this issue Jun 23, 2022 · 18 comments
Closed

Current Observations on Emulator #696

rupeshkumar22 opened this issue Jun 23, 2022 · 18 comments

Comments

@rupeshkumar22
Copy link
Contributor

As of now, I observe that DOWNLOAD_EMU is always set to false. It might have been set because of emulator issues.
The download destination will be /sdk/emulator based on this
Also, With AndroidUtil.createSubFolder(androidFolder, "sdk"); some redundent SDKs gets created.
The emulator needs to be launched by selecting the RUN IN EMULATOR option, for now, it's not working on the Windows platform.

@codeanticode
Copy link
Contributor

@rupeshkumar22 I think I set DOWNLOAD_EMU to false because at some moment it seemed that the emulator was downloaded by the SDK when requesting to create a system image, but this might have changed since then. Have you tried running the mode with DOWNLOAD_EMU = true?

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jun 26, 2022

@codeanticode @ranaaditya
Yes it gets downloaded when we opt to download fresh SDK(out of two options at startup Use Existing SDK and Download New SDK) under Processing/android/sdk
Yes, the emulator is not getting downloaded when it is set to false, But I did not explore the New SDK download option yet as I am trying to launch the emulator by selecting Use Existing SDK on startup and further it asks for downloading System Image.
After selecting the Use existing SDK option I use RUN IN EMULATOR and debug build gets successfully completed, It asks to download image. After clicking ok it start with downloading image to temp folder as x86-30_r10.zip and extracting it inside existing SDK. This process is not one time process and it is being asked to download System Image again and again. This is not a major issue and can be resolved.
The main issue I faced after download completion and extraction of image in existing sdk which is as follows-

EndOfDownloadImageAndExtraction

On Clicking **OK** I see the following-

OnOkEndOfDownloadImageAndExtraction

The issue seems to be related to the removal of JavaFX classes in Java 11 and Java 11+ Issue: #666

I will be sharing a design document for RUN IN EMULATOR option to state the current flow and possible solutions.

I observed DOWNLOAD_EMU
is a part of Download New SDK option and I will be exploring it after resolving the issues with first option Use Existing SDK.

@rupeshkumar22
Copy link
Contributor Author

@ranaaditya @codeanticode
Please check and revert if there are any suggestions or improvements for Current Workflow of the Emulator

@codeanticode
Copy link
Contributor

@rupeshkumar22 thanks for putting together this workflow. I'm surprised by the emulator being download repeatedly, I'm pretty sure this did not happen in the past, and not sure why it's happening now. I don't think we should have to keep the temporary file, the mode checks if the emulator command line tool exists:

https://github.com/processing/processing-android/blob/master/mode/src/processing/mode/android/AndroidSDK.java#L153

and only tries to download the emulator if that check fails. So something is wrong there, maybe due to a change in how the emulator files are saved in later versions of the Android SDK?

My recommendation would be to try to download the SDK and then the emulator from the command line, and if that works, create a system image and launch the emulator, also from the command line, using a recent SDK (30 or higher). If that works, we should be able to make it work from the Android mode by replicating what you did from the command line.

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jun 27, 2022

@codeanticode @ranaaditya When we opt to select Download New SDK for the first time on the dialog on startup it downloads the new SDK at Processing/android/sdk (downloads build tools. platform tools, and emulator if DOWNLOAD_EMU is set to true) After this download it exatrct the zip files present at Processing/android/temp/ to Processing/android/sdkand then deletes the Processing/android/temp/ which contains the downloaded SDK zips.

The next time we use Download New SDK on the dialog on startup it downloads the new SDK at some new folder as Processing/android/sdk.220620.0024
There is not an issue in downloading emulator and sdk again in new sdk as we load and use this new sdk.220620.0024 after the download is complete. We can optimize this repeated process of Download New SDK as it is again downloading zip files in the Processing/android/temp/ and extracts at Processing/android/sdk.220620.0024 by keeping Processing/android/temp/(just a suggestion)

The issue arises when we run the project in the emulator(Run in emulator) after selecting Use Existing SDK, here before downloading the image it does not check if the image is already present at AppData\Local\Android\sdk\system-images\android-30. It keeps on downloading the image at Processing/android/temp/x86-30_r10.zip and then extracts at AppData\Local\Android\sdk\system-images\android-30 every time we use 'Run in emulator' and never checks if it's already extracted at AppData\Local\Android\sdk\system-images\android-30

Is this parameterized constructor (the link that you shared) that holds the code to check emulator existence being referenced anywhere?

Yes, I think it's a better way to first try the emulator on the command line, After using an emulator on the command line I will do the adjustments on Android Mode by replicating the work from the command line.

@codeanticode
Copy link
Contributor

@rupeshkumar22The fact that the mode keeps trying to download the system image suggests to me that the hasImages() function is always returning false, even when the image is already installed? This function in turns calls getImages(), which it definitely used to work in the past but maybe is not working anymore due to recent changes in the android tools or paths, what to you think? I'd add some breakpoints in those functions to try to find where things break.

And at the end of the day, most of what the android mode does is just calling the underlying android tools included in the SDK, for instance in the case of getImages(), the key step is running the avd manager to get the list of available images. Same thing when creating a new image, just calls the avd manager. That's why I recommended to try to running all these steps by yourself from the command line, to make sure they do work. If they do, it would be simply a matter of replicating the correct calls inside the mode.

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jun 28, 2022

@codeanticode @ranaaditya Thanks for the mentioned points to focus on, I have identified the cause of the issue and am able to run the sketch in the emulator by using Download New SDK option on startup.
WorkingEmulator
There is an emulator package not found error mentioned in the shared design document. This issue occurs with avd.create(sdk) I confirmed it by running AVD create command separately. The emulator is getting downloaded by setting DOWNLOAD_EMU to true. But when I checked with \Processing\android\sdk\cmdline-tools\latest\bin\sdkmanager.bat --list emulator was not mentioned as installed. So I separately installed the emulator on the command line with this command using sdkmanager. On checking again it was mentioned as installed via sdkmanager.bat --list. After this Running In Emulator option worked.
Now there is a need to check why the downloaded emulator was not listed as installed in sdkmanager's list. Another way is to use process builder to install the emulator through ./sdkmanager --channel=3 emulator. So that emulator can get identified while creating AVD by avdmanager. I may need confirmation on this issue with Download New SDK option -> Run In Emulator. If Download New SDK option does not popup on startup, removing C:\Users\User\AppData\Roaming\Processing\preferences.txt file would work to reset for a fresh start.

For the Use Existing SDK option I am facing javafx class not find issues, which is due to old command-line tools in existing SDK(being used by Android Studio). We can check for these inconsistencies while using existing SDK. Downoading of the system image file repeatedly is not because hasImages() returns false every time. I confirmed this method is working fine when using New SDK Download option. Also, I checked HAXM is not working and the emulator is not getting launched when using the existing SDK configured by Android Studio. So I will be working on this. Any suggestion or recommendation would be helpful.

@codeanticode
Copy link
Contributor

@rupeshkumar22 this is great progress, thank you! Some comments:

  • Emulator or system images not listed by sdkmanager? It's important that we do not mix up the emulator itself with the system images to be used by the emulator. I know its confusing, the emulator is essentially the program runs the virtual device on the host computer, while the system images contain the entire state a device, including system files, applications, etc. Because of that, the system images are very large (in the order of GBs). There is a separate class in the mode that handles downloading and installation system images, SysImageDownloader.

  • Downloading and installing the emulator. From what you say, it sounds like the emulator it should be downloaded and installed by the sdk manager using the command sdkmanager --channel=3 emulator. Right now, the emulator is parsed from the main repository and downloaded alongside the rest of the SDK files (if DOWNLOAD_EMU is set to true), with the downloadAndUnpack() method in the SDKDownloader. But maybe we have to replace this manual parsing and downloading of the emulator files with the sdkmanager command you mentioned. I guess the sdk manager incorporated these options after our implementation of SDKDownloader, so we should probably go with the newer approach, since the sdk manager is pulling the files from the correct online repositories and placing them in the correct locations in the computer. You also said that the you checked if the emulator was installed by running sdkmanager.bat --list, even though the first time did not work, perhaps you did this right after installing the emulator with through the mode, and then it worked after you installed manually with with the --channel=3 emulator option? My suspicion is that the current emulator download/installation in the android mode is broken in some way, and that's why sdkmanager.bat --list does not list the emulator. Only after you install the emulator with sdkmanager --channel=3 emulator then it's listed. So the solution would be to replace the old code to parse and download the emulator files with sdkmanager --channel=3 emulator

  • System images: From your tests, it seems like the system images get downloaded correctly, because without those, the emulator won't run, even if the emulator itself got installed correctly.

  • Advanced emulator features (HAXM (intel), AMD support): The default emulator is generic in that it does not take advantage of specific host CPU features to run faster (and because of that it can be quite slow). That's why these Intel and AMD-specific versions exist. I must say that get HAXM to work was tricky, because it needs the user to accept some extra permissions during install, so the mode had to run an extra installer, see implementation here. I imagine all of those installation scripts changed in recent versions of HAXM so this needs to be revised. The good thing is that all of this is optional optimizations, the emulator works without HAXM or AMD optimizations, although slower.

Properly supporting the emulator was always very tricky, but if the sdk manager is now able to handle download/installation by itself, then we could at least rely on that to make our lives easier.

@ranaaditya please let us know if you have additional insights/suggestions.

@ranaaditya
Copy link
Member

@rupeshkumar22 this is great progress, thank you! Some comments:

  • Emulator or system images not listed by sdkmanager? It's important that we do not mix up the emulator itself with the system images to be used by the emulator. I know its confusing, the emulator is essentially the program runs the virtual device on the host computer, while the system images contain the entire state a device, including system files, applications, etc. Because of that, the system images are very large (in the order of GBs). There is a separate class in the mode that handles downloading and installation system images, SysImageDownloader.
  • Downloading and installing the emulator. From what you say, it sounds like the emulator it should be downloaded and installed by the sdk manager using the command sdkmanager --channel=3 emulator. Right now, the emulator is parsed from the main repository and downloaded alongside the rest of the SDK files (if DOWNLOAD_EMU is set to true), with the downloadAndUnpack() method in the SDKDownloader. But maybe we have to replace this manual parsing and downloading of the emulator files with the sdkmanager command you mentioned. I guess the sdk manager incorporated these options after our implementation of SDKDownloader, so we should probably go with the newer approach, since the sdk manager is pulling the files from the correct online repositories and placing them in the correct locations in the computer. You also said that the you checked if the emulator was installed by running sdkmanager.bat --list, even though the first time did not work, perhaps you did this right after installing the emulator with through the mode, and then it worked after you installed manually with with the --channel=3 emulator option? My suspicion is that the current emulator download/installation in the android mode is broken in some way, and that's why sdkmanager.bat --list does not list the emulator. Only after you install the emulator with sdkmanager --channel=3 emulator then it's listed. So the solution would be to replace the old code to parse and download the emulator files with sdkmanager --channel=3 emulator
  • System images: From your tests, it seems like the system images get downloaded correctly, because without those, the emulator won't run, even if the emulator itself got installed correctly.
  • Advanced emulator features (HAXM (intel), AMD support): The default emulator is generic in that it does not take advantage of specific host CPU features to run faster (and because of that it can be quite slow). That's why these Intel and AMD-specific versions exist. I must say that get HAXM to work was tricky, because it needs the user to accept some extra permissions during install, so the mode had to run an extra installer, see implementation here. I imagine all of those installation scripts changed in recent versions of HAXM so this needs to be revised. The good thing is that all of this is optional optimizations, the emulator works without HAXM or AMD optimizations, although slower.

Properly supporting the emulator was always very tricky, but if the sdk manager is now able to handle download/installation by itself, then we could at least rely on that to make our lives easier.

@ranaaditya please let us know if you have additional insights/suggestions.

@codeanticode you have already given a very very detailed explanation here about emulators and system image.

I will look into this issue in depth and will update this thread if I find something meaningful.

Good work @rupeshkumar22 , keep it up 👌

Thanks,
Aditya Rana

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jun 28, 2022

@codeanticode things are more clear in depth with this detailed explanation. I'll consider these points during implementation.This is really helpful. For the query in the first comment- Yes, SDKmanager --list shows installed image and emulator separately. Now, I can start working on this without any doubt. Thanks!

@ranaaditya thanks for appreciation. I'll connect with you as discussed. Thanks!

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jul 3, 2022

Hi @codeanticode @ranaaditya
Here's my final update before creating a stable PR for the emulator support.
I faced repeated image downloading issues when I opt to use the existing SDK. The reason is that hasImages is always returning false But not because the required images do not exist but because avdmanager and sdkmanager are not working and show the following error-
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema inside getImages
The reason why avdmanager and sdkmanager are not working is beacuse the SDK tools are being used if Command line tools are not found here at
tmp = new File(folder, "tools");
The above line will never get executed if we opt to Download New SDK because it will always download the latest command-line tools. So the issue will not be there when Download New SDK is selected.
whereas Use Existing SDK option can set a depricated SDK Tools as command-line tools when command line tools not found (set sdk\tools\bin\sdkmanager.bat instead of sdk\cmdline-tools\latest\bin\sdkmanager.bat)

These deprecated SDK tools(sdk\tools\bin\sdkmanager.bat) will not work with the latest Java version. #666
The solution is to only use sdk\cmdline-tools after downloading cmdline-tools here at tmp = new File(folder, "tools"); in the similar way we are downloading here during New SDK download. This method has been tested and worked well. I will make sure the new emulator support update will only use sdkmanager from the downloaded command-line tools to download the required packages-platform tools, emulator, etc.(i.e sdkmanager --channel=3 emulator) instead of downloading them with the remote repository method as suggested.
Let me know if there are any suggestions for implementation. Thanks!

@codeanticode
Copy link
Contributor

@rupeshkumar22 thanks for the comments, great to know you are close to make a PR with the emulator fixes.

First of all, one quick observation about the code you pointed to:

    File tmp = new File(folder, "cmdline-tools/latest");
    if (!tmp.exists()) {
      tmp = new File(folder, "tools");
    } else if (!tmp.exists()) {
      throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_tools_folder", folder)); 
    }    

Isn't there a logic bug there? If tmp does not exist, then if goes to the else branch, where if check again it tmp exists, but at point we know it does, so it will never throw the BadSDKException? If I understand the meaning of that code correctly :-) shouldn't be:

    File tmp = new File(folder, "cmdline-tools/latest");
    if (!tmp.exists()) {
      tmp = new File(folder, "tools");
      if (!tmp.exists()) {
        throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_tools_folder", folder)); 
      }
    } 

But, if as you said, the versions of the SDK that have the command line tools inside the tools folder instead of cmdline-tools/latest are incompatible with the latest Java, then we should shown an error saying that the SDK is deprecated and a new one needs to be downloaded. Does it sound right? @ranaaditya what do you think?

@rupeshkumar22
Copy link
Contributor Author

rupeshkumar22 commented Jul 3, 2022

Isn't there a logic bug there? If tmp does not exist, then if goes to the else branch, where if check again it tmp exists, but at point we know it does, so it will never throw the BadSDKException? If I understand the meaning of that code correctly :-) shouldn't be:

Yes, there is a logic bug thanks for indicating. I plan to remove tmp = new File(folder, "tools"); So mainly it will look like -

    File tmp = new File(folder, "cmdline-tools/latest");
    if (!tmp.exists()) {
      // logic to download command line tools
     // then the  "cmdline-tools/latest" will be there and following condition will be false if properly downloaded 
      if (!tmp.exists()) {
        throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_tools_folder", folder)); 
      }
    } 

But, if as you said, the versions of the SDK that have the command line tools inside the tools folder instead of cmdline-tools/latest are incompatible with the latest Java, then we should shown an error saying that the SDK is deprecated and a new one needs to be downloaded. Does it sound right? @ranaaditya what do you think?

Yes, we can do that. This seems a better option to resolve any incompatibilities.

@codeanticode
Copy link
Contributor

You plan sounds good, thank you!

@ranaaditya
Copy link
Member

@rupeshkumar22 thanks for the comments, great to know you are close to make a PR with the emulator fixes.

First of all, one quick observation about the code you pointed to:

    File tmp = new File(folder, "cmdline-tools/latest");
    if (!tmp.exists()) {
      tmp = new File(folder, "tools");
    } else if (!tmp.exists()) {
      throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_tools_folder", folder)); 
    }    

Isn't there a logic bug there? If tmp does not exist, then if goes to the else branch, where if check again it tmp exists, but at point we know it does, so it will never throw the BadSDKException? If I understand the meaning of that code correctly :-) shouldn't be:

    File tmp = new File(folder, "cmdline-tools/latest");
    if (!tmp.exists()) {
      tmp = new File(folder, "tools");
      if (!tmp.exists()) {
        throw new BadSDKException(AndroidMode.getTextString("android_sdk.error.missing_tools_folder", folder)); 
      }
    } 

But, if as you said, the versions of the SDK that have the command line tools inside the tools folder instead of cmdline-tools/latest are incompatible with the latest Java, then we should shown an error saying that the SDK is deprecated and a new one needs to be downloaded. Does it sound right? @ranaaditya what do you think?

I agree with @codeanticode 's observation and with his suggestion

@rupeshkumar22
Copy link
Contributor Author

Hi @codeanticode @ranaaditya
While comparing the packages of emulators downloaded by the current downloader and the emulator downloaded directly, I found that package.xml file is missing in the extracted files downloaded by the current download and unpack methods.

I moved forward with implementing a process to download the emulator directly by executing the command. I see the following error-

at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Accept? (y/N): Skipping following packages as the license is not accepted:
SDK Patch Applier v4
Android Emulator
The following packages can not be installed since their licenses or those of the packages they depend on were not accepted:
  patcher;v4
  emulator

It seems that downloaded SDK packages just before downloaded emulators are dependent on the emulator and first the license of those packages needs to be accepted before downloading the emulator. I'm moving ahead with first implementing acceptance of license of existing packages before downloading Emulator. This seems to work because I remember first I accepted the license while downloading the emulator directly on the command line which was working well.

@ranaaditya
Copy link
Member

Hi @codeanticode @ranaaditya While comparing the packages of emulators downloaded by the current downloader and the emulator downloaded directly, I found that package.xml file is missing in the extracted files downloaded by the current download and unpack methods.

I moved forward with implementing a process to download the emulator directly by executing the command. I see the following error-

at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Accept? (y/N): Skipping following packages as the license is not accepted:
SDK Patch Applier v4
Android Emulator
The following packages can not be installed since their licenses or those of the packages they depend on were not accepted:
  patcher;v4
  emulator

It seems that downloaded SDK packages just before downloaded emulators are dependent on the emulator and first the license of those packages needs to be accepted before downloading the emulator. I'm moving ahead with first implementing acceptance of license of existing packages before downloading Emulator. This seems to work because I remember first I accepted the license while downloading the emulator directly on the command line which was working well.

good observation @rupeshkumar22 , is there any way to not disturb the user for accepting the Licence instead we can do that from code ? not sure about it but it pops a notification even in Android studio to accept the licence before downloading the sdk and emulator !

If you NDK issue while running the emulator for apps from PDE then refer issue #599 , solution is in the issue thread.

Thanks !

@rupeshkumar22
Copy link
Contributor Author

Yes, we can automate the license acceptance other than manually by code but as we see a popup is there to ask the user to accept the license, there would be a need or it would be a more responsible way to ask the user to accept the license. Yes Android Studio does the same, But it asks to accept licenses one by one package specific. Whereas we accept licenses for all packages after downloading the packages together combined. I think that is creating an issue in installing an emulator because the emulator is dependent on packages and until and unless the license of packages is not accepted, these are not a part of SDK before installing the emulator, thus creating an issue. After confirming the working of this resolution, I will create a PR asap. Thanks for pointing out the references!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants