Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Document a consistent way to detect that the Python interpreter is the Android app one #8

Closed
paulproteus opened this issue Apr 14, 2020 · 15 comments

Comments

@paulproteus
Copy link
Contributor

I would like to do some research to find out the best way to detect that we're running in Android. Toga uses this to choose the right widget library.

@freakboy3742
Copy link
Member

Effectively, sys.platform should be reporting android. The iOS builds report iOS; I can't remember off the top of my head the exact trigger that makes this happen, but I know it didn't require major surgery.

@paulproteus
Copy link
Contributor Author

Yeah; the thing I worry about is that CPython already has some notion of Android support, and I'd rather be consistent with that rather than inconsistent with it.

@paulproteus
Copy link
Contributor Author

In upstream CPython, they seem to rely on sys.getandroidapilevel existing. See:

I propose that we rely on that in Toga, rather than changing sys.platform. Right now sys.platform is linux.

Curious for your thoughts @freakboy3742 .

@freakboy3742
Copy link
Member

Can't argue with the fact that this is what they're currently doing; however I will very much argue that they're doing the right thing. Continuing to report sys.platform == 'linux' is just wrong. If Android is "linux", then so is BSD, HPUX, and every other Unix. Looking for the Android API level before confirming Android seems equally wrong.

I don't object to using the existence of getandroidapilevel as a proxy for Android identification in the short term, though.

@paulproteus
Copy link
Contributor Author

OK! I went ahead and documented this in README, with a link to this discussion.

From my perspective, Android definitionally is Linux -- it literally uses the Linux kernel. By contrast, HPUX and BSD systems do not use the Linux kernel. I would say the platform module https://docs.python.org/3/library/platform.html seems the best place to distinguish is-Android-or-not, rather than feature-detecting sys.getandroidapilevel. Maybe we can do that one day.

Should we close this for now? If you want, we can discuss more and/or badger CPython upstream. :)

@freakboy3742
Copy link
Member

The Android support that is upstream is very much half-hearted; there hasn't been a concerted effort to formally add Android support, just a bunch of patches that happen to make Android support easier.

From the docs, sys.platform is "a platform identifier that can be used to append platform-specific components to sys.path, for instance."

To me, that's pretty clearly saying that sys.platform needs to return something other than linux. To that end, I still consider this an outstanding bug.

@pmp-p
Copy link

pmp-p commented Feb 27, 2021

From my perspective, Android definitionally is Linux -- it literally uses the Linux kernel.

Yes definitely all the syscall are present, that's why returning anything other than linux in sys.platform idea was dropped (cf https://bugs.python.org/issue32637 + linked discussion).

The only straight differences are the dev+filesystem hierarchy ( which can also vary on GNU/Linux distro), shared memory handling (this one is real), the lack of systemd/gnu tools in userspace, and the possible enforcement of selinux.

sys.platform needs to return something other than linux

So maybe not ...
Because the diffences beetween Android open source project and common GNU/Linux with selinux enforcements are in the libc provided ( but not always used in userspace : as a matter of fact you can use a Linux cpython on Android).

To that end, I still consider this an outstanding bug.

The lack of proper libc api/abi and versionning detection is indeed a bug : It has the side effect of preventing stdlib/pip tools getting a proper idea of target. Not detecting properly an unsupported target and host at cold startup is imho a failure.

Maybe a possible option could be fake some os-release file for target as per https://bugs.python.org/issue28468 instead of raising an exception. That's no much more clumsy than testing getandroidapilevel attr, reading files or bloating sysconfig MULTIARCH vars. ( cf python-distro/distro#253 pmp-p/pydk#22 )

Generic info about cpython and android usefull ressources : https://pythondev.readthedocs.io/android.html

@mansourmoufid
Copy link
Contributor

That would be nice. I understand why sys.platform is "linux" but apps will inevitably have Android-specific logic. For example, the concept of requesting permissions doesn't exist on desktop GNU/Linux systems (well maybe, I'm not up to date).

For Android I have to do:

try:
    import toga_android
    sys.platform = 'android'
except ImportError:
    pass

It doesn't bother me but...

Maybe we need a toga.platform?

@freakboy3742
Copy link
Member

@eliteraspberries This already exists: its spelled toga.platform.current_platform.

