-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
it doesn't work because now i'm sending stay awake that does work onl…
…y with usb plugged in
- Loading branch information
Showing
12 changed files
with
1,100 additions
and
2 deletions.
There are no files selected for viewing
Binary file not shown.
150 changes: 150 additions & 0 deletions
150
server/src/main/java/org/cagnulein/android_remote/CleanUp.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package org.cagnulein.android_remote; | ||
|
||
import android.util.Log; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
|
||
/** | ||
* Handle the cleanup of scrcpy, even if the main process is killed. | ||
* <p> | ||
* This is useful to restore some state when scrcpy is closed, even on device disconnection (which kills the scrcpy process). | ||
*/ | ||
public final class CleanUp { | ||
|
||
private static final int MSG_TYPE_MASK = 0b11; | ||
private static final int MSG_TYPE_RESTORE_STAY_ON = 0; | ||
private static final int MSG_TYPE_DISABLE_SHOW_TOUCHES = 1; | ||
private static final int MSG_TYPE_RESTORE_NORMAL_POWER_MODE = 2; | ||
private static final int MSG_TYPE_POWER_OFF_SCREEN = 3; | ||
|
||
private static final int MSG_PARAM_SHIFT = 2; | ||
|
||
private final OutputStream out; | ||
|
||
public CleanUp(OutputStream out) { | ||
this.out = out; | ||
} | ||
|
||
public static CleanUp configure(int displayId) throws IOException { | ||
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(displayId)}; | ||
|
||
ProcessBuilder builder = new ProcessBuilder(cmd); | ||
builder.environment().put("CLASSPATH", Server.SERVER_PATH); | ||
Process process = builder.start(); | ||
return new CleanUp(process.getOutputStream()); | ||
} | ||
|
||
private boolean sendMessage(int type, int param) { | ||
assert (type & ~MSG_TYPE_MASK) == 0; | ||
int msg = type | param << MSG_PARAM_SHIFT; | ||
try { | ||
out.write(msg); | ||
out.flush(); | ||
return true; | ||
} catch (IOException e) { | ||
Log.w("Cleanup", "Could not configure cleanup (type=" + type + ", param=" + param + ")", e); | ||
return false; | ||
} | ||
} | ||
|
||
public boolean setRestoreStayOn(int restoreValue) { | ||
// Restore the value (between 0 and 7), -1 to not restore | ||
// <https://developer.android.com/reference/android/provider/Settings.Global#STAY_ON_WHILE_PLUGGED_IN> | ||
assert restoreValue >= -1 && restoreValue <= 7; | ||
return sendMessage(MSG_TYPE_RESTORE_STAY_ON, restoreValue & 0b1111); | ||
} | ||
|
||
public boolean setDisableShowTouches(boolean disableOnExit) { | ||
return sendMessage(MSG_TYPE_DISABLE_SHOW_TOUCHES, disableOnExit ? 1 : 0); | ||
} | ||
|
||
public boolean setRestoreNormalPowerMode(boolean restoreOnExit) { | ||
return sendMessage(MSG_TYPE_RESTORE_NORMAL_POWER_MODE, restoreOnExit ? 1 : 0); | ||
} | ||
|
||
public boolean setPowerOffScreen(boolean powerOffScreenOnExit) { | ||
return sendMessage(MSG_TYPE_POWER_OFF_SCREEN, powerOffScreenOnExit ? 1 : 0); | ||
} | ||
|
||
public static void unlinkSelf() { | ||
try { | ||
new File(Server.SERVER_PATH).delete(); | ||
} catch (Exception e) { | ||
Ln.e("Could not unlink server", e); | ||
} | ||
} | ||
|
||
public static void main(String... args) { | ||
unlinkSelf(); | ||
|
||
int displayId = Integer.parseInt(args[0]); | ||
|
||
int restoreStayOn = -1; | ||
boolean disableShowTouches = false; | ||
boolean restoreNormalPowerMode = false; | ||
boolean powerOffScreen = false; | ||
|
||
try { | ||
// Wait for the server to die | ||
int msg; | ||
while ((msg = System.in.read()) != -1) { | ||
int type = msg & MSG_TYPE_MASK; | ||
int param = msg >> MSG_PARAM_SHIFT; | ||
switch (type) { | ||
case MSG_TYPE_RESTORE_STAY_ON: | ||
restoreStayOn = param > 7 ? -1 : param; | ||
break; | ||
case MSG_TYPE_DISABLE_SHOW_TOUCHES: | ||
disableShowTouches = param != 0; | ||
break; | ||
case MSG_TYPE_RESTORE_NORMAL_POWER_MODE: | ||
restoreNormalPowerMode = param != 0; | ||
break; | ||
case MSG_TYPE_POWER_OFF_SCREEN: | ||
powerOffScreen = param != 0; | ||
break; | ||
default: | ||
Ln.w("Unexpected msg type: " + type); | ||
break; | ||
} | ||
} | ||
} catch (IOException e) { | ||
// Expected when the server is dead | ||
} | ||
|
||
Ln.i("Cleaning up"); | ||
|
||
if (disableShowTouches) { | ||
Ln.i("Disabling \"show touches\""); | ||
try { | ||
Settings.putValue(Settings.TABLE_SYSTEM, "show_touches", "0"); | ||
} catch (SettingsException e) { | ||
Ln.e("Could not restore \"show_touches\"", e); | ||
} | ||
} | ||
|
||
if (restoreStayOn != -1) { | ||
Ln.i("Restoring \"stay awake\""); | ||
try { | ||
Settings.putValue(Settings.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(restoreStayOn)); | ||
} catch (SettingsException e) { | ||
Ln.e("Could not restore \"stay_on_while_plugged_in\"", e); | ||
} | ||
} | ||
|
||
/* VIOLA | ||
if (Device.isScreenOn()) { | ||
if (powerOffScreen) { | ||
Ln.i("Power off screen"); | ||
Device.powerOffScreen(displayId); | ||
} else if (restoreNormalPowerMode) { | ||
Ln.i("Restoring normal power mode"); | ||
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL); | ||
} | ||
}*/ | ||
|
||
System.exit(0); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
server/src/main/java/org/cagnulein/android_remote/Command.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package org.cagnulein.android_remote; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Scanner; | ||
|
||
public final class Command { | ||
private Command() { | ||
// not instantiable | ||
} | ||
|
||
public static void exec(String... cmd) throws IOException, InterruptedException { | ||
Process process = Runtime.getRuntime().exec(cmd); | ||
int exitCode = process.waitFor(); | ||
if (exitCode != 0) { | ||
throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode); | ||
} | ||
} | ||
|
||
public static String execReadLine(String... cmd) throws IOException, InterruptedException { | ||
String result = null; | ||
Process process = Runtime.getRuntime().exec(cmd); | ||
Scanner scanner = new Scanner(process.getInputStream()); | ||
if (scanner.hasNextLine()) { | ||
result = scanner.nextLine(); | ||
} | ||
int exitCode = process.waitFor(); | ||
if (exitCode != 0) { | ||
throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode); | ||
} | ||
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; | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
server/src/main/java/org/cagnulein/android_remote/FakeContext.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package org.cagnulein.android_remote; | ||
|
||
import android.annotation.TargetApi; | ||
import android.content.AttributionSource; | ||
import android.content.Context; | ||
import android.content.ContextWrapper; | ||
import android.os.Build; | ||
import android.os.Process; | ||
|
||
public final class FakeContext extends ContextWrapper { | ||
|
||
public static final String PACKAGE_NAME = "com.android.shell"; | ||
public static final int ROOT_UID = 0; // Like android.os.Process.ROOT_UID, but before API 29 | ||
|
||
private static final FakeContext INSTANCE = new FakeContext(); | ||
|
||
public static FakeContext get() { | ||
return INSTANCE; | ||
} | ||
|
||
private FakeContext() { | ||
super(Workarounds.getSystemContext()); | ||
} | ||
|
||
@Override | ||
public String getPackageName() { | ||
return PACKAGE_NAME; | ||
} | ||
|
||
@Override | ||
public String getOpPackageName() { | ||
return PACKAGE_NAME; | ||
} | ||
|
||
@TargetApi(Build.VERSION_CODES.S) | ||
@Override | ||
public AttributionSource getAttributionSource() { | ||
AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID); | ||
builder.setPackageName(PACKAGE_NAME); | ||
return builder.build(); | ||
} | ||
|
||
// @Override to be added on SDK upgrade for Android 14 | ||
@SuppressWarnings("unused") | ||
public int getDeviceId() { | ||
return 0; | ||
} | ||
|
||
@Override | ||
public Context getApplicationContext() { | ||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package org.cagnulein.android_remote; | ||
|
||
import android.system.ErrnoException; | ||
import android.system.Os; | ||
import android.system.OsConstants; | ||
|
||
import com.genymobile.scrcpy.BuildConfig; | ||
|
||
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() { | ||
// not instantiable | ||
} | ||
|
||
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. | ||
// See <https://github.com/Genymobile/scrcpy/issues/291>. | ||
int remaining = from.remaining(); | ||
while (remaining > 0) { | ||
try { | ||
int w = Os.write(fd, from); | ||
if (BuildConfig.DEBUG && w < 0) { | ||
// w should not be negative, since an exception is thrown on error | ||
throw new AssertionError("Os.write() returned a negative value (" + w + ")"); | ||
} | ||
remaining -= w; | ||
} catch (ErrnoException e) { | ||
if (e.errno != OsConstants.EINTR) { | ||
throw new IOException(e); | ||
} | ||
} | ||
} | ||
} | ||
|
||
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(); | ||
} | ||
|
||
public static boolean isBrokenPipe(IOException e) { | ||
Throwable cause = e.getCause(); | ||
return cause instanceof ErrnoException && ((ErrnoException) cause).errno == OsConstants.EPIPE; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
server/src/main/java/org/cagnulein/android_remote/Server.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.