simulate screen dragging

Summary: Ref T2890

Reviewers: #reviewers

Subscribers: kuba-orlik

Maniphest Tasks: T2890

Differential Revision: https://hub.sealcode.org/D1410
This commit is contained in:
Kuba Orlik 2025-01-18 16:43:36 +01:00
parent 2e0ea198f1
commit 0a6e04c5ba
4 changed files with 279 additions and 219 deletions

View File

@ -23,22 +23,27 @@ server.on("connection", (socket) => {
socket.write(fs.readFileSync("/screenshot.png")); socket.write(fs.readFileSync("/screenshot.png"));
socket.write("ENDOFMSG"); socket.write("ENDOFMSG");
} else if (data.includes("touch")) { } else if (data.includes("touch")) {
dataSplit = data.split(" "); const dataSplit = data.split(" ");
await spawnPromise("bash", [ await spawnPromise("bash", [
"/conf/touch.sh", "/conf/touch.sh",
dataSplit[1], dataSplit[1],
dataSplit[2], dataSplit[2],
]); ]);
} else if (data === "back") { } else if (data === "back") {
await spawnPromise("bash", [ await spawnPromise("bash", ["/conf/back.sh"]);
"/conf/back.sh",
]);
} else if (data === "home") { } else if (data === "home") {
await spawnPromise("bash", ["/conf/home.sh"]);
} else if (data.includes("drag")) {
const dataSplit = data.split(" ");
await spawnPromise("bash", [ await spawnPromise("bash", [
"/conf/home.sh", "/conf/drag.sh",
dataSplit[1],
dataSplit[2],
dataSplit[3],
dataSplit[4],
]); ]);
} }
}); });
socket.on("close", (_) => { socket.on("close", (_) => {
socket.end(); socket.end();

1
android/conf/drag.sh Normal file
View File

@ -0,0 +1 @@
/opt/android-sdk-linux/platform-tools/adb shell input swipe $1 $2 $3 $4 1000

View File

@ -4,31 +4,32 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Rentgen android</title> <title>Rentgen android</title>
<style> <style>
main{ main {
display: flex; display: flex;
} }
.log-section{ .log-section {
height: 600px; height: 600px;
width: 300px; width: 480px;
overflow-y: auto; overflow-y: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-left: 20px; margin-left: 20px;
} }
.screen{ .screen {
display: inline-block display: inline-block;
cursor: pointer;
} }
.screen-buttons{ .screen-buttons {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
margin-top: 5px; margin-top: 5px;
gap: 10px; gap: 10px;
} }
.screen-buttons button{ .screen-buttons button {
font-size: 1.1rem; font-size: 1.1rem;
padding: 10px 20px; padding: 10px 20px;
width: 100%; width: 100%;
@ -36,28 +37,33 @@
background-color: transparent; background-color: transparent;
} }
.screen-buttons button:hover{ .screen-buttons button:hover {
background-color: aqua; background-color: aqua;
} }
#clicks-log {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,
monospace;
}
</style> </style>
</head> </head>
<body> <body>
<main> <main>
<section class="screen-section"> <section class="screen-section">
<img id="screen" alt="android screen" src="" class="screen"/> <img
id="screen"
alt="android screen"
src=""
draggable="false"
class="screen"
/>
<div class="screen-buttons"> <div class="screen-buttons">
<button class="screen-buttons-home">home</button> <button class="screen-buttons-home">home</button>
<button class="screen-buttons-back">back</button> <button class="screen-buttons-back">back</button>
</div> </div>
</section> </section>
<p <p id="clicks-log" class="log-section"></p>
id="clicks-log" <p id="traffic-log" class="log-section"></p>
class="log-section"
></p>
<p
id="traffic-log"
class="log-section"
></p>
</main> </main>
<script> <script>
var screen = document.getElementById("screen"); var screen = document.getElementById("screen");
@ -78,13 +84,15 @@
const waitToLog = (clickInfoText) => { const waitToLog = (clickInfoText) => {
const clickInfo = document.createElement("span"); const clickInfo = document.createElement("span");
const waitInfo = document.createElement("span"); const waitInfo = document.createElement("span");
waitInfo.textContent = `await wait(${calculateElapsedTime(lastTouch)});` waitInfo.textContent = `await wait(${calculateElapsedTime(
lastTouch
)});`;
clicksLog.appendChild(waitInfo); clicksLog.appendChild(waitInfo);
clickInfo.textContent = clickInfoText; clickInfo.textContent = clickInfoText;
clicksLog.appendChild(clickInfo); clicksLog.appendChild(clickInfo);
} };
const registerClick = ({path, logText}) =>{ const registerClick = ({ path, logText, body }) => {
const clicksLog = document.getElementById("clicks-log"); const clicksLog = document.getElementById("clicks-log");
const span = document.createElement("span"); const span = document.createElement("span");
@ -95,12 +103,17 @@
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
}, },
...(body ? { body } : {}),
}); });
} };
homeButton.addEventListener("click", () => registerClick({path: "home", logText: "await homeButton();"})); homeButton.addEventListener("click", () =>
registerClick({ path: "home", logText: "await homeButton();" })
);
backButton.addEventListener("click", () => registerClick({path: "back", logText: "await backButton();"})); backButton.addEventListener("click", () =>
registerClick({ path: "back", logText: "await backButton();" })
);
async function displayImage() { async function displayImage() {
try { try {
@ -112,20 +125,44 @@
} }
} }
async function handleTouchEvent(event) { let isDragging = false;
let startDraggingPosX = 0;
let endDraggingPosX = 0;
let startDraggingPosY = 0;
let endDraggingPosY = 0;
const handleDraggStart = (e) => {
e.preventDefault();
isDragging = true;
startDraggingPosX = e.offsetX;
startDraggingPosY = e.offsetY;
};
screen.addEventListener("mousedown", handleDraggStart);
document.addEventListener("mouseup", (e) => {
endDraggingPosX = e.offsetX;
endDraggingPosY = e.offsetY;
if (
(isDragging && Math.abs(endDraggingPosY - startDraggingPosY) > 10) ||
Math.abs(endDraggingPosX - startDraggingPosX) > 10
) {
registerClick({
path: "drag",
logText: `await drag({x:${startDraggingPosX},y:${startDraggingPosY}},{x:${e.offsetX},y:${e.offsetY}});`,
body: `startX=${startDraggingPosX}&startY=${startDraggingPosY}&endX=${e.offsetX}&endY=${e.offsetY}`,
});
isDragging = false;
} else {
const phoneX = event.offsetX; const phoneX = event.offsetX;
const phoneY = event.offsetY; const phoneY = event.offsetY;
registerClick({
waitToLog(`await click(${phoneX}, ${phoneY});`); path: "touch",
logText: `await click(${phoneX}, ${phoneY});`,
await fetch("touch", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `x=${phoneX}&y=${phoneY}`, body: `x=${phoneX}&y=${phoneY}`,
}); });
} }
});
async function sleep(time) { async function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time)); return new Promise((resolve) => setTimeout(resolve, time));
@ -142,8 +179,6 @@
} }
} }
screen.addEventListener("click", handleTouchEvent);
screenshot_loop(); screenshot_loop();
</script> </script>
<script src="/trafficLog.js"></script> <script src="/trafficLog.js"></script>

