Compare commits
30 Commits
device_sim
...
v4l2_sink
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59cd1f55ad | ||
|
|
0cd902bd07 | ||
|
|
860569641f | ||
|
|
a963d89a64 | ||
|
|
195073d628 | ||
|
|
9d3bf09474 | ||
|
|
b2e67b5a60 | ||
|
|
066f4f5e88 | ||
|
|
c8eb5cc6e3 | ||
|
|
49582e4a2e | ||
|
|
99c6a76eb5 | ||
|
|
c9a5611382 | ||
|
|
7309a573dc | ||
|
|
8ede4b3f58 | ||
|
|
cec5bcbe0b | ||
|
|
6d8f0a247f | ||
|
|
bb6ac2b084 | ||
|
|
eb971390ed | ||
|
|
f27403e27f | ||
|
|
f82aab2057 | ||
|
|
71327e82cb | ||
|
|
fea3f29ffd | ||
|
|
fb07f4af55 | ||
|
|
1116502704 | ||
|
|
321bf79a0b | ||
|
|
85f6f32b9e | ||
|
|
7bb17e1abc | ||
|
|
adaa88952d | ||
|
|
8bae1f6b7f | ||
|
|
e3da97a80f |
27
README.md
27
README.md
@@ -301,7 +301,7 @@ vlc v4l2:///dev/videoN # VLC might add some buffering delay
|
||||
|
||||
For example, you could capture the video within [OBS].
|
||||
|
||||
[OBS]: https://obsproject.com/fr
|
||||
[OBS]: https://obsproject.com/
|
||||
|
||||
|
||||
### Connection
|
||||
@@ -741,10 +741,10 @@ _<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
|
||||
| Rotate display left | <kbd>MOD</kbd>+<kbd>←</kbd> _(left)_
|
||||
| Rotate display right | <kbd>MOD</kbd>+<kbd>→</kbd> _(right)_
|
||||
| Resize window to 1:1 (pixel-perfect) | <kbd>MOD</kbd>+<kbd>g</kbd>
|
||||
| Resize window to remove black borders | <kbd>MOD</kbd>+<kbd>w</kbd> \| _Double-left-click¹_
|
||||
| Resize window to remove black borders | <kbd>MOD</kbd>+<kbd>w</kbd> \| _Double-click¹_
|
||||
| Click on `HOME` | <kbd>MOD</kbd>+<kbd>h</kbd> \| _Middle-click_
|
||||
| Click on `BACK` | <kbd>MOD</kbd>+<kbd>b</kbd> \| _Right-click²_
|
||||
| Click on `APP_SWITCH` | <kbd>MOD</kbd>+<kbd>s</kbd> \| _4th-click³_
|
||||
| Click on `APP_SWITCH` | <kbd>MOD</kbd>+<kbd>s</kbd>
|
||||
| Click on `MENU` (unlock screen) | <kbd>MOD</kbd>+<kbd>m</kbd>
|
||||
| Click on `VOLUME_UP` | <kbd>MOD</kbd>+<kbd>↑</kbd> _(up)_
|
||||
| Click on `VOLUME_DOWN` | <kbd>MOD</kbd>+<kbd>↓</kbd> _(down)_
|
||||
@@ -753,27 +753,18 @@ _<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
|
||||
| Turn device screen off (keep mirroring) | <kbd>MOD</kbd>+<kbd>o</kbd>
|
||||
| Turn device screen on | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>o</kbd>
|
||||
| Rotate device screen | <kbd>MOD</kbd>+<kbd>r</kbd>
|
||||
| Expand notification panel | <kbd>MOD</kbd>+<kbd>n</kbd> \| _5th-click³_
|
||||
| Expand settings panel | <kbd>MOD</kbd>+<kbd>n</kbd>+<kbd>n</kbd> \| _Double-5th-click³_
|
||||
| Collapse panels | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>n</kbd>
|
||||
| Copy to clipboard⁴ | <kbd>MOD</kbd>+<kbd>c</kbd>
|
||||
| Cut to clipboard⁴ | <kbd>MOD</kbd>+<kbd>x</kbd>
|
||||
| Synchronize clipboards and paste⁴ | <kbd>MOD</kbd>+<kbd>v</kbd>
|
||||
| Expand notification panel | <kbd>MOD</kbd>+<kbd>n</kbd>
|
||||
| Collapse notification panel | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>n</kbd>
|
||||
| Copy to clipboard³ | <kbd>MOD</kbd>+<kbd>c</kbd>
|
||||
| Cut to clipboard³ | <kbd>MOD</kbd>+<kbd>x</kbd>
|
||||
| Synchronize clipboards and paste³ | <kbd>MOD</kbd>+<kbd>v</kbd>
|
||||
| Inject computer clipboard text | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>
|
||||
| Enable/disable FPS counter (on stdout) | <kbd>MOD</kbd>+<kbd>i</kbd>
|
||||
| Pinch-to-zoom | <kbd>Ctrl</kbd>+_click-and-move_
|
||||
|
||||
_¹Double-click on black borders to remove them._
|
||||
_²Right-click turns the screen on if it was off, presses BACK otherwise._
|
||||
_³4th and 5th mouse buttons, if your mouse has them._
|
||||
_⁴Only on Android >= 7._
|
||||
|
||||
Shortcuts with repeated keys are executted by releasing and pressing the key a
|
||||
second time. For example, to execute "Expand settings panel":
|
||||
|
||||
1. Press and keep pressing <kbd>MOD</kbd>.
|
||||
2. Then double-press <kbd>n</kbd>.
|
||||
3. Finally, release <kbd>MOD</kbd>.
|
||||
_³Only on Android >= 7._
|
||||
|
||||
All <kbd>Ctrl</kbd>+_key_ shortcuts are forwarded to the device, so they are
|
||||
handled by the active application.
|
||||
|
||||
@@ -81,8 +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_COLLAPSE_NOTIFICATION_PANEL:
|
||||
case CONTROL_MSG_TYPE_GET_CLIPBOARD:
|
||||
case CONTROL_MSG_TYPE_ROTATE_DEVICE:
|
||||
// no additional data
|
||||
|
||||
@@ -27,8 +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_COLLAPSE_NOTIFICATION_PANEL,
|
||||
CONTROL_MSG_TYPE_GET_CLIPBOARD,
|
||||
CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
||||
CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
|
||||
|
||||
@@ -111,8 +111,6 @@ decoder_push(struct decoder *decoder, const AVPacket *packet) {
|
||||
// A frame lost should not make the whole pipeline fail. The error, if
|
||||
// any, is already logged.
|
||||
(void) ok;
|
||||
|
||||
av_frame_unref(decoder->frame);
|
||||
} else if (ret != AVERROR(EAGAIN)) {
|
||||
LOGE("Could not receive video frame: %d", ret);
|
||||
return false;
|
||||
|
||||
@@ -72,10 +72,6 @@ input_manager_init(struct input_manager *im,
|
||||
im->sdl_shortcut_mods.count = shortcut_mods->count;
|
||||
|
||||
im->vfinger_down = false;
|
||||
|
||||
im->last_keycode = SDLK_UNKNOWN;
|
||||
im->last_mod = 0;
|
||||
im->key_repeat = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -183,19 +179,9 @@ expand_notification_panel(struct controller *controller) {
|
||||
}
|
||||
|
||||
static void
|
||||
expand_settings_panel(struct controller *controller) {
|
||||
collapse_notification_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;
|
||||
msg.type = CONTROL_MSG_TYPE_COLLAPSE_PANELS;
|
||||
msg.type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL;
|
||||
|
||||
if (!controller_push_msg(controller, &msg)) {
|
||||
LOGW("Could not request 'collapse notification panel'");
|
||||
@@ -398,27 +384,16 @@ input_manager_process_key(struct input_manager *im,
|
||||
// control: indicates the state of the command-line option --no-control
|
||||
bool control = im->control;
|
||||
|
||||
bool smod = is_shortcut_mod(im, event->keysym.mod);
|
||||
|
||||
struct controller *controller = im->controller;
|
||||
|
||||
SDL_Keycode keycode = event->keysym.sym;
|
||||
uint16_t mod = event->keysym.mod;
|
||||
bool down = event->type == SDL_KEYDOWN;
|
||||
bool ctrl = event->keysym.mod & KMOD_CTRL;
|
||||
bool shift = event->keysym.mod & KMOD_SHIFT;
|
||||
bool repeat = event->repeat;
|
||||
|
||||
bool smod = is_shortcut_mod(im, mod);
|
||||
|
||||
if (down && !repeat) {
|
||||
if (keycode == im->last_keycode && mod == im->last_mod) {
|
||||
++im->key_repeat;
|
||||
} else {
|
||||
im->key_repeat = 0;
|
||||
im->last_keycode = keycode;
|
||||
im->last_mod = mod;
|
||||
}
|
||||
}
|
||||
|
||||
// The shortcut modifier is pressed
|
||||
if (smod) {
|
||||
int action = down ? ACTION_DOWN : ACTION_UP;
|
||||
@@ -523,11 +498,9 @@ input_manager_process_key(struct input_manager *im,
|
||||
case SDLK_n:
|
||||
if (control && !repeat && down) {
|
||||
if (shift) {
|
||||
collapse_panels(controller);
|
||||
} else if (im->key_repeat == 0) {
|
||||
expand_notification_panel(controller);
|
||||
collapse_notification_panel(controller);
|
||||
} else {
|
||||
expand_settings_panel(controller);
|
||||
expand_notification_panel(controller);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -693,11 +666,7 @@ input_manager_process_mouse_button(struct input_manager *im,
|
||||
return;
|
||||
}
|
||||
if (control && event->button == SDL_BUTTON_X2 && down) {
|
||||
if (event->clicks < 2) {
|
||||
expand_notification_panel(im->controller);
|
||||
} else {
|
||||
expand_settings_panel(im->controller);
|
||||
}
|
||||
expand_notification_panel(im->controller);
|
||||
return;
|
||||
}
|
||||
if (control && event->button == SDL_BUTTON_RIGHT) {
|
||||
|
||||
@@ -33,13 +33,6 @@ struct input_manager {
|
||||
} sdl_shortcut_mods;
|
||||
|
||||
bool vfinger_down;
|
||||
|
||||
// Tracks the number of identical consecutive shortcut key down events.
|
||||
// Not to be confused with event->repeat, which counts the number of
|
||||
// system-generated repeated key presses.
|
||||
unsigned key_repeat;
|
||||
SDL_Keycode last_keycode;
|
||||
uint16_t last_mod;
|
||||
};
|
||||
|
||||
void
|
||||
|
||||
@@ -58,7 +58,7 @@ get_server_path(void) {
|
||||
LOGE("Could not get executable path, "
|
||||
"using " SERVER_FILENAME " from current directory");
|
||||
// not found, use current directory
|
||||
return strdup(SERVER_FILENAME);
|
||||
return SERVER_FILENAME;
|
||||
}
|
||||
char *dir = dirname(executable_path);
|
||||
size_t dirlen = strlen(dir);
|
||||
@@ -70,7 +70,7 @@ get_server_path(void) {
|
||||
LOGE("Could not alloc server path string, "
|
||||
"using " SERVER_FILENAME " from current directory");
|
||||
free(executable_path);
|
||||
return strdup(SERVER_FILENAME);
|
||||
return SERVER_FILENAME;
|
||||
}
|
||||
|
||||
memcpy(server_path, dir, dirlen);
|
||||
|
||||
@@ -92,11 +92,11 @@ encode_and_write_frame(struct sc_v4l2_sink *vs, const AVFrame *frame) {
|
||||
// A packet was received
|
||||
|
||||
bool ok = write_packet(vs, packet);
|
||||
av_packet_unref(packet);
|
||||
if (!ok) {
|
||||
LOGW("Could not send packet to v4l2 sink");
|
||||
return false;
|
||||
}
|
||||
av_packet_unref(packet);
|
||||
} else if (ret != AVERROR(EAGAIN)) {
|
||||
LOGE("Could not receive v4l2 video packet: %d", ret);
|
||||
return false;
|
||||
@@ -125,7 +125,6 @@ run_v4l2_sink(void *data) {
|
||||
|
||||
video_buffer_consume(&vs->vb, vs->frame);
|
||||
bool ok = encode_and_write_frame(vs, vs->frame);
|
||||
av_frame_unref(vs->frame);
|
||||
if (!ok) {
|
||||
LOGE("Could not send frame to v4l2 sink");
|
||||
break;
|
||||
|
||||
@@ -177,9 +177,9 @@ static void test_serialize_expand_notification_panel(void) {
|
||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||
}
|
||||
|
||||
static void test_serialize_expand_settings_panel(void) {
|
||||
static void test_serialize_collapse_notification_panel(void) {
|
||||
struct control_msg msg = {
|
||||
.type = CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL,
|
||||
.type = CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||
};
|
||||
|
||||
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
||||
@@ -187,22 +187,7 @@ static void test_serialize_expand_settings_panel(void) {
|
||||
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,
|
||||
};
|
||||
|
||||
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_COLLAPSE_PANELS,
|
||||
CONTROL_MSG_TYPE_COLLAPSE_NOTIFICATION_PANEL,
|
||||
};
|
||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||
}
|
||||
@@ -289,8 +274,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_collapse_notification_panel();
|
||||
test_serialize_get_clipboard();
|
||||
test_serialize_set_clipboard();
|
||||
test_serialize_set_screen_power_mode();
|
||||
|
||||
@@ -11,12 +11,11 @@ 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_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;
|
||||
public static final int TYPE_COLLAPSE_NOTIFICATION_PANEL = 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;
|
||||
|
||||
private int type;
|
||||
private String text;
|
||||
|
||||
@@ -77,8 +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_COLLAPSE_NOTIFICATION_PANEL:
|
||||
case ControlMessage.TYPE_GET_CLIPBOARD:
|
||||
case ControlMessage.TYPE_ROTATE_DEVICE:
|
||||
msg = ControlMessage.createEmpty(type);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class Controller {
|
||||
public void control() throws IOException {
|
||||
// on start, power on the device
|
||||
if (!Device.isScreenOn()) {
|
||||
device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
|
||||
device.injectKeycode(KeyEvent.KEYCODE_POWER);
|
||||
|
||||
// dirty hack
|
||||
// After POWER is injected, the device is powered on asynchronously.
|
||||
@@ -107,10 +107,7 @@ 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:
|
||||
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||
Device.collapsePanels();
|
||||
break;
|
||||
case ControlMessage.TYPE_GET_CLIPBOARD:
|
||||
@@ -273,7 +270,7 @@ public class Controller {
|
||||
if (keepPowerModeOff) {
|
||||
schedulePowerModeOff();
|
||||
}
|
||||
return device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
|
||||
return device.injectKeycode(KeyEvent.KEYCODE_POWER);
|
||||
}
|
||||
|
||||
private boolean setClipboard(String text, boolean paste) {
|
||||
@@ -284,7 +281,7 @@ public class Controller {
|
||||
|
||||
// On Android >= 7, also press the PASTE key if requested
|
||||
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
||||
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE);
|
||||
device.injectKeycode(KeyEvent.KEYCODE_PASTE);
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
||||
@@ -164,39 +164,54 @@ public final class Device {
|
||||
return supportsInputEvents;
|
||||
}
|
||||
|
||||
public static boolean injectEvent(InputEvent inputEvent, int displayId) {
|
||||
public static boolean injectEvent(InputEvent inputEvent, int mode, int displayId) {
|
||||
if (!supportsInputEvents(displayId)) {
|
||||
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
||||
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, mode);
|
||||
}
|
||||
|
||||
public boolean injectEvent(InputEvent inputEvent, int mode) {
|
||||
if (!supportsInputEvents()) {
|
||||
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
||||
}
|
||||
|
||||
return injectEvent(inputEvent, mode, displayId);
|
||||
}
|
||||
|
||||
public static boolean injectEventOnDisplay(InputEvent event, int displayId) {
|
||||
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, displayId);
|
||||
}
|
||||
|
||||
public boolean injectEvent(InputEvent event) {
|
||||
return injectEvent(event, displayId);
|
||||
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
||||
}
|
||||
|
||||
public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
|
||||
InputDevice.SOURCE_KEYBOARD);
|
||||
return injectEvent(event, displayId);
|
||||
return injectEventOnDisplay(event, displayId);
|
||||
}
|
||||
|
||||
public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) {
|
||||
return injectKeyEvent(action, keyCode, repeat, metaState, displayId);
|
||||
long now = SystemClock.uptimeMillis();
|
||||
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
|
||||
InputDevice.SOURCE_KEYBOARD);
|
||||
return injectEvent(event);
|
||||
}
|
||||
|
||||
public static boolean pressReleaseKeycode(int keyCode, int displayId) {
|
||||
public static boolean injectKeycode(int keyCode, int displayId) {
|
||||
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId);
|
||||
}
|
||||
|
||||
public boolean pressReleaseKeycode(int keyCode) {
|
||||
return pressReleaseKeycode(keyCode, displayId);
|
||||
public boolean injectKeycode(int keyCode) {
|
||||
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
|
||||
}
|
||||
|
||||
public static boolean isScreenOn() {
|
||||
@@ -215,10 +230,6 @@ public final class Device {
|
||||
SERVICE_MANAGER.getStatusBarManager().expandNotificationsPanel();
|
||||
}
|
||||
|
||||
public static void expandSettingsPanel() {
|
||||
SERVICE_MANAGER.getStatusBarManager().expandSettingsPanel();
|
||||
}
|
||||
|
||||
public static void collapsePanels() {
|
||||
SERVICE_MANAGER.getStatusBarManager().collapsePanels();
|
||||
}
|
||||
@@ -272,7 +283,7 @@ public final class Device {
|
||||
if (!isScreenOn()) {
|
||||
return true;
|
||||
}
|
||||
return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, displayId);
|
||||
return injectKeycode(KeyEvent.KEYCODE_POWER, displayId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ public class ActivityManager {
|
||||
|
||||
private final IInterface manager;
|
||||
private Method getContentProviderExternalMethod;
|
||||
private boolean getContentProviderExternalMethodNewVersion = true;
|
||||
private boolean getContentProviderExternalMethodLegacy;
|
||||
private Method removeContentProviderExternalMethod;
|
||||
|
||||
public ActivityManager(IInterface manager) {
|
||||
@@ -29,7 +29,7 @@ public class ActivityManager {
|
||||
} catch (NoSuchMethodException e) {
|
||||
// old version
|
||||
getContentProviderExternalMethod = manager.getClass().getMethod("getContentProviderExternal", String.class, int.class, IBinder.class);
|
||||
getContentProviderExternalMethodNewVersion = false;
|
||||
getContentProviderExternalMethodLegacy = true;
|
||||
}
|
||||
}
|
||||
return getContentProviderExternalMethod;
|
||||
@@ -46,7 +46,7 @@ public class ActivityManager {
|
||||
try {
|
||||
Method method = getGetContentProviderExternalMethod();
|
||||
Object[] args;
|
||||
if (getContentProviderExternalMethodNewVersion) {
|
||||
if (!getContentProviderExternalMethodLegacy) {
|
||||
// new version
|
||||
args = new Object[]{name, ServiceManager.USER_ID, token, null};
|
||||
} else {
|
||||
|
||||
@@ -11,8 +11,6 @@ public class StatusBarManager {
|
||||
|
||||
private final IInterface manager;
|
||||
private Method expandNotificationsPanelMethod;
|
||||
private Method expandSettingsPanelMethod;
|
||||
private boolean expandSettingsPanelMethodNewVersion = true;
|
||||
private Method collapsePanelsMethod;
|
||||
|
||||
public StatusBarManager(IInterface manager) {
|
||||
@@ -26,20 +24,6 @@ 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");
|
||||
@@ -56,21 +40,6 @@ 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();
|
||||
|
||||
@@ -182,35 +182,19 @@ public class ControlMessageReaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseExpandSettingsPanelEvent() throws IOException {
|
||||
public void testParseCollapseNotificationPanelEvent() throws IOException {
|
||||
ControlMessageReader reader = new ControlMessageReader();
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(bos);
|
||||
dos.writeByte(ControlMessage.TYPE_EXPAND_SETTINGS_PANEL);
|
||||
dos.writeByte(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_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();
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(bos);
|
||||
dos.writeByte(ControlMessage.TYPE_COLLAPSE_PANELS);
|
||||
|
||||
byte[] packet = bos.toByteArray();
|
||||
|
||||
reader.readFrom(new ByteArrayInputStream(packet));
|
||||
ControlMessage event = reader.next();
|
||||
|
||||
Assert.assertEquals(ControlMessage.TYPE_COLLAPSE_PANELS, event.getType());
|
||||
Assert.assertEquals(ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL, event.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user