diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index edda3919..77d1f56f 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -152,7 +152,12 @@ page at http://checkstyle.sourceforge.net/config.html --> + + + + + diff --git a/libcore/build.gradle b/libcore/build.gradle new file mode 100644 index 00000000..9900fd60 --- /dev/null +++ b/libcore/build.gradle @@ -0,0 +1 @@ +apply plugin: 'java-library' diff --git a/libcore/src/main/java/libcore/io/ErrnoException.java b/libcore/src/main/java/libcore/io/ErrnoException.java new file mode 100644 index 00000000..be89321a --- /dev/null +++ b/libcore/src/main/java/libcore/io/ErrnoException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.io; + +/** + * A checked exception thrown when {@link Os} methods fail. This exception contains the native + * errno value, for comparison against the constants in {@link OsConstants}, should sophisticated + * callers need to adjust their behavior based on the exact failure. + */ +public final class ErrnoException extends Exception { + private final String functionName; + public final int errno; + + public ErrnoException(String functionName, int errno) { + throw new AssertionError(); + } +} diff --git a/libcore/src/main/java/libcore/io/Libcore.java b/libcore/src/main/java/libcore/io/Libcore.java new file mode 100644 index 00000000..0231ecb5 --- /dev/null +++ b/libcore/src/main/java/libcore/io/Libcore.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.io; + +public final class Libcore { + private Libcore() { + } + + public static Os os = null; +} diff --git a/libcore/src/main/java/libcore/io/Os.java b/libcore/src/main/java/libcore/io/Os.java new file mode 100644 index 00000000..4a9e61a8 --- /dev/null +++ b/libcore/src/main/java/libcore/io/Os.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.io; + +import java.io.FileDescriptor; +import java.nio.ByteBuffer; + +public interface Os { + public String strerror(int errno); + + public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException; +} diff --git a/libcore/src/main/java/libcore/io/OsConstants.java b/libcore/src/main/java/libcore/io/OsConstants.java new file mode 100644 index 00000000..ea0af53b --- /dev/null +++ b/libcore/src/main/java/libcore/io/OsConstants.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package libcore.io; + +public final class OsConstants { + private OsConstants() { + } + + public static final int EINTR = placeholder(); + + public static String errnoName(int errno) { + return null; + } + + // A hack to avoid these constants being inlined by javac... + private static int placeholder() { return 0; } +} diff --git a/server/build.gradle b/server/build.gradle index 67591e5b..dd7591e2 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) testImplementation 'junit:junit:4.13.1' compileOnly rootProject.fileTree("thirdparty/androidx/annotation/1.3.0/annotation-1.3.0.jar") + compileOnly project(':libcore') } apply from: "$project.rootDir/config/android-checkstyle.gradle" diff --git a/server/build_without_gradle.sh b/server/build_without_gradle.sh index e41e8e59..e4202e74 100755 --- a/server/build_without_gradle.sh +++ b/server/build_without_gradle.sh @@ -54,6 +54,8 @@ classpath="$CLASSES_DIR" classpath="$classpath:$ROOT_PROJECT_DIR/thirdparty/androidx/annotation/1.3.0/annotation-1.3.0.jar" javac -bootclasspath "$ANDROID_JAR" -cp "$classpath" -d "$CLASSES_DIR" \ -source 1.8 -target 1.8 \ + android/system/*.java \ + $ROOT_PROJECT_DIR/libcore/src/main/java/libcore/io/*.java \ com/genymobile/scrcpy/*.java \ com/genymobile/scrcpy/wrappers/*.java @@ -65,6 +67,7 @@ then # use dx "$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \ --output "$BUILD_DIR/classes.dex" \ + android/system/*.class \ android/view/*.class \ android/content/*.class \ com/genymobile/scrcpy/*.class \ @@ -78,6 +81,7 @@ else # use d8 "$ANDROID_HOME/build-tools/$BUILD_TOOLS/d8" --classpath "$ANDROID_JAR" \ --output "$BUILD_DIR/classes.zip" \ + android/system/*.class \ android/view/*.class \ android/content/*.class \ com/genymobile/scrcpy/*.class \ diff --git a/server/src/main/java/android/system/ErrnoException.java b/server/src/main/java/android/system/ErrnoException.java new file mode 100644 index 00000000..75d90193 --- /dev/null +++ b/server/src/main/java/android/system/ErrnoException.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.system; + +import android.annotation.TargetApi; + +import java.io.IOException; +import java.net.SocketException; + +import libcore.io.Libcore; + +/** + * A checked exception thrown when {@link Os} methods fail. This exception contains the native + * errno value, for comparison against the constants in {@link OsConstants}, should sophisticated + * callers need to adjust their behavior based on the exact failure. + */ +@SuppressWarnings("unused") +@TargetApi(21) +public final class ErrnoException extends Exception { + private final String functionName; + + /** + * The errno value, for comparison with the {@code E} constants in {@link OsConstants}. + */ + public final int errno; + + /** + * Constructs an instance with the given function name and errno value. + */ + public ErrnoException(String functionName, int errno) { + this.functionName = functionName; + this.errno = errno; + } + + /** + * Constructs an instance with the given function name, errno value, and cause. + */ + public ErrnoException(String functionName, int errno, Throwable cause) { + super(cause); + this.functionName = functionName; + this.errno = errno; + } + + /** + * Converts the stashed function name and errno value to a human-readable string. + * We do this here rather than in the constructor so that callers only pay for + * this if they need it. + */ + @Override public String getMessage() { + String errnoName = OsConstants.errnoName(errno); + if (errnoName == null) { + errnoName = "errno " + errno; + } + String description = Libcore.os.strerror(errno); + return functionName + " failed: " + errnoName + " (" + description + ")"; + } + + /** + * Throws an {@link IOException} with a message based on {@link #getMessage()} and with this + * instance as the cause. + * + *

