summaryrefslogtreecommitdiff
path: root/app/src/main/java/com/javispedro/vndroid/ServerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/javispedro/vndroid/ServerService.java')
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ServerService.java175
1 files changed, 175 insertions, 0 deletions
diff --git a/app/src/main/java/com/javispedro/vndroid/ServerService.java b/app/src/main/java/com/javispedro/vndroid/ServerService.java
new file mode 100644
index 0000000..bf72d21
--- /dev/null
+++ b/app/src/main/java/com/javispedro/vndroid/ServerService.java
@@ -0,0 +1,175 @@
+package com.javispedro.vndroid;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.media.Image;
+import android.media.projection.MediaProjection;
+import android.media.projection.MediaProjectionManager;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+import com.javispedro.vndroid.keymaps.AndroidKeyHandler;
+import com.javispedro.vndroid.keymaps.SpanishKeyHandler;
+
+public class ServerService extends Service {
+ private static final String TAG = ServerService.class.getSimpleName();
+ public static final String ACTION_START = "ACTION_START";
+ public static final String ACTION_STOP = "ACTION_STOP";
+ public static final String ACTION_NOTIFY_MEDIA_PROJECTION_RESULT = "ACTION_NOTIFY_MEDIA_PROJECTION_RESULT";
+
+ private ScreenGrabber screenGrabber;
+ private RFBServer rfbServer;
+ private PointerEventOutput pointerOut;
+ private KeyEventOutput keyOut;
+
+ public ServerService() {
+ }
+
+ @Override
+ public void onCreate() {
+ ServerRunningNotification.initNotificationChannel(this);
+ System.loadLibrary("native-lib");
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null) {
+ switch (intent.getAction()) {
+ case ACTION_START:
+ start();
+ break;
+ case ACTION_STOP:
+ stop();
+ break;
+ case ACTION_NOTIFY_MEDIA_PROJECTION_RESULT:
+ notifyMediaProjectionResult(intent.getIntExtra("resultCode", Activity.RESULT_CANCELED),
+ (Intent) intent.getParcelableExtra("resultData"));
+ break;
+ }
+ }
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if (screenGrabber != null && screenGrabber.hasSizeChanged()) {
+ Log.d(TAG, "screen size has changed");
+ screenGrabber.updateScreenSize();
+ }
+ }
+
+ protected class ScreenGrabberCallback implements ScreenGrabber.Callback {
+ @Override
+ public void onImage(Image image) {
+ if (rfbServer != null) {
+ rfbServer.putImage(image);
+ } else {
+ image.close();
+ }
+ }
+ }
+
+ protected class EventCallback implements RFBServer.EventCallback {
+ @Override
+ public void onPointerEvent(int buttonMask, int x, int y) {
+ try {
+ x = screenGrabber.scaleInputX(x);
+ y = screenGrabber.scaleInputY(y);
+ pointerOut.postPointerEvent((byte) buttonMask, x, y);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception on pointer EventCallback: " + e.toString());
+ e.printStackTrace();
+ // Need to supress the exception, otherwise we'll crash JNI
+ }
+ }
+
+ @Override
+ public void onKeyEvent(int key, boolean state) {
+ try {
+ keyOut.postKeyEvent(key, state);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception on key EventCallback: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ protected void start() {
+ if (rfbServer != null) {
+ Log.w(TAG, "cannot start, already started");
+ return;
+ }
+
+ Log.d(TAG, "starting");
+
+ if (!ControlService.isServiceStarted()) {
+ Toast toast = Toast.makeText(this, R.string.toast_no_input_service, Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+ pointerOut = new PointerEventOutput();
+ keyOut = new KeyEventOutput();
+ keyOut.addHandler(new AndroidKeyHandler());
+ keyOut.addHandler(new SpanishKeyHandler());
+
+
+ if (screenGrabber == null) {
+ screenGrabber = new ScreenVirtualGrabber(this);
+ }
+
+ rfbServer = new RFBServer();
+ rfbServer.setEventCallback(new EventCallback());
+ rfbServer.start();
+
+ screenGrabber.setCallback(new ScreenGrabberCallback());
+ screenGrabber.start();
+
+ Notification notification = ServerRunningNotification.build(this);
+ startForeground(1, notification);
+ }
+
+ protected void stop() {
+ Log.d(TAG, "stopping");
+
+ if (rfbServer != null) {
+ rfbServer.stop();
+ rfbServer = null;
+ }
+ if (screenGrabber != null) {
+ screenGrabber.stop();
+ screenGrabber = null;
+ }
+ if (pointerOut != null) {
+ pointerOut = null;
+ }
+ if (keyOut != null) {
+ keyOut = null;
+ }
+
+ stopForeground(true);
+ stopSelf();
+ }
+
+ protected void notifyMediaProjectionResult(int resultCode, Intent data) {
+ if (screenGrabber != null) {
+ Log.w(TAG, "already have an screen grabber");
+ }
+ MediaProjectionManager manager = getSystemService(MediaProjectionManager.class);
+ MediaProjection projection = manager.getMediaProjection(resultCode, data);
+
+ WindowManager wm = getSystemService(WindowManager.class);
+
+ screenGrabber = new ScreenMirrorGrabber(this, projection, wm.getDefaultDisplay());
+ }
+}