11 package com.freerdp.freerdpcore.services;
13 import android.content.Context;
14 import android.graphics.Bitmap;
15 import android.net.Uri;
16 import android.util.Log;
18 import androidx.collection.LongSparseArray;
20 import com.freerdp.freerdpcore.application.GlobalApp;
21 import com.freerdp.freerdpcore.application.SessionState;
22 import com.freerdp.freerdpcore.domain.BookmarkBase;
23 import com.freerdp.freerdpcore.domain.ManualBookmark;
24 import com.freerdp.freerdpcore.presentation.ApplicationSettingsActivity;
26 import java.util.ArrayList;
27 import java.util.Objects;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
33 private static final String TAG =
"LibFreeRDP";
35 private static boolean mHasH264 =
false;
37 private static final LongSparseArray<Boolean> mInstanceState =
new LongSparseArray<>();
39 public static final long VERIFY_CERT_FLAG_NONE = 0x00;
40 public static final long VERIFY_CERT_FLAG_LEGACY = 0x02;
41 public static final long VERIFY_CERT_FLAG_REDIRECT = 0x10;
42 public static final long VERIFY_CERT_FLAG_GATEWAY = 0x20;
43 public static final long VERIFY_CERT_FLAG_CHANGED = 0x40;
44 public static final long VERIFY_CERT_FLAG_MISMATCH = 0x80;
45 public static final long VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1 = 0x100;
46 public static final long VERIFY_CERT_FLAG_FP_IS_PEM = 0x200;
48 private static boolean tryLoad(String[] libraries)
50 boolean success =
false;
51 final String LD_PATH = System.getProperty(
"java.library.path");
52 for (String lib : libraries)
56 Log.v(TAG,
"Trying to load library " + lib +
" from LD_PATH: " + LD_PATH);
57 System.loadLibrary(lib);
60 catch (UnsatisfiedLinkError e)
62 Log.e(TAG,
"Failed to load library " + lib +
": " + e.toString());
71 private static boolean tryLoad(String library)
73 return tryLoad(
new String[] { library });
80 System.loadLibrary(
"freerdp-android");
83 String version = freerdp_get_jni_version();
84 String[] versions = version.split(
"[\\.-]");
85 if (versions.length > 0)
87 System.loadLibrary(
"freerdp-client" + versions[0]);
88 System.loadLibrary(
"freerdp" + versions[0]);
89 System.loadLibrary(
"winpr" + versions[0]);
91 Pattern pattern = Pattern.compile(
"^(\\d+)\\.(\\d+)\\.(\\d+).*");
92 Matcher matcher = pattern.matcher(version);
93 if (!matcher.matches() || (matcher.groupCount() < 3))
94 throw new RuntimeException(
"APK broken: native library version " + version +
95 " does not meet requirements!");
96 int major = Integer.parseInt(Objects.requireNonNull(matcher.group(1)));
97 int minor = Integer.parseInt(Objects.requireNonNull(matcher.group(2)));
98 int patch = Integer.parseInt(Objects.requireNonNull(matcher.group(3)));
101 mHasH264 = freerdp_has_h264();
103 mHasH264 = freerdp_has_h264();
104 else if ((minor == 5) && (patch >= 1))
105 mHasH264 = freerdp_has_h264();
107 throw new RuntimeException(
"APK broken: native library version " + version +
108 " does not meet requirements!");
109 Log.i(TAG,
"Successfully loaded native library. H264 is " +
110 (mHasH264 ?
"supported" :
"not available"));
112 catch (UnsatisfiedLinkError e)
114 Log.e(TAG,
"Failed to load library: " + e.toString());
119 public static boolean hasH264Support()
124 private static native
boolean freerdp_has_h264();
126 private static native String freerdp_get_jni_version();
128 private static native String freerdp_get_version();
130 private static native String freerdp_get_build_revision();
132 private static native String freerdp_get_build_config();
134 private static native
long freerdp_new(Context context);
136 private static native
void freerdp_free(
long inst);
138 private static native
boolean freerdp_parse_arguments(
long inst, String[] args);
140 private static native
boolean freerdp_connect(
long inst);
142 private static native
boolean freerdp_disconnect(
long inst);
144 private static native
boolean freerdp_update_graphics(
long inst, Bitmap bitmap,
int x,
int y,
145 int width,
int height);
147 private static native
boolean freerdp_send_cursor_event(
long inst,
int x,
int y,
int flags);
149 private static native
boolean freerdp_send_key_event(
long inst,
int keycode,
boolean down);
151 private static native
boolean freerdp_send_unicodekey_event(
long inst,
int keycode,
154 private static native
boolean freerdp_send_clipboard_data(
long inst, String data);
156 private static native String freerdp_get_last_error_string(
long inst);
163 public static long newInstance(Context context)
165 return freerdp_new(context);
168 public static void freeInstance(
long inst)
170 synchronized (mInstanceState)
172 if (mInstanceState.get(inst,
false))
174 freerdp_disconnect(inst);
176 while (mInstanceState.get(inst,
false))
180 mInstanceState.wait();
182 catch (InterruptedException e)
184 throw new RuntimeException();
191 public static boolean connect(
long inst)
193 synchronized (mInstanceState)
195 if (mInstanceState.get(inst,
false))
197 throw new RuntimeException(
"instance already connected");
200 return freerdp_connect(inst);
203 public static boolean disconnect(
long inst)
205 synchronized (mInstanceState)
207 if (mInstanceState.get(inst,
false))
209 return freerdp_disconnect(inst);
215 public static boolean cancelConnection(
long inst)
217 synchronized (mInstanceState)
219 if (mInstanceState.get(inst,
false))
221 return freerdp_disconnect(inst);
227 private static String addFlag(String name,
boolean enabled)
236 public static boolean setConnectionInfo(Context context,
long inst,
BookmarkBase bookmark)
243 ArrayList<String> args =
new ArrayList<>();
249 if (!clientName.isEmpty())
251 args.add(
"/client-hostname:" + clientName);
253 String certName =
"";
262 args.add(
"/v:" + hostname);
263 args.add(
"/port:" + String.valueOf(port));
265 arg = bookmark.getUsername();
268 args.add(
"/u:" + arg);
270 arg = bookmark.getDomain();
273 args.add(
"/d:" + arg);
275 arg = bookmark.getPassword();
278 args.add(
"/p:" + arg);
282 String.format(
"/size:%dx%d", screenSettings.getWidth(), screenSettings.getHeight()));
283 args.add(
"/bpp:" + String.valueOf(screenSettings.getColors()));
285 if (advanced.getConsoleMode())
290 switch (advanced.getSecurity())
293 args.add(
"/sec:nla");
296 args.add(
"/sec:tls");
299 args.add(
"/sec:rdp");
305 if (!certName.isEmpty())
307 args.add(
"/cert-name:" + certName);
311 if (flags.getRemoteFX())
321 if (flags.getH264() && mHasH264)
323 args.add(
"/gfx:AVC444");
326 args.add(addFlag(
"wallpaper", flags.getWallpaper()));
327 args.add(addFlag(
"window-drag", flags.getFullWindowDrag()));
328 args.add(addFlag(
"menu-anims", flags.getMenuAnimations()));
329 args.add(addFlag(
"themes", flags.getTheming()));
330 args.add(addFlag(
"fonts", flags.getFontSmoothing()));
331 args.add(addFlag(
"aero", flags.getDesktopComposition()));
333 if (!advanced.getRemoteProgram().isEmpty())
335 args.add(
"/shell:" + advanced.getRemoteProgram());
338 if (!advanced.getWorkDir().isEmpty())
340 args.add(
"/shell-dir:" + advanced.getWorkDir());
343 args.add(addFlag(
"async-channels", debug.getAsyncChannel()));
344 args.add(addFlag(
"async-update", debug.getAsyncUpdate()));
346 if (advanced.getRedirectSDCard())
348 String path = android.os.Environment.getExternalStorageDirectory().getPath();
349 args.add(
"/drive:sdcard," + path);
352 args.add(
"/clipboard");
361 args.add(String.format(
"/g:%s:%d", gateway.getHostname(), gateway.getPort()));
363 arg = gateway.getUsername();
366 args.add(
"/gu:" + arg);
368 arg = gateway.getDomain();
371 args.add(
"/gd:" + arg);
373 arg = gateway.getPassword();
376 args.add(
"/gp:" + arg);
383 args.add(
"/audio-mode:" + String.valueOf(advanced.getRedirectSound()));
384 if (advanced.getRedirectSound() == 0)
389 if (advanced.getRedirectMicrophone())
391 args.add(
"/microphone");
394 args.add(
"/kbd:unicode:on");
395 args.add(
"/cert:ignore");
396 args.add(
"/log-level:" + debug.getDebugLevel());
397 String[] arrayArgs = args.toArray(
new String[0]);
398 return freerdp_parse_arguments(inst, arrayArgs);
401 public static boolean setConnectionInfo(Context context,
long inst, Uri openUri)
403 ArrayList<String> args =
new ArrayList<>();
413 if (!clientName.isEmpty())
415 args.add(
"/client-hostname:" + clientName);
419 String hostname = openUri.getHost();
420 int port = openUri.getPort();
421 if (hostname !=
null)
423 hostname = hostname + ((port == -1) ?
"" : (
":" + String.valueOf(port)));
424 args.add(
"/v:" + hostname);
427 String user = openUri.getUserInfo();
430 args.add(
"/u:" + user);
433 for (String key : openUri.getQueryParameterNames())
435 String value = openUri.getQueryParameter(key);
443 else if (value.equals(
"-") || value.equals(
"+"))
447 args.add(value + key);
453 if (key.equals(
"drive") && value.equals(
"sdcard"))
456 String path = android.os.Environment.getExternalStorageDirectory().getPath();
457 value =
"sdcard," + path;
460 args.add(
"/" + key +
":" + value);
464 String[] arrayArgs = args.toArray(
new String[0]);
465 return freerdp_parse_arguments(inst, arrayArgs);
468 public static boolean updateGraphics(
long inst, Bitmap bitmap,
int x,
int y,
int width,
471 return freerdp_update_graphics(inst, bitmap, x, y, width, height);
474 public static boolean sendCursorEvent(
long inst,
int x,
int y,
int flags)
476 return freerdp_send_cursor_event(inst, x, y, flags);
479 public static boolean sendKeyEvent(
long inst,
int keycode,
boolean down)
481 return freerdp_send_key_event(inst, keycode, down);
484 public static boolean sendUnicodeKeyEvent(
long inst,
int keycode,
boolean down)
486 return freerdp_send_unicodekey_event(inst, keycode, down);
489 public static boolean sendClipboardData(
long inst, String data)
491 return freerdp_send_clipboard_data(inst, data);
494 private static void OnConnectionSuccess(
long inst)
496 if (listener !=
null)
497 listener.OnConnectionSuccess(inst);
498 synchronized (mInstanceState)
500 mInstanceState.append(inst,
true);
501 mInstanceState.notifyAll();
505 private static void OnConnectionFailure(
long inst)
507 if (listener !=
null)
508 listener.OnConnectionFailure(inst);
509 synchronized (mInstanceState)
511 mInstanceState.remove(inst);
512 mInstanceState.notifyAll();
516 private static void OnPreConnect(
long inst)
518 if (listener !=
null)
519 listener.OnPreConnect(inst);
522 private static void OnDisconnecting(
long inst)
524 if (listener !=
null)
525 listener.OnDisconnecting(inst);
528 private static void OnDisconnected(
long inst)
530 if (listener !=
null)
531 listener.OnDisconnected(inst);
532 synchronized (mInstanceState)
534 mInstanceState.remove(inst);
535 mInstanceState.notifyAll();
539 private static void OnSettingsChanged(
long inst,
int width,
int height,
int bpp)
545 if (uiEventListener !=
null)
546 uiEventListener.OnSettingsChanged(width, height, bpp);
549 private static boolean OnAuthenticate(
long inst, StringBuilder username, StringBuilder domain,
550 StringBuilder password)
556 if (uiEventListener !=
null)
557 return uiEventListener.OnAuthenticate(username, domain, password);
561 private static boolean OnGatewayAuthenticate(
long inst, StringBuilder username,
562 StringBuilder domain, StringBuilder password)
568 if (uiEventListener !=
null)
569 return uiEventListener.OnGatewayAuthenticate(username, domain, password);
573 private static int OnVerifyCertificateEx(
long inst, String host,
long port, String commonName,
574 String subject, String issuer, String fingerprint,
581 if (uiEventListener !=
null)
582 return uiEventListener.OnVerifiyCertificateEx(host, port, commonName, subject, issuer,
587 private static int OnVerifyChangedCertificateEx(
long inst, String host,
long port,
588 String commonName, String subject,
589 String issuer, String fingerprint,
590 String oldSubject, String oldIssuer,
591 String oldFingerprint,
long flags)
597 if (uiEventListener !=
null)
598 return uiEventListener.OnVerifyChangedCertificateEx(host, port, commonName, subject,
599 issuer, fingerprint, oldSubject,
600 oldIssuer, oldFingerprint, flags);
604 private static void OnGraphicsUpdate(
long inst,
int x,
int y,
int width,
int height)
610 if (uiEventListener !=
null)
611 uiEventListener.OnGraphicsUpdate(x, y, width, height);
614 private static void OnGraphicsResize(
long inst,
int width,
int height,
int bpp)
620 if (uiEventListener !=
null)
621 uiEventListener.OnGraphicsResize(width, height, bpp);
624 private static void OnRemoteClipboardChanged(
long inst, String data)
630 if (uiEventListener !=
null)
631 uiEventListener.OnRemoteClipboardChanged(data);
634 public static String getVersion()
636 return freerdp_get_version();
640 void OnPreConnect(
long instance);
642 void OnConnectionSuccess(
long instance);
644 void OnConnectionFailure(
long instance);
646 void OnDisconnecting(
long instance);
648 void OnDisconnected(
long instance);
652 void OnSettingsChanged(
int width,
int height,
int bpp);
654 boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
655 StringBuilder password);
657 boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
658 StringBuilder password);
660 int OnVerifiyCertificateEx(String host,
long port, String commonName, String subject, String issuer,
661 String fingerprint,
long flags);
663 int OnVerifyChangedCertificateEx(String host,
long port, String commonName, String subject, String issuer,
664 String fingerprint, String oldSubject, String oldIssuer,
665 String oldFingerprint,
long flags);
667 void OnGraphicsUpdate(
int x,
int y,
int width,
int height);
669 void OnGraphicsResize(
int width,
int height,
int bpp);
671 void OnRemoteClipboardChanged(String data);