Apply Genymobile rules for Android projects

Apply Genymobile checkstyle and gradle build files organization.
hidpi
Romain Vimont 6 years ago
parent 285fc97d02
commit e55e42a442

@ -0,0 +1,28 @@
apply plugin: 'checkstyle'
check.dependsOn 'checkstyle'
checkstyle {
toolVersion = '6.19'
}
task checkstyle(type: Checkstyle) {
description = "Check Java style with Checkstyle"
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
source = javaSources()
classpath = files()
ignoreFailures = true
}
def javaSources() {
def files = []
android.sourceSets.each { sourceSet ->
sourceSet.java.each { javaSource ->
javaSource.getSrcDirs().each {
if (it.exists()) {
files.add(it)
}
}
}
}
return files
}

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!-- This is a checkstyle configuration file. For descriptions of
what the following rules do, please see the checkstyle configuration
page at http://checkstyle.sourceforge.net/config.html -->
<module name="Checker">
<!-- Checks whether files end with a new line. -->
<!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
<module name="NewlineAtEndOfFile" />
<!-- Checks that property files contain the same keys. -->
<!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
<module name="Translation" />
<!-- Checks for Size Violations. -->
<!-- See http://checkstyle.sf.net/config_sizes.html -->
<module name="FileLength" />
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter" />
<!-- Miscellaneous other checks. -->
<!-- See http://checkstyle.sf.net/config_misc.html -->
<module name="RegexpSingleline">
<property name="format" value="\s+$" />
<property name="minimum" value="0" />
<property name="maximum" value="0" />
<property name="message" value="Line has trailing spaces." />
<property name="severity" value="info" />
</module>
<module name="SuppressWarningsFilter"/>
<module name="TreeWalker">
<!-- Checks for Naming Conventions. -->
<!-- See http://checkstyle.sf.net/config_naming.html -->
<module name="ConstantName" />
<module name="LocalFinalVariableName" />
<module name="LocalVariableName" />
<module name="MemberName" />
<module name="MethodName" />
<module name="PackageName" />
<module name="ParameterName" />
<module name="StaticVariableName" />
<module name="TypeName" />
<module name="SuppressWarningsHolder"/>
<!-- Checks for imports -->
<!-- See http://checkstyle.sf.net/config_import.html -->
<module name="AvoidStarImport">
<property name="allowStaticMemberImports" value="true" />
</module>
<module name="IllegalImport" />
<!-- defaults to sun.* packages -->
<module name="RedundantImport" />
<module name="UnusedImports" />
<module name="CustomImportOrder">
<property name="thirdPartyPackageRegExp" value=".*"/>
<property name="specialImportsRegExp" value="com.genymobile"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE###STATIC"/>
</module>
<!-- Checks for Size Violations. -->
<!-- See http://checkstyle.sf.net/config_sizes.html -->
<module name="LineLength">
<!-- what is a good max value? -->
<property name="max" value="150" />
<!-- ignore lines like "$File: //depot/... $" -->
<property name="ignorePattern" value="\$File.*\$" />
<property name="severity" value="info" />
</module>
<module name="MethodLength" />
<module name="ParameterNumber">
<property name="ignoreOverriddenMethods" value="true"/>
</module>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="EmptyForIteratorPad" />
<module name="GenericWhitespace" />
<module name="MethodParamPad" />
<module name="NoWhitespaceAfter" />
<module name="NoWhitespaceBefore" />
<module name="OperatorWrap" />
<module name="ParenPad" />
<module name="TypecastParenPad" />
<module name="WhitespaceAfter" />
<module name="WhitespaceAround" />
<!-- Modifier Checks -->
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
<module name="ModifierOrder" />
<module name="RedundantModifier" />
<!-- Checks for blocks. You know, those {}'s -->
<!-- See http://checkstyle.sf.net/config_blocks.html -->
<module name="AvoidNestedBlocks" />
<module name="EmptyBlock">
<property name="option" value="text" />
</module>
<module name="LeftCurly" />
<module name="NeedBraces" />
<module name="RightCurly" />
<!-- Checks for common coding problems -->
<!-- See http://checkstyle.sf.net/config_coding.html -->
<!-- <module name="AvoidInlineConditionals"/> -->
<module name="EmptyStatement" />
<module name="EqualsHashCode" />
<module name="HiddenField">
<property name="tokens" value="VARIABLE_DEF" />
<!-- only check variables not parameters -->
<property name="ignoreConstructorParameter" value="true" />
<property name="ignoreSetter" value="true" />
<property name="severity" value="warning" />
</module>
<module name="IllegalInstantiation" />
<module name="InnerAssignment" />
<module name="MagicNumber">
<property name="severity" value="info" />
<property name="ignoreHashCodeMethod" value="true" />
<property name="ignoreAnnotation" value="true" />
</module>
<module name="MissingSwitchDefault" />
<module name="SimplifyBooleanExpression" />
<module name="SimplifyBooleanReturn" />
<!-- Checks for class design -->
<!-- See http://checkstyle.sf.net/config_design.html -->
<!-- <module name="DesignForExtension"/> -->
<module name="FinalClass" />
<module name="HideUtilityClassConstructor" />
<module name="InterfaceIsType" />
<module name="VisibilityModifier" />
<!-- Miscellaneous other checks. -->
<!-- See http://checkstyle.sf.net/config_misc.html -->
<module name="ArrayTypeStyle" />
<!-- <module name="FinalParameters"/> -->
<module name="TodoComment">
<property name="format" value="TODO" />
<property name="severity" value="info" />
</module>
<module name="UpperEll" />
<module name="FileContentsHolder" />
<!-- Required by comment suppression filters -->
</module>
<module name="SuppressionFilter">
<!--<property name="file" value="team-props/checkstyle/checkstyle-suppressions.xml" />-->
</module>
<!-- Enable suppression comments -->
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE IGNORE\s+(\S+)" />
<property name="onCommentFormat" value="CHECKSTYLE END IGNORE\s+(\S+)" />
<property name="checkFormat" value="$1" />
</module>
<module name="SuppressWithNearbyCommentFilter">
<!-- Syntax is "SUPPRESS CHECKSTYLE name" -->
<property name="commentFormat" value="SUPPRESS CHECKSTYLE (\w+)" />
<property name="checkFormat" value="$1" />
<property name="influenceFormat" value="1" />
</module>
</module>