Longer term, I still want to revisit the value of sys.platform on Android - I still argue that returning "Linux" is misleading - but in the short term, toga.platform.current_platform will unambiguously tell you the currently active platform (with the added benefit that it will identify when you're using the dummy, or a platform like web that isn't tied to the OS).

@mhsmith
Copy link
Member

mhsmith commented Aug 4, 2022

Another reason to keep sys.platform == "linux" on Android is that there's a large body of existing libraries which are not Android-aware, and maybe never will be, but for which Android is sufficiently similar to standard Linux that any behavior conditional on the "linux" value will still be correct.

Also, note that the sys.platform documentation defines the value in terms of the uname command, and the only difference between Linux and other Unixes is that Linux no longer includes the kernel version number since Python 3.3. Android actually does come with a uname command, and it returns "Linux".

After discussion today, we agreed to revisit this when we're ready to talk to the CPython team about them adopting Android as an officially-supported platform.

@pmp-p
Copy link

pmp-p commented Aug 4, 2022

sys.platform is what operating system you are running on and yes it is Linux with no doubt ( or it would not run debian out of the box when you change init ).

The only thing to solve is is identifiying the libc(codenamed bionic) and its version so two steps :

hasattr( sys, "getandroidapilevel") => if true, it's android for sure
then
sys.getandroidapilevel() => get bionic libc version ( API )

The only thing actually missing is the presence of a SE linux enforcement test routine which is becoming more and more a real problem ( see termux issues for more).

@freakboy3742
Copy link
Member

@pmp-p I'm not arguing that there's a Linux kernel under the hood. I'm arguing that from the perspective of end-users actually using the code, that fact is (mostly) irrelevant. Running Debian on their phone and operating through termux is not how the vast majority of Android users experience and operate their phones. Saying "this phone runs Linux" is not an observation that helps anyone, outside of use case that @mhsmith referred to (the fact that some existing code will work "accidentally on purpose" because Android is enough like a desktop/server machine to allow syscalls to work).

I refer you to my earlier comments about Python's definition of sys.platform. SELinux enforcement is very clearly not the only thing that is different between a phone and a laptop. If the purpose of sys.platform is to determine which platform-specific components should be added to the path, then being able to add an Android-specific path would seem to be a fairly important feature.

@pmp-p
Copy link

pmp-p commented Aug 4, 2022

i'm just replying to :"Document a consistent way to detect that the Python interpreter is the Android app one" though i thought @paulproteus did with #8 (comment)

so tldr;
if it's android app one, or running from adb shell : there is sys.getandroidapilevel
if it's linux python with not-bionic libc on android kernel : there is not.

And since you are, i would argue too that it's up to the platform module to "determine which platform-specific components should be added to the path" and that it should not be in stdlib but outside to allow easier "support of unsupported platforms"

That is in case @mhsmith get in touch with "cpython team" (what does that mean ? "core dev" ? "people in charge" ? i'm a bit confused here).
officially-supported platform means at least 1 android buildbot+ 1 dedicated coredev as per PEP11 : maybe someone could explain more what is the plan for that in a separate issue, there are not much opened here on Python-Android-support.

FYI: all stale android open issues are being closed eg python/cpython#71045 (comment)

@freakboy3742
Copy link
Member

@pmp-p I'm fully aware that getandroidapilevel exists. I'm arguing that isn't a good API for platform identification, which is what sys.platform is for.

I'm fully aware of PEP11, and I've had initial discussions with CPython core team (individually, and through presentations to the PyCon core team summit) about the prospects of elevating both Android and iOS to Tier 3 support. There aren't any concrete plans for this at present, but it's on the roadmap for BeeWare to look at. If I had to guess on timelines, I'd say next year's PyCon US core team summit will be when we start pursuing this in earnest. Those discussions will be primarily on CPython channels, rather than BeeWare channels.

I'm also aware that they're closing Android issues - that makes complete sense given that Android is, at present, not a supported platform. All the discussions I've had indicate that the Android-specific features that currently exist in the CPython codebase weren't merged with any particular plan or maintenance strategy in place; part of moving to Tier 3 support would be putting a consistent plan in maintenance strategy in place.

@freakboy3742
Copy link
Member

With the move to a Chaquopy base in Briefcase 0.3.10, this project is being archived, so I'm closing out all outstanding issues.

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

No branches or pull requests

5 participants