From 3f42c61ead715884ac6b1f85c0b6054ff437646d Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 1 Nov 2018 13:01:39 +0100 Subject: Initial import --- .../java/com/javispedro/vndroid/ServerService.java | 175 +++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 app/src/main/java/com/javispedro/vndroid/ServerService.java (limited to 'app/src/main/java/com/javispedro/vndroid/ServerService.java') 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()); + } +} -- cgit v1.2.3