Compare commits

..

9 Commits

Author SHA1 Message Date
Romain Vimont
fde0aaaa48 clean up
TODO: adb uninstall sometimes hang
2022-09-25 15:48:23 +02:00
Romain Vimont
9e8eaed31b Add option --reinstall
With --install, the server is installed only if the current version is
not already installed. Passing --reinstall force reinstallation is all
cases.
2022-09-25 15:42:36 +02:00
Romain Vimont
75e2b1e930 Add option --install
When this flag is set, the scrcpy is installed rather than pushed to
/data/local/tmp.
2022-09-25 15:42:36 +02:00
Romain Vimont
0fe74f8e96 Add "adb uninstall"
This will allow to uninstall the server when necessary.
2022-09-25 15:42:36 +02:00
Romain Vimont
be70f0218d Add util function to get the APK version
Use "dumpsys package com.genymobile.scrcpy" to get the APK version.
2022-09-25 15:42:36 +02:00
Romain Vimont
91dee4f245 Add util function to get the APK path
Use "pm list package -f" to find where the APK is actually installed on
the device.
2022-09-25 15:42:36 +02:00
Romain Vimont
caf9035e0d Make build_without_gradle generate a signed APK 2022-09-25 15:42:36 +02:00
Romain Vimont
e4acae7578 Sign APK with credentials from keystore.properties 2022-09-25 15:42:36 +02:00
Romain Vimont
3dfd1ed8af Rename server to scrcpy-server.apk
This will allow to install it.
2022-09-25 15:42:36 +02:00
8 changed files with 2 additions and 331 deletions

View File

@@ -37,7 +37,7 @@ static const char *const android_motionevent_action_labels[] = {
"move",
"cancel",
"outside",
"pointer-down",
"ponter-down",
"pointer-up",
"hover-move",
"scroll",

View File

@@ -30,14 +30,4 @@ public final class Command {
}
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;
}
}

View File

@@ -7,7 +7,6 @@ import com.genymobile.scrcpy.wrappers.SurfaceControl;
import com.genymobile.scrcpy.wrappers.WindowManager;
import android.content.IOnPrimaryClipChangedListener;
import android.content.pm.ApplicationInfo;
import android.graphics.Rect;
import android.os.Build;
import android.os.IBinder;
@@ -22,8 +21,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
public final class Device {
private static final String SCRCPY_PACKAGE_NAME = "com.genymobile.scrcpy";
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
public static final int POWER_MODE_NORMAL = SurfaceControl.POWER_MODE_NORMAL;
@@ -322,12 +319,4 @@ public final class Device {
public static Settings getSettings() {
return SETTINGS;
}
public static String getApkPath() {
ApplicationInfo info = SERVICE_MANAGER.getPackageManager().getApplicationInfo(SCRCPY_PACKAGE_NAME);
if (info == null) {
return null;
}
return info.sourceDir;
}
}

View File

@@ -6,9 +6,7 @@ import android.system.OsConstants;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Scanner;
public final class IO {
private IO() {
@@ -39,13 +37,4 @@ public final class IO {
public static void writeFully(FileDescriptor fd, byte[] buffer, int offset, int len) throws IOException {
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();
}
}

View File

@@ -1,16 +1,8 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Command;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.Ln;
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 {
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
@@ -18,61 +10,11 @@ public final class DisplayManager {
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) {
try {
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, displayId);
if (displayInfo == null) {
// fallback when displayInfo is null
return getDisplayInfoFromDumpsysDisplay(displayId);
return null;
}
Class<?> cls = displayInfo.getClass();
// width and height already take the rotation into account

View File

@@ -1,36 +0,0 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Ln;
import android.content.pm.ApplicationInfo;
import android.os.IInterface;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PackageManager {
private IInterface manager;
private Method getApplicationInfoMethod;
public PackageManager(IInterface manager) {
this.manager = manager;
}
private Method getGetApplicationInfoMethod() throws NoSuchMethodException {
if (getApplicationInfoMethod == null) {
getApplicationInfoMethod = manager.getClass().getDeclaredMethod("getApplicationInfo", String.class, int.class, int.class);
}
return getApplicationInfoMethod;
}
public ApplicationInfo getApplicationInfo(String packageName) {
try {
Method method = getGetApplicationInfoMethod();
return (ApplicationInfo) method.invoke(manager, packageName, 0, ServiceManager.USER_ID);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
Ln.e("Cannot get application info", e);
return null;
}
}
}

View File

@@ -22,7 +22,6 @@ public final class ServiceManager {
private StatusBarManager statusBarManager;
private ClipboardManager clipboardManager;
private ActivityManager activityManager;
private PackageManager packageManager;
public ServiceManager() {
try {
@@ -120,20 +119,4 @@ public final class ServiceManager {
return activityManager;
}
public PackageManager getPackageManager() {
if (packageManager == null) {
try {
//IInterface manager = getService("package", "android.content.pm.IPackageManager");
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method getPackageManager = activityThreadClass.getDeclaredMethod("getPackageManager");
IInterface manager = (IInterface) getPackageManager.invoke(null);
return new PackageManager(manager);
} catch (Exception e) {
throw new AssertionError(e);
}
}
return packageManager;
}
}

View File

@@ -1,186 +0,0 @@
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());
}
}