diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 7d18fb6a..8908c546 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -81,6 +81,7 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) { buf[1] = msg->set_screen_power_mode.mode; return 2; case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL: + case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL: case CONTROL_MSG_TYPE_COLLAPSE_PANELS: case CONTROL_MSG_TYPE_GET_CLIPBOARD: case CONTROL_MSG_TYPE_ROTATE_DEVICE: diff --git a/app/src/control_msg.h b/app/src/control_msg.h index 1e9481d9..c1099c79 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -27,6 +27,7 @@ enum control_msg_type { CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT, CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON, CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL, + CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, CONTROL_MSG_TYPE_COLLAPSE_PANELS, CONTROL_MSG_TYPE_GET_CLIPBOARD, CONTROL_MSG_TYPE_SET_CLIPBOARD, diff --git a/app/src/input_manager.c b/app/src/input_manager.c index b6006285..0d3175e6 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -182,6 +182,16 @@ expand_notification_panel(struct controller *controller) { } } +static void +expand_settings_panel(struct controller *controller) { + struct control_msg msg; + msg.type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL; + + if (!controller_push_msg(controller, &msg)) { + LOGW("Could not request 'expand settings panel'"); + } +} + static void collapse_panels(struct controller *controller) { struct control_msg msg; diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index d7b89929..ef9247ca 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -177,6 +177,21 @@ static void test_serialize_expand_notification_panel(void) { assert(!memcmp(buf, expected, sizeof(expected))); } +static void test_serialize_expand_settings_panel(void) { + struct control_msg msg = { + .type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, + }; + + unsigned char buf[CONTROL_MSG_MAX_SIZE]; + size_t size = control_msg_serialize(&msg, buf); + assert(size == 1); + + const unsigned char expected[] = { + CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL, + }; + assert(!memcmp(buf, expected, sizeof(expected))); +} + static void test_serialize_collapse_panels(void) { struct control_msg msg = { .type = CONTROL_MSG_TYPE_COLLAPSE_PANELS, @@ -274,6 +289,7 @@ int main(int argc, char *argv[]) { test_serialize_inject_scroll_event(); test_serialize_back_or_screen_on(); test_serialize_expand_notification_panel(); + test_serialize_expand_settings_panel(); test_serialize_collapse_panels(); test_serialize_get_clipboard(); test_serialize_set_clipboard(); diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java index 34ce1941..f8edd53c 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessage.java @@ -11,11 +11,12 @@ public final class ControlMessage { public static final int TYPE_INJECT_SCROLL_EVENT = 3; public static final int TYPE_BACK_OR_SCREEN_ON = 4; public static final int TYPE_EXPAND_NOTIFICATION_PANEL = 5; - public static final int TYPE_COLLAPSE_PANELS = 6; - public static final int TYPE_GET_CLIPBOARD = 7; - public static final int TYPE_SET_CLIPBOARD = 8; - public static final int TYPE_SET_SCREEN_POWER_MODE = 9; - public static final int TYPE_ROTATE_DEVICE = 10; + public static final int TYPE_EXPAND_SETTINGS_PANEL = 6; + public static final int TYPE_COLLAPSE_PANELS = 7; + public static final int TYPE_GET_CLIPBOARD = 8; + public static final int TYPE_SET_CLIPBOARD = 9; + public static final int TYPE_SET_SCREEN_POWER_MODE = 10; + public static final int TYPE_ROTATE_DEVICE = 11; private int type; private String text; diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index 97f027ff..e4ab8402 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -77,6 +77,7 @@ public class ControlMessageReader { msg = parseSetScreenPowerMode(); break; case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: + case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL: case ControlMessage.TYPE_COLLAPSE_PANELS: case ControlMessage.TYPE_GET_CLIPBOARD: case ControlMessage.TYPE_ROTATE_DEVICE: diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 15c0584a..3760bbd4 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -107,6 +107,9 @@ public class Controller { case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL: Device.expandNotificationPanel(); break; + case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL: + Device.expandSettingsPanel(); + break; case ControlMessage.TYPE_COLLAPSE_PANELS: Device.collapsePanels(); break; diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index 624c9fa0..a63976fd 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -227,6 +227,10 @@ public final class Device { SERVICE_MANAGER.getStatusBarManager().expandNotificationsPanel(); } + public static void expandSettingsPanel() { + SERVICE_MANAGER.getStatusBarManager().expandSettingsPanel(); + } + public static void collapsePanels() { SERVICE_MANAGER.getStatusBarManager().collapsePanels(); } diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java index 6f8941bd..5b1e5f5e 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/StatusBarManager.java @@ -11,6 +11,8 @@ public class StatusBarManager { private final IInterface manager; private Method expandNotificationsPanelMethod; + private Method expandSettingsPanelMethod; + private boolean expandSettingsPanelMethodNewVersion = true; private Method collapsePanelsMethod; public StatusBarManager(IInterface manager) { @@ -24,6 +26,20 @@ public class StatusBarManager { return expandNotificationsPanelMethod; } + private Method getExpandSettingsPanel() throws NoSuchMethodException { + if (expandSettingsPanelMethod == null) { + try { + // Since Android 7: https://android.googlesource.com/platform/frameworks/base.git/+/a9927325eda025504d59bb6594fee8e240d95b01%5E%21/ + expandSettingsPanelMethod = manager.getClass().getMethod("expandSettingsPanel", String.class); + } catch (NoSuchMethodException e) { + // old version + expandSettingsPanelMethod = manager.getClass().getMethod("expandSettingsPanel"); + expandSettingsPanelMethodNewVersion = false; + } + } + return expandSettingsPanelMethod; + } + private Method getCollapsePanelsMethod() throws NoSuchMethodException { if (collapsePanelsMethod == null) { collapsePanelsMethod = manager.getClass().getMethod("collapsePanels"); @@ -40,6 +56,21 @@ public class StatusBarManager { } } + public void expandSettingsPanel() { + try { + Method method = getExpandSettingsPanel(); + if (expandSettingsPanelMethodNewVersion) { + // new version + method.invoke(manager, (Object) null); + } else { + // old version + method.invoke(manager); + } + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + Ln.e("Could not invoke method", e); + } + } + public void collapsePanels() { try { Method method = getCollapsePanelsMethod(); diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index 97429026..da568486 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -181,6 +181,22 @@ public class ControlMessageReaderTest { Assert.assertEquals(ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL, event.getType()); } + @Test + public void testParseExpandSettingsPanelEvent() throws IOException { + ControlMessageReader reader = new ControlMessageReader(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeByte(ControlMessage.TYPE_EXPAND_SETTINGS_PANEL); + + byte[] packet = bos.toByteArray(); + + reader.readFrom(new ByteArrayInputStream(packet)); + ControlMessage event = reader.next(); + + Assert.assertEquals(ControlMessage.TYPE_EXPAND_SETTINGS_PANEL, event.getType()); + } + @Test public void testParseCollapsePanelsEvent() throws IOException { ControlMessageReader reader = new ControlMessageReader();