Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions app/src/main/runtime/display/XServerDisplayActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -1075,11 +1075,17 @@ public void handleOnBackPressed() {
GuestProgramLauncherComponent.ensureImageFsNativeLibrary(this, imageFs, "libfakeinput.so");
GuestProgramLauncherComponent.ensureImageFsNativeLibrary(this, imageFs, "libandroid-sysvshm.so");
File devInputDir = new File(imageFs.getRootDir(), "dev/input");
boolean reattachingLiveSession = SessionKeepAliveService.isSessionActive()
&& SessionKeepAliveService.getActiveEnvironment() != null
&& SessionKeepAliveService.getActiveXServer() != null;
if (devInputDir.exists() || devInputDir.mkdirs()) {
for (int i = 0; i < 4; i++) {
File eventFile = new File(devInputDir, "event" + i);
if (eventFile.exists()) {
eventFile.delete();
// On reattach the running guest still holds these nodes; deleting them breaks its live input mapping.
if (!reattachingLiveSession) {
for (int i = 0; i < 4; i++) {
File eventFile = new File(devInputDir, "event" + i);
if (eventFile.exists()) {
eventFile.delete();
}
}
}
}
Expand Down Expand Up @@ -6420,8 +6426,14 @@ private void setupXEnvironment() throws PackageManager.NameNotFoundException {
this.environment.setContext(this);
this.reusingSession = true;

// Free the old handler's socket (keep its writers/rings) and mark the fresh one initialized so the guest's input keeps flowing.
WinHandler previousWinHandler = this.xServer.getWinHandler();
if (previousWinHandler != null && previousWinHandler != winHandler) {
previousWinHandler.stopForReattach();
}
this.xServer.setWinHandler(winHandler);

winHandler.markSessionInitialized();

this.guestProgramLauncherComponent = environment.getComponent(GuestProgramLauncherComponent.class);
return;
}
Expand Down
51 changes: 42 additions & 9 deletions app/src/main/runtime/display/winhandler/WinHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -547,18 +547,51 @@ public void stop() {
if (this.vibrationExecutor != null) this.vibrationExecutor.shutdownNow();
}

// Hand the socket/threads to a replacement handler while keeping the fake-input writers/rings the running guest is mapped to (unlike stop()).
public void stopForReattach() {
synchronized (this.actions) {
this.running = false;
this.actions.clear();
this.actions.notifyAll();
}
this.vibrationRunning = false;
if (this.socket != null) {
this.socket.close();
this.socket = null;
}
if (this.vibrationServer != null) {
try {
this.vibrationServer.close();
} catch (IOException ignored) {
}
this.vibrationServer = null;
}
if (this.sendExecutor != null) this.sendExecutor.shutdownNow();
if (this.receiveExecutor != null) this.receiveExecutor.shutdownNow();
if (this.vibrationExecutor != null) this.vibrationExecutor.shutdownNow();
}

private void applyInitHandshake() {
this.initReceived = true;
this.preferences =
PreferenceManager.getDefaultSharedPreferences(this.activity.getBaseContext());
if (!this.xinputDisabledInitialized) {
this.xinputDisabled = this.preferences.getBoolean("xinput_toggle", false);
}
synchronized (this.actions) {
this.actions.notifyAll();
}
}

// Reused session: the guest already handshook and won't repeat it, so adopt init state or mouse/keyboard input stays gated off.
public void markSessionInitialized() {
applyInitHandshake();
}

private void handleRequest(byte requestCode, int port) {
switch (requestCode) {
case 1:
this.initReceived = true;
this.preferences =
PreferenceManager.getDefaultSharedPreferences(this.activity.getBaseContext());
if (!this.xinputDisabledInitialized) {
this.xinputDisabled = this.preferences.getBoolean("xinput_toggle", false);
}
synchronized (this.actions) {
this.actions.notifyAll();
}
applyInitHandshake();
return;
case 5:
if (this.onGetProcessInfoListener != null) {
Expand Down