@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
compileSdkVersion 27
defaultConfig {
applicationId "com.genymobile.scrcpy"
minSdkVersion 21
targetSdkVersion 26
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@ -22,3 +22,5 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
}
apply from: "$project.rootDir/config/android-checkstyle.gradle"

@ -3,7 +3,7 @@ package com.genymobile.scrcpy;
/**
* Union of all supported event types, identified by their {@code type}.
*/
public class ControlEvent {
public final class ControlEvent {
public static final int TYPE_KEYCODE = 0;
public static final int TYPE_TEXT = 1;

@ -12,9 +12,12 @@ public class ControlEventReader {
private static final int SCROLL_PAYLOAD_LENGTH = 16;
private static final int COMMAND_PAYLOAD_LENGTH = 1;
private final byte[] rawBuffer = new byte[128];
private static final int MAX_TEXT_LENGTH = 32;
private static final int RAW_BUFFER_SIZE = 128;
private final byte[] rawBuffer = new byte[RAW_BUFFER_SIZE];
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
private final byte[] textBuffer = new byte[32];
private final byte[] textBuffer = new byte[MAX_TEXT_LENGTH];
public ControlEventReader() {
// invariant: the buffer is always in "get" mode
@ -136,10 +139,12 @@ public class ControlEventReader {
return new Position(x, y, screenWidth, screenHeight);
}
@SuppressWarnings("checkstyle:MagicNumber")
private static int toUnsigned(short value) {
return value & 0xffff;
}
@SuppressWarnings("checkstyle:MagicNumber")
private static int toUnsigned(byte value) {
return value & 0xff;
}

@ -9,7 +9,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class DesktopConnection implements Closeable {
public final class DesktopConnection implements Closeable {
private static final int DEVICE_NAME_FIELD_LENGTH = 64;
@ -48,9 +48,8 @@ public class DesktopConnection implements Closeable {
socket.close();
}
@SuppressWarnings("checkstyle:MagicNumber")
private void send(String deviceName, int width, int height) throws IOException {
assert width < 0x10000 : "width may not be stored on 16 bits";
assert height < 0x10000 : "height may not be stored on 16 bits";
byte[] buffer = new byte[DEVICE_NAME_FIELD_LENGTH + 4];
byte[] deviceNameBytes = deviceName.getBytes(StandardCharsets.UTF_8);

@ -1,13 +1,13 @@
package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.ServiceManager;
import android.graphics.Point;
import android.os.Build;
import android.os.RemoteException;
import android.view.IRotationWatcher;
import android.view.InputEvent;
import com.genymobile.scrcpy.wrappers.ServiceManager;
public final class Device {
public interface RotationListener {
@ -40,6 +40,7 @@ public final class Device {
return screenInfo;
}
@SuppressWarnings("checkstyle:MagicNumber")
private ScreenInfo computeScreenInfo(int maxSize) {
// Compute the video size and the padding of the content inside this video.
// Principle:
@ -52,7 +53,9 @@ public final class Device {
int w = deviceSize.getWidth();
int h = deviceSize.getHeight();
if (maxSize > 0) {
assert maxSize % 8 == 0;
if (BuildConfig.DEBUG && maxSize % 8 != 0) {
throw new AssertionError("Max size must be a multiple of 8");
}
boolean portrait = h > w;
int major = portrait ? h : w;
int minor = portrait ? w : h;
@ -70,6 +73,7 @@ public final class Device {
}
public Point getPhysicalPoint(Position position) {
@SuppressWarnings("checkstyle:HiddenField") // it hides the field on purpose, to read it with a lock
ScreenInfo screenInfo = getScreenInfo(); // read with synchronization
Size videoSize = screenInfo.getVideoSize();
Size clientVideoSize = position.getScreenSize();

@ -1,5 +1,7 @@
package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.InputManager;
import android.graphics.Point;
import android.os.SystemClock;
import android.view.InputDevice;
@ -8,10 +10,9 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import com.genymobile.scrcpy.wrappers.InputManager;
import java.io.IOException;
public class EventController {
private final Device device;
@ -83,6 +84,8 @@ public class EventController {
case ControlEvent.TYPE_COMMAND:
executeCommand(controlEvent.getAction());
break;
default:
// do nothing
}
}
@ -157,6 +160,8 @@ public class EventController {
switch (action) {
case ControlEvent.COMMAND_SCREEN_ON:
return turnScreenOn();
default:
Ln.w("Unsupported command: " + action);
}
return false;
}

@ -6,7 +6,7 @@ import android.util.Log;
* Log both to Android logger (so that logs are visible in "adb logcat") and standard output/error (so that they are visible in the terminal
* directly).
*/
public class Ln {
public final class Ln {
private static final String TAG = "scrcpy";

@ -27,11 +27,15 @@ public class Position {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Position position = (Position) o;
return Objects.equals(point, position.point) &&
Objects.equals(screenSize, position.screenSize);
return Objects.equals(point, position.point)
&& Objects.equals(screenSize, position.screenSize);
}
@Override
@ -41,10 +45,10 @@ public class Position {
@Override
public String toString() {
return "Position{" +
"point=" + point +
", screenSize=" + screenSize +
'}';
return "Position{"
+ "point=" + point
+ ", screenSize=" + screenSize
+ '}';
}
}

@ -2,7 +2,11 @@ package com.genymobile.scrcpy;
import java.io.IOException;
public class ScrCpyServer {
public final class ScrCpyServer {
private ScrCpyServer() {
// not instantiable
}
private static void scrcpy(Options options) throws IOException {
final Device device = new Device(options);
@ -34,6 +38,7 @@ public class ScrCpyServer {
}).start();
}
@SuppressWarnings("checkstyle:MagicNumber")
private static Options createOptions(String... args) {
Options options = new Options();
if (args.length < 1) {

@ -1,5 +1,7 @@
package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.SurfaceControl;
import android.graphics.Rect;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
@ -7,8 +9,6 @@ import android.media.MediaFormat;
import android.os.IBinder;
import android.view.Surface;
import com.genymobile.scrcpy.wrappers.SurfaceControl;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
@ -22,6 +22,8 @@ public class ScreenEncoder implements Device.RotationListener {
private static final int REPEAT_FRAME_DELAY = 6; // repeat after 6 frames
private static final int MICROSECONDS_IN_ONE_SECOND = 1_000_000;
private final AtomicBoolean rotationChanged = new AtomicBoolean();
private int bitRate;
@ -81,6 +83,7 @@ public class ScreenEncoder implements Device.RotationListener {
}
private boolean encode(MediaCodec codec, OutputStream outputStream) throws IOException {
@SuppressWarnings("checkstyle:MagicNumber")
byte[] buf = new byte[bitRate / 8]; // may contain up to 1 second of video
boolean eof = false;
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
@ -124,7 +127,7 @@ public class ScreenEncoder implements Device.RotationListener {
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
// display the very first frame, and recover from bad quality when no new frames
format.setLong(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1_000_000 * REPEAT_FRAME_DELAY / frameRate); // µs
format.setLong(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, MICROSECONDS_IN_ONE_SECOND * REPEAT_FRAME_DELAY / frameRate); // µs
return format;
}

@ -31,11 +31,15 @@ public final class Size {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Size size = (Size) o;
return width == size.width &&
height == size.height;
return width == size.width
&& height == size.height;
}
@Override
@ -45,9 +49,9 @@ public final class Size {
@Override
public String toString() {
return "Size{" +
"width=" + width +
", height=" + height +
'}';
return "Size{"
+ "width=" + width
+ ", height=" + height
+ '}';
}
}

@ -1,11 +1,11 @@
package com.genymobile.scrcpy.wrappers;
import android.os.IInterface;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.Size;
public class DisplayManager {
import android.os.IInterface;
public final class DisplayManager {
private final IInterface manager;
public DisplayManager(IInterface manager) {

@ -6,7 +6,7 @@ import android.view.InputEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InputManager {
public final class InputManager {
public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0;
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;

@ -1,19 +1,21 @@
package com.genymobile.scrcpy.wrappers;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.IInterface;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PowerManager {
public final class PowerManager {
private final IInterface manager;
private final Method isScreenOnMethod;
public PowerManager(IInterface manager) {
this.manager = manager;
try {
String methodName = Build.VERSION.SDK_INT >= 20 ? "isInteractive" : "isScreenOn";
@SuppressLint("ObsoleteSdkInt") // we may lower minSdkVersion in the future
String methodName = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH ? "isInteractive" : "isScreenOn";
isScreenOnMethod = manager.getClass().getMethod(methodName);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);

@ -1,11 +1,13 @@
package com.genymobile.scrcpy.wrappers;
import android.annotation.SuppressLint;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.Method;
public class ServiceManager {
@SuppressLint("PrivateApi")
public final class ServiceManager {
private final Method getServiceMethod;
private WindowManager windowManager;

@ -1,16 +1,18 @@
package com.genymobile.scrcpy.wrappers;
import android.annotation.SuppressLint;
import android.graphics.Rect;
import android.os.IBinder;
import android.view.Surface;
public class SurfaceControl {
@SuppressLint("PrivateApi")
public final class SurfaceControl {
private static final Class<?> cls;
private static final Class<?> CLASS;
static {
try {
cls = Class.forName("android.view.SurfaceControl");
CLASS = Class.forName("android.view.SurfaceControl");
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
@ -22,7 +24,7 @@ public class SurfaceControl {
public static void openTransaction() {
try {
cls.getMethod("openTransaction").invoke(null);
CLASS.getMethod("openTransaction").invoke(null);
} catch (Exception e) {
throw new AssertionError(e);
}
@ -30,7 +32,7 @@ public class SurfaceControl {
public static void closeTransaction() {
try {
cls.getMethod("closeTransaction").invoke(null);
CLASS.getMethod("closeTransaction").invoke(null);
} catch (Exception e) {
throw new AssertionError(e);
}
@ -38,7 +40,7 @@ public class SurfaceControl {
public static void setDisplayProjection(IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect) {
try {
cls.getMethod("setDisplayProjection", IBinder.class, int.class, Rect.class, Rect.class)
CLASS.getMethod("setDisplayProjection", IBinder.class, int.class, Rect.class, Rect.class)
.invoke(null, displayToken, orientation, layerStackRect, displayRect);
} catch (Exception e) {
throw new AssertionError(e);
@ -47,7 +49,7 @@ public class SurfaceControl {
public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
try {
cls.getMethod("setDisplayLayerStack", IBinder.class, int.class).invoke(null, displayToken, layerStack);
CLASS.getMethod("setDisplayLayerStack", IBinder.class, int.class).invoke(null, displayToken, layerStack);
} catch (Exception e) {
throw new AssertionError(e);
}
@ -55,7 +57,7 @@ public class SurfaceControl {
public static void setDisplaySurface(IBinder displayToken, Surface surface) {
try {
cls.getMethod("setDisplaySurface", IBinder.class, Surface.class).invoke(null, displayToken, surface);
CLASS.getMethod("setDisplaySurface", IBinder.class, Surface.class).invoke(null, displayToken, surface);
} catch (Exception e) {
throw new AssertionError(e);
}
@ -63,7 +65,7 @@ public class SurfaceControl {
public static IBinder createDisplay(String name, boolean secure) {
try {
return (IBinder) cls.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
return (IBinder) CLASS.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
} catch (Exception e) {
throw new AssertionError(e);
}
@ -71,7 +73,7 @@ public class SurfaceControl {
public static void destroyDisplay(IBinder displayToken) {
try {
cls.getMethod("destroyDisplay", IBinder.class).invoke(null, displayToken);
CLASS.getMethod("destroyDisplay", IBinder.class).invoke(null, displayToken);
} catch (Exception e) {
throw new AssertionError(e);
}

@ -3,7 +3,7 @@ package com.genymobile.scrcpy.wrappers;
import android.os.IInterface;
import android.view.IRotationWatcher;
public class WindowManager {
public final class WindowManager {
private final IInterface manager;
public WindowManager(IInterface manager) {

Loading…
Cancel
Save