Skip to content

Commit 858849d

Browse files
committed
feat(android): implement screenshot resizing and coordinate adjustment for AI processing
1 parent 6056004 commit 858849d

File tree

1 file changed

+52
-11
lines changed

1 file changed

+52
-11
lines changed

packages/android/src/device.ts

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,15 @@ export type AndroidDeviceOpt = {
6060
usePhysicalDisplayIdForScreenshot?: boolean;
6161
usePhysicalDisplayIdForDisplayLookup?: boolean;
6262
customActions?: DeviceAction<any>[];
63+
screenshotResizeScale?: number;
6364
} & AndroidDeviceInputOpt;
6465

6566
export class AndroidDevice implements AbstractInterface {
6667
private deviceId: string;
6768
private yadbPushed = false;
6869
private devicePixelRatio = 1;
6970
private devicePixelRatioInitialized = false;
71+
private scalingRatio = 1; // Record scaling ratio for coordinate adjustment
7072
private adb: ADB | null = null;
7173
private connectingAdb: Promise<ADB> | null = null;
7274
private destroyed = false;
@@ -713,12 +715,28 @@ ${Object.keys(size)
713715
const width = Number.parseInt(match[isLandscape ? 2 : 1], 10);
714716
const height = Number.parseInt(match[isLandscape ? 1 : 2], 10);
715717

716-
// Return physical pixels to match screenshot dimensions
717-
// This ensures AI coordinate conversion uses the same dimensions as the screenshot
718+
// Determine scaling: use screenshotResizeScale if provided, otherwise use 1/devicePixelRatio
719+
// Default is 1/dpr to scale down by device pixel ratio (e.g., dpr=3 -> scale=1/3)
720+
const scale =
721+
this.options?.screenshotResizeScale ?? 1 / this.devicePixelRatio;
722+
this.scalingRatio = scale;
723+
724+
// Apply scale to get logical dimensions for AI processing
725+
// adjustCoordinates() will convert back to physical pixels when needed for touch operations
726+
const logicalWidth = Math.round(width * scale);
727+
const logicalHeight = Math.round(height * scale);
728+
729+
return {
730+
width: logicalWidth,
731+
height: logicalHeight,
732+
};
733+
}
734+
735+
private adjustCoordinates(x: number, y: number): { x: number; y: number } {
736+
const scale = this.scalingRatio;
718737
return {
719-
width,
720-
height,
721-
dpr: this.devicePixelRatio,
738+
x: Math.round(x / scale),
739+
y: Math.round(y / scale),
722740
};
723741
}
724742

@@ -1170,17 +1188,20 @@ ${Object.keys(size)
11701188
async mouseClick(x: number, y: number): Promise<void> {
11711189
const adb = await this.getAdb();
11721190

1191+
// Use adjusted coordinates
1192+
const { x: adjustedX, y: adjustedY } = this.adjustCoordinates(x, y);
11731193
await adb.shell(
1174-
`input${this.getDisplayArg()} swipe ${x} ${y} ${x} ${y} 150`,
1194+
`input${this.getDisplayArg()} swipe ${adjustedX} ${adjustedY} ${adjustedX} ${adjustedY} 150`,
11751195
);
11761196
}
11771197

11781198
async mouseDoubleClick(x: number, y: number): Promise<void> {
11791199
const adb = await this.getAdb();
1200+
const { x: adjustedX, y: adjustedY } = this.adjustCoordinates(x, y);
11801201

11811202
// Use input tap for double-click as it generates proper touch events
11821203
// that Android can recognize as a double-click gesture
1183-
const tapCommand = `input${this.getDisplayArg()} tap ${x} ${y}`;
1204+
const tapCommand = `input${this.getDisplayArg()} tap ${adjustedX} ${adjustedY}`;
11841205
await adb.shell(tapCommand);
11851206
// Short delay between taps for double-click recognition
11861207
await sleep(50);
@@ -1200,11 +1221,15 @@ ${Object.keys(size)
12001221
): Promise<void> {
12011222
const adb = await this.getAdb();
12021223

1224+
// Use adjusted coordinates
1225+
const { x: fromX, y: fromY } = this.adjustCoordinates(from.x, from.y);
1226+
const { x: toX, y: toY } = this.adjustCoordinates(to.x, to.y);
1227+
12031228
// Ensure duration has a default value
12041229
const swipeDuration = duration ?? defaultNormalScrollDuration;
12051230

12061231
await adb.shell(
1207-
`input${this.getDisplayArg()} swipe ${from.x} ${from.y} ${to.x} ${to.y} ${swipeDuration}`,
1232+
`input${this.getDisplayArg()} swipe ${fromX} ${fromY} ${toX} ${toY} ${swipeDuration}`,
12081233
);
12091234
}
12101235

@@ -1244,12 +1269,22 @@ ${Object.keys(size)
12441269
const endX = startX - deltaX;
12451270
const endY = startY - deltaY;
12461271

1272+
// Adjust coordinates to fit device ratio
1273+
const { x: adjustedStartX, y: adjustedStartY } = this.adjustCoordinates(
1274+
startX,
1275+
startY,
1276+
);
1277+
const { x: adjustedEndX, y: adjustedEndY } = this.adjustCoordinates(
1278+
endX,
1279+
endY,
1280+
);
1281+
12471282
const adb = await this.getAdb();
12481283
const swipeDuration = duration ?? defaultNormalScrollDuration;
12491284

12501285
// Execute the swipe operation
12511286
await adb.shell(
1252-
`input${this.getDisplayArg()} swipe ${startX} ${startY} ${endX} ${endY} ${swipeDuration}`,
1287+
`input${this.getDisplayArg()} swipe ${adjustedStartX} ${adjustedStartY} ${adjustedEndX} ${adjustedEndY} ${swipeDuration}`,
12531288
);
12541289
}
12551290

@@ -1290,8 +1325,10 @@ ${Object.keys(size)
12901325
async longPress(x: number, y: number, duration = 1000): Promise<void> {
12911326
const adb = await this.getAdb();
12921327

1328+
// Use adjusted coordinates
1329+
const { x: adjustedX, y: adjustedY } = this.adjustCoordinates(x, y);
12931330
await adb.shell(
1294-
`input${this.getDisplayArg()} swipe ${x} ${y} ${x} ${y} ${duration}`,
1331+
`input${this.getDisplayArg()} swipe ${adjustedX} ${adjustedY} ${adjustedX} ${adjustedY} ${duration}`,
12951332
);
12961333
}
12971334

@@ -1323,9 +1360,13 @@ ${Object.keys(size)
13231360
): Promise<void> {
13241361
const adb = await this.getAdb();
13251362

1363+
// Use adjusted coordinates
1364+
const { x: fromX, y: fromY } = this.adjustCoordinates(from.x, from.y);
1365+
const { x: toX, y: toY } = this.adjustCoordinates(to.x, to.y);
1366+
13261367
// Use the specified duration for better pull gesture recognition
13271368
await adb.shell(
1328-
`input${this.getDisplayArg()} swipe ${from.x} ${from.y} ${to.x} ${to.y} ${duration}`,
1369+
`input${this.getDisplayArg()} swipe ${fromX} ${fromY} ${toX} ${toY} ${duration}`,
13291370
);
13301371
}
13311372

0 commit comments

Comments
 (0)