Skip to content
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

Support Kitkat #3341

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open

Support Kitkat #3341

wants to merge 10 commits into from

Conversation

consp1racy
Copy link

@consp1racy consp1racy commented Jun 20, 2022

This is another attempt at suporting API 19. We're developing for a market that's often stuck 10 years ago and seeing this work felt amazing. Maybe label it as experimental.

What this consists of:

  • Rebase the original api19 branch on top of master.
  • Polyfill android.system.Os.write(FileDescriptor, ByteBuffer).
  • Backport MediaCodec.getOutputBuffer API.
  • Set ANDROID_HOME=/data/local/tmp for server.

What doesn't work:

What definitely works:

  • HTC Desire 601(rooted)
  • Philips 10BDL3051 (no root) with the ANDROID_DATA hack

The performance isn't amazing but it works.

htc desire 601

philips 10bdl3051t

Since "adb forward" fallback has been implemented, it is easy to support
API 19.

Replace the incompatible calls related to MediaCodec to use
minSdkVersion 19 instead of 21.
@consp1racy consp1racy changed the title Support Kitkat WIP: Support Kitkat Jun 20, 2022
Copy link
Collaborator

@rom1v rom1v left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your work.

I guess you followed #98 discussions. After re-reading it, when I concluded:

The video encoder does not work below 5.0.

Maybe it was related to the smart watch from the issue (without an hardware encoder) and not to Android < 5 after all. So indeed, it might be possible to support Android 4.4.

TBH, I'm not sure it's worth it to add support for 4.4 in 2022. It adds complexity and maintenance (btw there is still probably the dalvik-cache creation to handle). But if it works, maybe we could merge (anyway at least a separate up-to-date api19 branch could be useful)… I have no Android 4.4 device to test unfortunately. I will try to find one.

@@ -21,6 +21,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1'
compileOnly 'androidx.annotation:annotation:1.3.0' // 1.3.0 doesn't depend on Kotlin stdlib.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, the server should be buildable without any java/kotlin dependencies (and without gradle): build_without_gradle.sh

(Btw, I just removed the implementation fileTree line above: 7f2f595)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is it OK to download a prebuilt into a directory (e.g. prebuilt-compileOnly) and also use everything in it as classpath for javac? That should work both ways. I really want the IDE to help me not call API 19 stuff on API 21.

and without gradle

Any other reason than using build system within build system is weird? (And the flex of knowing how to manually produce an APK? 😁 )

Copy link
Collaborator

@rom1v rom1v Jun 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it OK to download a prebuilt into a directory

Nope. If it was a necessary dependency, we could discuss what to do, but here they are just annotations, it does not worth the dependency.

Any other reason than using build system within build system is weird?

It is used to build the official Debian package: https://salsa.debian.org/yangfl-guest/scrcpy/-/blob/ab5d09e733bb9635b4410693ceff95dbc859dd4c/debian/rules#L41
There were problems with gradle/kotlin (Debian provides its own packages for android tools), and it is not acceptable for Debian to download dependencies while building (there must be a separate package built from sources…).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only want @RequiresApi, Android Studio will probably be happy if we just include this one class in the project. Then we don't need to manage a dependency.

server/src/main/java/android/system/Os.java Outdated Show resolved Hide resolved
@consp1racy
Copy link
Author

consp1racy commented Jun 25, 2022

I've made it so the AndroidX annotation-1.3.0.jar lives as a copy inside the repo. It's a compile-only dependency both in server/build.gradle and server/build_without_gradle.sh. That way it contributes to developer experience in Android Studio, it contributes to lint, but has no effect on the produced artifact. The annotations and their calls are not present scrcpy-server binary.

The same thing now applies to the libcore.io package. This package is part of the framework and only needs to be presetn at compile time. The binary doesn't contain any of these classes.

The same approach should be done in the future with the system AIDL interfaces (e.g. IRotationWatcher.aidl or IClipboard) these are part of the framework and shouldn't be part of the binary. This only applies to gradle build.

android.system package remains shadowed for now. Tried doing it better but it bloated the binary.

Removed unnecessary logic from MediaCodecCompat.

Extracted MediaCodecListCompat from ScreenEncoder to keep it clean.

@consp1racy consp1racy changed the title WIP: Support Kitkat Support Kitkat Jun 27, 2022
@consp1racy
Copy link
Author

consp1racy commented Jun 27, 2022

  • We no longer shadow android.system package. Instead there's new androidx.system package.
  • OsCompat.write(FileDescriptor, ByteBuffer) now advances buffer position on all platforms. This was fixed in Lollopop MR1. This is no longer part of IO.writeFully.
  • OsCompat.write automatically retries on EINTR.
  • As a side-effect, we can now use lambdas.

This wraps up API 19 support. I think devices without an encoder, like the watch, should be handled separately, by querying PackageManager features or listing media codecs and failing with better error message.

So that we don't shadow framework classes in our binary.
Update buffer position in OsCompat.write (fixed in Lollipop MR1).
Synthesize InterruptedIOException in Kitkat like in Lollipop.
OsCompat never throws EINTR errno.
@consp1racy
Copy link
Author

  • Make the /data/local/tmp/dalvik-cache directory ourselves.

We need a path that is writable by shell on Android 4.

Genymobile#98 (comment)
@yume-chan
Copy link
Contributor

Why the video socket is using file descriptors, not standard Java streams? Is file descriptor faster than stream or something?

@consp1racy
Copy link
Author

Why the video socket is using file descriptors, not standard Java streams? Is file descriptor faster than stream or something?

66def38

@hebing0305
Copy link

I really need it. How can I download it?

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

Successfully merging this pull request may close these issues.

4 participants