View File

@ -18,14 +18,23 @@ let doneWrite = 0;
let screenshotPromise = null; let screenshotPromise = null;
async function screenshot() { async function screenshot() {
const time_start = Date.now();
socket_client.write("screenshot"); socket_client.write("screenshot");
while (!doneWrite) await sleep(15); while (!doneWrite) {
await sleep(15);
if (Date.now() - time_start > 2000) {
console.error("Screenshot timed out after 2s");
break; // timeout
}
}
doneWrite = 0; doneWrite = 0;
screenshotPromise = null; screenshotPromise = null;
} }
async function guardedScreenshot() { async function guardedScreenshot() {
console.log("Requesting a screenshot");
if (!screenshotPromise) { if (!screenshotPromise) {
console.log("no ongoing promise, starting a new one");
screenshotPromise = screenshot(); screenshotPromise = screenshot();
} }
return screenshotPromise; return screenshotPromise;
@ -121,4 +130,14 @@ app.post("/home", function (req, res) {
res.sendStatus(200); res.sendStatus(200);
}); });
app.post("/drag", function (req, res) {
const body = req.body;
const startX = Number(body.startX);
const startY = Number(body.startY);
const endX = Number(body.endX);
const endY = Number(body.endY);
socket_client.write(`drag ${startX} ${startY} ${endX} ${endY}`);
res.sendStatus(200);
});
app.listen(8080, () => console.log("Listening in port 8080")); app.listen(8080, () => console.log("Listening in port 8080"));