scan media

This commit is contained in:
Romain Vimont 2021-06-13 11:36:31 +02:00
commit 64ea0d1a4a
7 changed files with 87 additions and 0 deletions

View file

@ -80,6 +80,13 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE: case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
buf[1] = msg->set_screen_power_mode.mode; buf[1] = msg->set_screen_power_mode.mode;
return 2; return 2;
case CONTROL_MSG_TYPE_SCAN_MEDIA:
{
size_t len = write_string(msg->scan_media.path,
CONTROL_MSG_SCAN_MEDIA_PATH_MAX_LENGTH,
&buf[1]);
return 1 + len;
}
case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL: case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL: case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL:
case CONTROL_MSG_TYPE_COLLAPSE_PANELS: case CONTROL_MSG_TYPE_COLLAPSE_PANELS:
@ -102,6 +109,9 @@ control_msg_destroy(struct control_msg *msg) {
case CONTROL_MSG_TYPE_SET_CLIPBOARD: case CONTROL_MSG_TYPE_SET_CLIPBOARD:
free(msg->set_clipboard.text); free(msg->set_clipboard.text);
break; break;
case CONTROL_MSG_TYPE_SCAN_MEDIA:
free(msg->scan_media.path);
break;
default: default:
// do nothing // do nothing
break; break;

View file

@ -17,6 +17,8 @@
// type: 1 byte; paste flag: 1 byte; length: 4 bytes // type: 1 byte; paste flag: 1 byte; length: 4 bytes
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6) #define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)
#define CONTROL_MSG_SCAN_MEDIA_PATH_MAX_LENGTH 256
#define POINTER_ID_MOUSE UINT64_C(-1); #define POINTER_ID_MOUSE UINT64_C(-1);
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2); #define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2);
@ -33,6 +35,7 @@ enum control_msg_type {
CONTROL_MSG_TYPE_SET_CLIPBOARD, CONTROL_MSG_TYPE_SET_CLIPBOARD,
CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE, CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
CONTROL_MSG_TYPE_ROTATE_DEVICE, CONTROL_MSG_TYPE_ROTATE_DEVICE,
CONTROL_MSG_TYPE_SCAN_MEDIA,
}; };
enum screen_power_mode { enum screen_power_mode {
@ -76,6 +79,9 @@ struct control_msg {
struct { struct {
enum screen_power_mode mode; enum screen_power_mode mode;
} set_screen_power_mode; } set_screen_power_mode;
struct {
char *path; // owned, to be freed by free()
} scan_media;
}; };
}; };

View file

@ -278,6 +278,28 @@ static void test_serialize_rotate_device(void) {
assert(!memcmp(buf, expected, sizeof(expected))); assert(!memcmp(buf, expected, sizeof(expected)));
} }
static void test_serialize_scan_media(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_SCAN_MEDIA,
.scan_media = {
.path = "/sdcard/Download/",
},
};
unsigned char buf[CONTROL_MSG_MAX_SIZE];
size_t size = control_msg_serialize(&msg, buf);
assert(size == 22);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_SCAN_MEDIA,
0x00, 0x00, 0x00, 0x11, // path length
'/', 's', 'd', 'c', 'a', 'r', 'd', '/',
'D', 'o', 'w', 'n', 'l', 'o', 'a', 'd',
'/' // path
};
assert(!memcmp(buf, expected, sizeof(expected)));
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
(void) argc; (void) argc;
(void) argv; (void) argv;
@ -295,5 +317,6 @@ int main(int argc, char *argv[]) {
test_serialize_set_clipboard(); test_serialize_set_clipboard();
test_serialize_set_screen_power_mode(); test_serialize_set_screen_power_mode();
test_serialize_rotate_device(); test_serialize_rotate_device();
test_serialize_scan_media();
return 0; return 0;
} }

View file

@ -17,6 +17,7 @@ public final class ControlMessage {
public static final int TYPE_SET_CLIPBOARD = 9; public static final int TYPE_SET_CLIPBOARD = 9;
public static final int TYPE_SET_SCREEN_POWER_MODE = 10; public static final int TYPE_SET_SCREEN_POWER_MODE = 10;
public static final int TYPE_ROTATE_DEVICE = 11; public static final int TYPE_ROTATE_DEVICE = 11;
public static final int TYPE_SCAN_MEDIA = 12;
private int type; private int type;
private String text; private String text;
@ -97,6 +98,13 @@ public final class ControlMessage {
return msg; return msg;
} }
public static ControlMessage createScanMedia(String path) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_SCAN_MEDIA;
msg.text = path;
return msg;
}
public static ControlMessage createEmpty(int type) { public static ControlMessage createEmpty(int type) {
ControlMessage msg = new ControlMessage(); ControlMessage msg = new ControlMessage();
msg.type = type; msg.type = type;

View file

@ -76,6 +76,9 @@ public class ControlMessageReader {
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE: case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
msg = parseSetScreenPowerMode(); msg = parseSetScreenPowerMode();
break; break;
case ControlMessage.TYPE_SCAN_MEDIA:
msg = parseScanMedia();
break;
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL: case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL:
case ControlMessage.TYPE_COLLAPSE_PANELS: case ControlMessage.TYPE_COLLAPSE_PANELS:
@ -182,6 +185,14 @@ public class ControlMessageReader {
return ControlMessage.createSetScreenPowerMode(mode); return ControlMessage.createSetScreenPowerMode(mode);
} }
private ControlMessage parseScanMedia() {
String path = parseString();
if (path == null) {
return null;
}
return ControlMessage.createScanMedia(path);
}
private static Position readPosition(ByteBuffer buffer) { private static Position readPosition(ByteBuffer buffer) {
int x = buffer.getInt(); int x = buffer.getInt();
int y = buffer.getInt(); int y = buffer.getInt();

View file

@ -1,5 +1,7 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
import android.content.Intent;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.InputDevice; import android.view.InputDevice;
@ -7,6 +9,7 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -135,6 +138,12 @@ public class Controller {
case ControlMessage.TYPE_ROTATE_DEVICE: case ControlMessage.TYPE_ROTATE_DEVICE:
Device.rotateDevice(); Device.rotateDevice();
break; break;
case ControlMessage.TYPE_SCAN_MEDIA:
String path = msg.getText();
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(new File(path)));
Device.sendBroadcast(intent);
break;
default: default:
// do nothing // do nothing
} }

View file

@ -314,6 +314,26 @@ public class ControlMessageReaderTest {
Assert.assertEquals(ControlMessage.TYPE_ROTATE_DEVICE, event.getType()); Assert.assertEquals(ControlMessage.TYPE_ROTATE_DEVICE, event.getType());
} }
@Test
public void testScanMedia() throws IOException {
ControlMessageReader reader = new ControlMessageReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_SCAN_MEDIA);
byte[] text = "/sdcard/Download/".getBytes(StandardCharsets.UTF_8);
dos.writeInt(text.length);
dos.write(text);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlMessage event = reader.next();
Assert.assertEquals(ControlMessage.TYPE_SCAN_MEDIA, event.getType());
Assert.assertEquals("/sdcard/Download/", event.getText());
}
@Test @Test
public void testMultiEvents() throws IOException { public void testMultiEvents() throws IOException {
ControlMessageReader reader = new ControlMessageReader(); ControlMessageReader reader = new ControlMessageReader();