This method always terminates by throwing the exception. Callers can write + * {@code throw e.rethrowAsIOException()} to make that clear to the compiler. + */ + public IOException rethrowAsIOException() throws IOException { + IOException newException = new IOException(getMessage()); + newException.initCause(this); + throw newException; + } + + /** + * Throws a {@link SocketException} with a message based on {@link #getMessage()} and with this + * instance as the cause. + * + *

This method always terminates by throwing the exception. Callers can write + * {@code throw e.rethrowAsIOException()} to make that clear to the compiler. + */ + public SocketException rethrowAsSocketException() throws SocketException { + final SocketException newException = new SocketException(getMessage()); + newException.initCause(this); + throw newException; + } +} diff --git a/server/src/main/java/android/system/Os.java b/server/src/main/java/android/system/Os.java new file mode 100644 index 00000000..456179ca --- /dev/null +++ b/server/src/main/java/android/system/Os.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.system; + +import android.annotation.TargetApi; + +import java.io.FileDescriptor; +import java.io.InterruptedIOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.SocketException; +import java.nio.ByteBuffer; + +import libcore.io.Libcore; + +/** + * Access to low-level system functionality. Most of these are system calls. Most users will want + * to use higher-level APIs where available, but this class provides access to the underlying + * primitives used to implement the higher-level APIs. + * + *

The corresponding constants can be found in {@link OsConstants}. + */ +@SuppressWarnings("unused") +@TargetApi(21) +public final class Os { + private Os() {} + + /** + * See write(2). + */ + public static int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException { + try { + return Libcore.os.write(fd, buffer); + } catch (libcore.io.ErrnoException e) { + throw new ErrnoException("write", e.errno); + } + } +} diff --git a/server/src/main/java/android/system/OsConstants.java b/server/src/main/java/android/system/OsConstants.java new file mode 100644 index 00000000..8580c6b6 --- /dev/null +++ b/server/src/main/java/android/system/OsConstants.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.system; + +import android.annotation.TargetApi; + +@SuppressWarnings("unused") +@TargetApi(21) +public final class OsConstants { + + private OsConstants() { } + + public static final int EINTR = libcore.io.OsConstants.EINTR; + + /** + * Returns the string name of an errno value. + * For example, "EACCES". See {@link Os#strerror} for human-readable errno descriptions. + */ + public static String errnoName(int errno) { + return libcore.io.OsConstants.errnoName(errno); + } +} diff --git a/server/src/main/java/com/genymobile/scrcpy/IO.java b/server/src/main/java/com/genymobile/scrcpy/IO.java index 57c017db..bc2f37bd 100644 --- a/server/src/main/java/com/genymobile/scrcpy/IO.java +++ b/server/src/main/java/com/genymobile/scrcpy/IO.java @@ -1,5 +1,6 @@ package com.genymobile.scrcpy; +import android.annotation.TargetApi; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -13,6 +14,7 @@ public final class IO { // not instantiable } + @TargetApi(21) // Backported subset of android.system. public static void writeFully(FileDescriptor fd, ByteBuffer from) throws IOException { // ByteBuffer position is not updated as expected by Os.write() on old Android versions, so // count the remaining bytes manually. diff --git a/settings.gradle b/settings.gradle index 8f51035f..31c8f101 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ include ':server' +include ':libcore'