Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
949b64dff2 | ||
|
|
00e9e69c2a | ||
|
|
4a5cdcd390 | ||
|
|
e5e210506f | ||
|
|
a2a22f497f | ||
|
|
51a1762cbd | ||
|
|
c1ec1d1023 | ||
|
|
0a0a446ea6 | ||
|
|
fccfc43b9e | ||
|
|
121bb71dfe |
13
app/data/scrcpy-console.desktop
Normal file
13
app/data/scrcpy-console.desktop
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=scrcpy (console)
|
||||||
|
GenericName=Android Remote Control
|
||||||
|
Comment=Display and control your Android device
|
||||||
|
# For some users, the PATH or ADB environment variables are set from the shell
|
||||||
|
# startup file, like .bashrc or .zshrc… Run an interactive shell to get
|
||||||
|
# environment correctly initialized.
|
||||||
|
Exec=/bin/bash --norc --noprofile -i -c '"$SHELL" -i -c scrcpy || read -p "Press any key to quit..."'
|
||||||
|
Icon=scrcpy
|
||||||
|
Terminal=true
|
||||||
|
Type=Application
|
||||||
|
Categories=Utility;RemoteAccess;
|
||||||
|
StartupNotify=false
|
||||||
13
app/data/scrcpy.desktop
Normal file
13
app/data/scrcpy.desktop
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=scrcpy
|
||||||
|
GenericName=Android Remote Control
|
||||||
|
Comment=Display and control your Android device
|
||||||
|
# For some users, the PATH or ADB environment variables are set from the shell
|
||||||
|
# startup file, like .bashrc or .zshrc… Run an interactive shell to get
|
||||||
|
# environment correctly initialized.
|
||||||
|
Exec=/bin/sh -c '"$SHELL" -i -c scrcpy'
|
||||||
|
Icon=scrcpy
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=Utility;RemoteAccess;
|
||||||
|
StartupNotify=false
|
||||||
@@ -223,14 +223,26 @@ executable('scrcpy', src,
|
|||||||
install: true,
|
install: true,
|
||||||
c_args: [])
|
c_args: [])
|
||||||
|
|
||||||
|
# <https://mesonbuild.com/Builtin-options.html#directories>
|
||||||
|
datadir = get_option('datadir') # by default 'share'
|
||||||
|
|
||||||
install_man('scrcpy.1')
|
install_man('scrcpy.1')
|
||||||
install_data('data/icon.png',
|
install_data('data/icon.png',
|
||||||
rename: 'scrcpy.png',
|
rename: 'scrcpy.png',
|
||||||
install_dir: 'share/icons/hicolor/256x256/apps')
|
install_dir: join_paths(datadir, 'icons/hicolor/256x256/apps'))
|
||||||
install_data('data/zsh-completion/_scrcpy',
|
install_data('data/zsh-completion/_scrcpy',
|
||||||
install_dir: 'share/zsh/site-functions')
|
install_dir: join_paths(datadir, 'zsh/site-functions'))
|
||||||
install_data('data/bash-completion/scrcpy',
|
install_data('data/bash-completion/scrcpy',
|
||||||
install_dir: 'share/bash-completion/completions')
|
install_dir: join_paths(datadir, 'bash-completion/completions'))
|
||||||
|
|
||||||
|
# Desktop entry file for application launchers
|
||||||
|
if host_machine.system() == 'linux'
|
||||||
|
# Install a launcher (ex: /usr/local/share/applications/scrcpy.desktop)
|
||||||
|
install_data('data/scrcpy.desktop',
|
||||||
|
install_dir: join_paths(datadir, 'applications'))
|
||||||
|
install_data('data/scrcpy-console.desktop',
|
||||||
|
install_dir: join_paths(datadir, 'applications'))
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
### TESTS
|
### TESTS
|
||||||
|
|||||||
@@ -92,8 +92,14 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned flags,
|
|||||||
close(in[0]);
|
close(in[0]);
|
||||||
}
|
}
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
|
} else {
|
||||||
|
int devnull = open("/dev/null", O_RDONLY | O_CREAT, 0666);
|
||||||
|
if (devnull != -1) {
|
||||||
|
dup2(devnull, STDIN_FILENO);
|
||||||
|
} else {
|
||||||
|
LOGE("Could not open /dev/null for stdin");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Do not close stdin in the child process, this makes adb fail on Linux
|
|
||||||
|
|
||||||
if (pout) {
|
if (pout) {
|
||||||
if (out[1] != STDOUT_FILENO) {
|
if (out[1] != STDOUT_FILENO) {
|
||||||
@@ -102,8 +108,12 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned flags,
|
|||||||
}
|
}
|
||||||
close(out[0]);
|
close(out[0]);
|
||||||
} else if (!inherit_stdout) {
|
} else if (!inherit_stdout) {
|
||||||
// Close stdout in the child process
|
int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666);
|
||||||
close(STDOUT_FILENO);
|
if (devnull != -1) {
|
||||||
|
dup2(devnull, STDOUT_FILENO);
|
||||||
|
} else {
|
||||||
|
LOGE("Could not open /dev/null for stdout");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perr) {
|
if (perr) {
|
||||||
@@ -113,8 +123,12 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned flags,
|
|||||||
}
|
}
|
||||||
close(err[0]);
|
close(err[0]);
|
||||||
} else if (!inherit_stderr) {
|
} else if (!inherit_stderr) {
|
||||||
// Close stderr in the child process
|
int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666);
|
||||||
close(STDERR_FILENO);
|
if (devnull != -1) {
|
||||||
|
dup2(devnull, STDERR_FILENO);
|
||||||
|
} else {
|
||||||
|
LOGE("Could not open /dev/null for stderr");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
classpath 'com.android.tools.build:gradle:7.2.2'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
@@ -17,7 +17,7 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
options.compilerArgs << "-Xlint:deprecation"
|
options.compilerArgs << "-Xlint:deprecation"
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 33
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.genymobile.scrcpy"
|
applicationId "com.genymobile.scrcpy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 31
|
targetSdkVersion 33
|
||||||
versionCode 12400
|
versionCode 12400
|
||||||
versionName "1.24"
|
versionName "1.24"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ set -e
|
|||||||
SCRCPY_DEBUG=false
|
SCRCPY_DEBUG=false
|
||||||
SCRCPY_VERSION_NAME=1.24
|
SCRCPY_VERSION_NAME=1.24
|
||||||
|
|
||||||
PLATFORM=${ANDROID_PLATFORM:-31}
|
PLATFORM=${ANDROID_PLATFORM:-33}
|
||||||
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-31.0.0}
|
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-33.0.0}
|
||||||
|
BUILD_TOOLS_DIR="$ANDROID_HOME/build-tools/$BUILD_TOOLS"
|
||||||
|
|
||||||
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
|
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
|
||||||
CLASSES_DIR="$BUILD_DIR/classes"
|
CLASSES_DIR="$BUILD_DIR/classes"
|
||||||
@@ -41,9 +42,8 @@ EOF
|
|||||||
|
|
||||||
echo "Generating java from aidl..."
|
echo "Generating java from aidl..."
|
||||||
cd "$SERVER_DIR/src/main/aidl"
|
cd "$SERVER_DIR/src/main/aidl"
|
||||||
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o"$CLASSES_DIR" \
|
"$BUILD_TOOLS_DIR/aidl" -o"$CLASSES_DIR" android/view/IRotationWatcher.aidl
|
||||||
android/view/IRotationWatcher.aidl
|
"$BUILD_TOOLS_DIR/aidl" -o"$CLASSES_DIR" \
|
||||||
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o"$CLASSES_DIR" \
|
|
||||||
android/content/IOnPrimaryClipChangedListener.aidl
|
android/content/IOnPrimaryClipChangedListener.aidl
|
||||||
|
|
||||||
echo "Compiling java sources..."
|
echo "Compiling java sources..."
|
||||||
@@ -59,8 +59,7 @@ cd "$CLASSES_DIR"
|
|||||||
if [[ $PLATFORM -lt 31 ]]
|
if [[ $PLATFORM -lt 31 ]]
|
||||||
then
|
then
|
||||||
# use dx
|
# use dx
|
||||||
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \
|
"$BUILD_TOOLS_DIR/dx" --dex --output "$BUILD_DIR/classes.dex" \
|
||||||
--output "$BUILD_DIR/classes.dex" \
|
|
||||||
android/view/*.class \
|
android/view/*.class \
|
||||||
android/content/*.class \
|
android/content/*.class \
|
||||||
com/genymobile/scrcpy/*.class \
|
com/genymobile/scrcpy/*.class \
|
||||||
@@ -72,7 +71,7 @@ then
|
|||||||
rm -rf classes.dex classes
|
rm -rf classes.dex classes
|
||||||
else
|
else
|
||||||
# use d8
|
# use d8
|
||||||
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/d8" --classpath "$ANDROID_JAR" \
|
"$BUILD_TOOLS_DIR/d8" --classpath "$ANDROID_JAR" \
|
||||||
--output "$BUILD_DIR/classes.zip" \
|
--output "$BUILD_DIR/classes.zip" \
|
||||||
android/view/*.class \
|
android/view/*.class \
|
||||||
android/content/*.class \
|
android/content/*.class \
|
||||||
|
|||||||
@@ -30,4 +30,14 @@ public final class Command {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String execReadOutput(String... cmd) throws IOException, InterruptedException {
|
||||||
|
Process process = Runtime.getRuntime().exec(cmd);
|
||||||
|
String output = IO.toString(process.getInputStream());
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import android.system.OsConstants;
|
|||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
public final class IO {
|
public final class IO {
|
||||||
private IO() {
|
private IO() {
|
||||||
@@ -37,4 +39,13 @@ public final class IO {
|
|||||||
public static void writeFully(FileDescriptor fd, byte[] buffer, int offset, int len) throws IOException {
|
public static void writeFully(FileDescriptor fd, byte[] buffer, int offset, int len) throws IOException {
|
||||||
writeFully(fd, ByteBuffer.wrap(buffer, offset, len));
|
writeFully(fd, ByteBuffer.wrap(buffer, offset, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toString(InputStream inputStream) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
Scanner scanner = new Scanner(inputStream);
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
builder.append(scanner.nextLine()).append('\n');
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.Command;
|
||||||
import com.genymobile.scrcpy.DisplayInfo;
|
import com.genymobile.scrcpy.DisplayInfo;
|
||||||
|
import com.genymobile.scrcpy.Ln;
|
||||||
import com.genymobile.scrcpy.Size;
|
import com.genymobile.scrcpy.Size;
|
||||||
|
|
||||||
|
import android.view.Display;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class DisplayManager {
|
public final class DisplayManager {
|
||||||
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
||||||
|
|
||||||
@@ -10,11 +18,61 @@ public final class DisplayManager {
|
|||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public to call it from unit tests
|
||||||
|
public static DisplayInfo parseDisplayInfo(String dumpsysDisplayOutput, int displayId) {
|
||||||
|
Pattern regex = Pattern.compile(
|
||||||
|
"^ mOverrideDisplayInfo=DisplayInfo\\{\".*?\", displayId " + displayId + ".*?(, FLAG_.*)?, real ([0-9]+) x ([0-9]+).*?, "
|
||||||
|
+ "rotation ([0-9]+).*?, layerStack ([0-9]+)",
|
||||||
|
Pattern.MULTILINE);
|
||||||
|
Matcher m = regex.matcher(dumpsysDisplayOutput);
|
||||||
|
if (!m.find()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int flags = parseDisplayFlags(m.group(1));
|
||||||
|
int width = Integer.parseInt(m.group(2));
|
||||||
|
int height = Integer.parseInt(m.group(3));
|
||||||
|
int rotation = Integer.parseInt(m.group(4));
|
||||||
|
int layerStack = Integer.parseInt(m.group(5));
|
||||||
|
|
||||||
|
return new DisplayInfo(displayId, new Size(width, height), rotation, layerStack, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DisplayInfo getDisplayInfoFromDumpsysDisplay(int displayId) {
|
||||||
|
try {
|
||||||
|
String dumpsysDisplayOutput = Command.execReadOutput("dumpsys", "display");
|
||||||
|
return parseDisplayInfo(dumpsysDisplayOutput, displayId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Ln.e("Could not get display info from \"dumpsys display\" output", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int parseDisplayFlags(String text) {
|
||||||
|
Pattern regex = Pattern.compile("FLAG_[A-Z_]+");
|
||||||
|
if (text == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
Matcher m = regex.matcher(text);
|
||||||
|
while (m.find()) {
|
||||||
|
String flagString = m.group();
|
||||||
|
try {
|
||||||
|
Field filed = Display.class.getDeclaredField(flagString);
|
||||||
|
flags |= filed.getInt(null);
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
// Silently ignore, some flags reported by "dumpsys display" are @TestApi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
public DisplayInfo getDisplayInfo(int displayId) {
|
public DisplayInfo getDisplayInfo(int displayId) {
|
||||||
try {
|
try {
|
||||||
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, displayId);
|
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, displayId);
|
||||||
if (displayInfo == null) {
|
if (displayInfo == null) {
|
||||||
return null;
|
// fallback when displayInfo is null
|
||||||
|
return getDisplayInfoFromDumpsysDisplay(displayId);
|
||||||
}
|
}
|
||||||
Class<?> cls = displayInfo.getClass();
|
Class<?> cls = displayInfo.getClass();
|
||||||
// width and height already take the rotation into account
|
// width and height already take the rotation into account
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.wrappers.DisplayManager;
|
||||||
|
|
||||||
|
import android.view.Display;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class CommandParserTest {
|
||||||
|
@Test
|
||||||
|
public void testParseDisplayInfoFromDumpsysDisplay() {
|
||||||
|
/* @formatter:off */
|
||||||
|
String partialOutput = "Logical Displays: size=1\n"
|
||||||
|
+ " Display 0:\n"
|
||||||
|
+ "mDisplayId=0\n"
|
||||||
|
+ " mLayerStack=0\n"
|
||||||
|
+ " mHasContent=true\n"
|
||||||
|
+ " mDesiredDisplayModeSpecs={baseModeId=2 primaryRefreshRateRange=[90 90] appRequestRefreshRateRange=[90 90]}\n"
|
||||||
|
+ " mRequestedColorMode=0\n"
|
||||||
|
+ " mDisplayOffset=(0, 0)\n"
|
||||||
|
+ " mDisplayScalingDisabled=false\n"
|
||||||
|
+ " mPrimaryDisplayDevice=Built-in Screen\n"
|
||||||
|
+ " mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, "
|
||||||
|
+ "real 1440 x 3120, largest app 1440 x 3120, smallest app 1440 x 3120, appVsyncOff 2000000, presDeadline 11111111, mode 2, "
|
||||||
|
+ "defaultMode 1, modes [{id=1, width=1440, height=3120, fps=60.0}, {id=2, width=1440, height=3120, fps=90.0}, {id=3, width=1080, "
|
||||||
|
+ "height=2340, fps=90.0}, {id=4, width=1080, height=2340, fps=60.0}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[2, 3, 4], "
|
||||||
|
+ "mMaxLuminance=540.0, mMaxAverageLuminance=270.1, mMinLuminance=0.2}, minimalPostProcessingSupported false, rotation 0, state OFF, "
|
||||||
|
+ "type INTERNAL, uniqueId \"local:0\", app 1440 x 3120, density 600 (515.154 x 514.597) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0, 7, 9], address {port=129, model=0}, deviceProductInfo DeviceProductInfo{name=, manufacturerPnpId=QCM, "
|
||||||
|
+ "productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, relativeAddress=null}, removeMode 0}\n"
|
||||||
|
+ " mOverrideDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, "
|
||||||
|
+ "FLAG_TRUSTED, real 1440 x 3120, largest app 3120 x 2983, smallest app 1440 x 1303, appVsyncOff 2000000, presDeadline 11111111, "
|
||||||
|
+ "mode 2, defaultMode 1, modes [{id=1, width=1440, height=3120, fps=60.0}, {id=2, width=1440, height=3120, fps=90.0}, {id=3, "
|
||||||
|
+ "width=1080, height=2340, fps=90.0}, {id=4, width=1080, height=2340, fps=60.0}], hdrCapabilities "
|
||||||
|
+ "HdrCapabilities{mSupportedHdrTypes=[2, 3, 4], mMaxLuminance=540.0, mMaxAverageLuminance=270.1, mMinLuminance=0.2}, "
|
||||||
|
+ "minimalPostProcessingSupported false, rotation 0, state ON, type INTERNAL, uniqueId \"local:0\", app 1440 x 3120, density 600 "
|
||||||
|
+ "(515.154 x 514.597) dpi, layerStack 0, colorMode 0, supportedColorModes [0, 7, 9], address {port=129, model=0}, deviceProductInfo "
|
||||||
|
+ "DeviceProductInfo{name=, manufacturerPnpId=QCM, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, "
|
||||||
|
+ "relativeAddress=null}, removeMode 0}\n"
|
||||||
|
+ " mRequestedMinimalPostProcessing=false\n";
|
||||||
|
DisplayInfo displayInfo = DisplayManager.parseDisplayInfo(partialOutput, 0);
|
||||||
|
Assert.assertNotNull(displayInfo);
|
||||||
|
Assert.assertEquals(0, displayInfo.getDisplayId());
|
||||||
|
Assert.assertEquals(0, displayInfo.getRotation());
|
||||||
|
Assert.assertEquals(0, displayInfo.getLayerStack());
|
||||||
|
// FLAG_TRUSTED does not exist in Display (@TestApi), so it won't be reported
|
||||||
|
Assert.assertEquals(Display.FLAG_SECURE | Display.FLAG_SUPPORTS_PROTECTED_BUFFERS, displayInfo.getFlags());
|
||||||
|
Assert.assertEquals(1440, displayInfo.getSize().getWidth());
|
||||||
|
Assert.assertEquals(3120, displayInfo.getSize().getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseDisplayInfoFromDumpsysDisplayWithRotation() {
|
||||||
|
/* @formatter:off */
|
||||||
|
String partialOutput = "Logical Displays: size=1\n"
|
||||||
|
+ " Display 0:\n"
|
||||||
|
+ "mDisplayId=0\n"
|
||||||
|
+ " mLayerStack=0\n"
|
||||||
|
+ " mHasContent=true\n"
|
||||||
|
+ " mDesiredDisplayModeSpecs={baseModeId=2 primaryRefreshRateRange=[90 90] appRequestRefreshRateRange=[90 90]}\n"
|
||||||
|
+ " mRequestedColorMode=0\n"
|
||||||
|
+ " mDisplayOffset=(0, 0)\n"
|
||||||
|
+ " mDisplayScalingDisabled=false\n"
|
||||||
|
+ " mPrimaryDisplayDevice=Built-in Screen\n"
|
||||||
|
+ " mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, "
|
||||||
|
+ "real 1440 x 3120, largest app 1440 x 3120, smallest app 1440 x 3120, appVsyncOff 2000000, presDeadline 11111111, mode 2, "
|
||||||
|
+ "defaultMode 1, modes [{id=1, width=1440, height=3120, fps=60.0}, {id=2, width=1440, height=3120, fps=90.0}, {id=3, width=1080, "
|
||||||
|
+ "height=2340, fps=90.0}, {id=4, width=1080, height=2340, fps=60.0}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[2, 3, 4], "
|
||||||
|
+ "mMaxLuminance=540.0, mMaxAverageLuminance=270.1, mMinLuminance=0.2}, minimalPostProcessingSupported false, rotation 0, state ON, "
|
||||||
|
+ "type INTERNAL, uniqueId \"local:0\", app 1440 x 3120, density 600 (515.154 x 514.597) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0, 7, 9], address {port=129, model=0}, deviceProductInfo DeviceProductInfo{name=, manufacturerPnpId=QCM, "
|
||||||
|
+ "productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, relativeAddress=null}, removeMode 0}\n"
|
||||||
|
+ " mOverrideDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, "
|
||||||
|
+ "FLAG_TRUSTED, real 3120 x 1440, largest app 3120 x 2983, smallest app 1440 x 1303, appVsyncOff 2000000, presDeadline 11111111, "
|
||||||
|
+ "mode 2, defaultMode 1, modes [{id=1, width=1440, height=3120, fps=60.0}, {id=2, width=1440, height=3120, fps=90.0}, {id=3, "
|
||||||
|
+ "width=1080, height=2340, fps=90.0}, {id=4, width=1080, height=2340, fps=60.0}], hdrCapabilities "
|
||||||
|
+ "HdrCapabilities{mSupportedHdrTypes=[2, 3, 4], mMaxLuminance=540.0, mMaxAverageLuminance=270.1, mMinLuminance=0.2}, "
|
||||||
|
+ "minimalPostProcessingSupported false, rotation 3, state ON, type INTERNAL, uniqueId \"local:0\", app 3120 x 1440, density 600 "
|
||||||
|
+ "(515.154 x 514.597) dpi, layerStack 0, colorMode 0, supportedColorModes [0, 7, 9], address {port=129, model=0}, deviceProductInfo "
|
||||||
|
+ "DeviceProductInfo{name=, manufacturerPnpId=QCM, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, "
|
||||||
|
+ "relativeAddress=null}, removeMode 0}\n"
|
||||||
|
+ " mRequestedMinimalPostProcessing=false";
|
||||||
|
DisplayInfo displayInfo = DisplayManager.parseDisplayInfo(partialOutput, 0);
|
||||||
|
Assert.assertNotNull(displayInfo);
|
||||||
|
Assert.assertEquals(0, displayInfo.getDisplayId());
|
||||||
|
Assert.assertEquals(3, displayInfo.getRotation());
|
||||||
|
Assert.assertEquals(0, displayInfo.getLayerStack());
|
||||||
|
// FLAG_TRUSTED does not exist in Display (@TestApi), so it won't be reported
|
||||||
|
Assert.assertEquals(Display.FLAG_SECURE | Display.FLAG_SUPPORTS_PROTECTED_BUFFERS, displayInfo.getFlags());
|
||||||
|
Assert.assertEquals(3120, displayInfo.getSize().getWidth());
|
||||||
|
Assert.assertEquals(1440, displayInfo.getSize().getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseDisplayInfoFromDumpsysDisplayAPI31() {
|
||||||
|
/* @formatter:off */
|
||||||
|
String partialOutput = "Logical Displays: size=1\n"
|
||||||
|
+ " Display 0:\n"
|
||||||
|
+ " mDisplayId=0\n"
|
||||||
|
+ " mPhase=1\n"
|
||||||
|
+ " mLayerStack=0\n"
|
||||||
|
+ " mHasContent=true\n"
|
||||||
|
+ " mDesiredDisplayModeSpecs={baseModeId=1 allowGroupSwitching=false primaryRefreshRateRange=[0 60] appRequestRefreshRateRange=[0 "
|
||||||
|
+ "Infinity]}\n"
|
||||||
|
+ " mRequestedColorMode=0\n"
|
||||||
|
+ " mDisplayOffset=(0, 0)\n"
|
||||||
|
+ " mDisplayScalingDisabled=false\n"
|
||||||
|
+ " mPrimaryDisplayDevice=Built-in Screen\n"
|
||||||
|
+ " mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0\", displayGroupId 0, FLAG_SECURE, "
|
||||||
|
+ "FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, real 1080 x 2280, largest app 1080 x 2280, smallest app 1080 x 2280, appVsyncOff "
|
||||||
|
+ "1000000, presDeadline 16666666, mode 1, defaultMode 1, modes [{id=1, width=1080, height=2280, fps=60.000004, "
|
||||||
|
+ "alternativeRefreshRates=[]}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[], mMaxLuminance=500.0, "
|
||||||
|
+ "mMaxAverageLuminance=500.0, mMinLuminance=0.0}, userDisabledHdrTypes [], minimalPostProcessingSupported false, rotation 0, state "
|
||||||
|
+ "ON, type INTERNAL, uniqueId \"local:0\", app 1080 x 2280, density 440 (440.0 x 440.0) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0], address {port=0, model=0}, deviceProductInfo DeviceProductInfo{name=EMU_display_0, "
|
||||||
|
+ "manufacturerPnpId=GGL, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, connectionToSinkType=0}, "
|
||||||
|
+ "removeMode 0, refreshRateOverride 0.0, brightnessMinimum 0.0, brightnessMaximum 1.0, brightnessDefault 0.39763778}\n"
|
||||||
|
+ " mOverrideDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0\", displayGroupId 0, FLAG_SECURE, "
|
||||||
|
+ "FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, real 1080 x 2280, largest app 2148 x 2065, smallest app 1080 x 997, appVsyncOff "
|
||||||
|
+ "1000000, presDeadline 16666666, mode 1, defaultMode 1, modes [{id=1, width=1080, height=2280, fps=60.000004, "
|
||||||
|
+ "alternativeRefreshRates=[]}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[], mMaxLuminance=500.0, "
|
||||||
|
+ "mMaxAverageLuminance=500.0, mMinLuminance=0.0}, userDisabledHdrTypes [], minimalPostProcessingSupported false, rotation 0, state "
|
||||||
|
+ "ON, type INTERNAL, uniqueId \"local:0\", app 1080 x 2148, density 440 (440.0 x 440.0) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0], address {port=0, model=0}, deviceProductInfo DeviceProductInfo{name=EMU_display_0, "
|
||||||
|
+ "manufacturerPnpId=GGL, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, connectionToSinkType=0}, "
|
||||||
|
+ "removeMode 0, refreshRateOverride 0.0, brightnessMinimum 0.0, brightnessMaximum 1.0, brightnessDefault 0.39763778}\n"
|
||||||
|
+ " mRequestedMinimalPostProcessing=false\n"
|
||||||
|
+ " mFrameRateOverrides=[]\n"
|
||||||
|
+ " mPendingFrameRateOverrideUids={}\n";
|
||||||
|
DisplayInfo displayInfo = DisplayManager.parseDisplayInfo(partialOutput, 0);
|
||||||
|
Assert.assertNotNull(displayInfo);
|
||||||
|
Assert.assertEquals(0, displayInfo.getDisplayId());
|
||||||
|
Assert.assertEquals(0, displayInfo.getRotation());
|
||||||
|
Assert.assertEquals(0, displayInfo.getLayerStack());
|
||||||
|
// FLAG_TRUSTED does not exist in Display (@TestApi), so it won't be reported
|
||||||
|
Assert.assertEquals(Display.FLAG_SECURE | Display.FLAG_SUPPORTS_PROTECTED_BUFFERS, displayInfo.getFlags());
|
||||||
|
Assert.assertEquals(1080, displayInfo.getSize().getWidth());
|
||||||
|
Assert.assertEquals(2280, displayInfo.getSize().getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseDisplayInfoFromDumpsysDisplayAPI31NoFlags() {
|
||||||
|
/* @formatter:off */
|
||||||
|
String partialOutput = "Logical Displays: size=1\n"
|
||||||
|
+ " Display 0:\n"
|
||||||
|
+ " mDisplayId=0\n"
|
||||||
|
+ " mPhase=1\n"
|
||||||
|
+ " mLayerStack=0\n"
|
||||||
|
+ " mHasContent=true\n"
|
||||||
|
+ " mDesiredDisplayModeSpecs={baseModeId=1 allowGroupSwitching=false primaryRefreshRateRange=[0 60] appRequestRefreshRateRange=[0 "
|
||||||
|
+ "Infinity]}\n"
|
||||||
|
+ " mRequestedColorMode=0\n"
|
||||||
|
+ " mDisplayOffset=(0, 0)\n"
|
||||||
|
+ " mDisplayScalingDisabled=false\n"
|
||||||
|
+ " mPrimaryDisplayDevice=Built-in Screen\n"
|
||||||
|
+ " mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0\", displayGroupId 0, "
|
||||||
|
+ "real 1080 x 2280, largest app 1080 x 2280, smallest app 1080 x 2280, appVsyncOff "
|
||||||
|
+ "1000000, presDeadline 16666666, mode 1, defaultMode 1, modes [{id=1, width=1080, height=2280, fps=60.000004, "
|
||||||
|
+ "alternativeRefreshRates=[]}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[], mMaxLuminance=500.0, "
|
||||||
|
+ "mMaxAverageLuminance=500.0, mMinLuminance=0.0}, userDisabledHdrTypes [], minimalPostProcessingSupported false, rotation 0, state "
|
||||||
|
+ "ON, type INTERNAL, uniqueId \"local:0\", app 1080 x 2280, density 440 (440.0 x 440.0) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0], address {port=0, model=0}, deviceProductInfo DeviceProductInfo{name=EMU_display_0, "
|
||||||
|
+ "manufacturerPnpId=GGL, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, connectionToSinkType=0}, "
|
||||||
|
+ "removeMode 0, refreshRateOverride 0.0, brightnessMinimum 0.0, brightnessMaximum 1.0, brightnessDefault 0.39763778}\n"
|
||||||
|
+ " mOverrideDisplayInfo=DisplayInfo{\"Built-in Screen\", displayId 0\", displayGroupId 0, "
|
||||||
|
+ "real 1080 x 2280, largest app 2148 x 2065, smallest app 1080 x 997, appVsyncOff "
|
||||||
|
+ "1000000, presDeadline 16666666, mode 1, defaultMode 1, modes [{id=1, width=1080, height=2280, fps=60.000004, "
|
||||||
|
+ "alternativeRefreshRates=[]}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[], mMaxLuminance=500.0, "
|
||||||
|
+ "mMaxAverageLuminance=500.0, mMinLuminance=0.0}, userDisabledHdrTypes [], minimalPostProcessingSupported false, rotation 0, state "
|
||||||
|
+ "ON, type INTERNAL, uniqueId \"local:0\", app 1080 x 2148, density 440 (440.0 x 440.0) dpi, layerStack 0, colorMode 0, "
|
||||||
|
+ "supportedColorModes [0], address {port=0, model=0}, deviceProductInfo DeviceProductInfo{name=EMU_display_0, "
|
||||||
|
+ "manufacturerPnpId=GGL, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, connectionToSinkType=0}, "
|
||||||
|
+ "removeMode 0, refreshRateOverride 0.0, brightnessMinimum 0.0, brightnessMaximum 1.0, brightnessDefault 0.39763778}\n"
|
||||||
|
+ " mRequestedMinimalPostProcessing=false\n"
|
||||||
|
+ " mFrameRateOverrides=[]\n"
|
||||||
|
+ " mPendingFrameRateOverrideUids={}\n";
|
||||||
|
DisplayInfo displayInfo = DisplayManager.parseDisplayInfo(partialOutput, 0);
|
||||||
|
Assert.assertNotNull(displayInfo);
|
||||||
|
Assert.assertEquals(0, displayInfo.getDisplayId());
|
||||||
|
Assert.assertEquals(0, displayInfo.getRotation());
|
||||||
|
Assert.assertEquals(0, displayInfo.getLayerStack());
|
||||||
|
Assert.assertEquals(0, displayInfo.getFlags());
|
||||||
|
Assert.assertEquals(1080, displayInfo.getSize().getWidth());
|
||||||
|
Assert.assertEquals(2280, displayInfo.getSize().getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user