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);
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);
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_is_unicode_input_supported(
long inst);
156 private static native
boolean freerdp_send_clipboard_data(
long inst, String data);
158 private static native
boolean freerdp_send_clipboard_image_data(
long inst,
byte[] data,
161 private static native
boolean freerdp_send_monitor_layout(
long inst,
int width,
int height);
163 private static native String freerdp_get_last_error_string(
long inst);
170 public static long newInstance(Context context)
172 return freerdp_new(context);
175 public static void freeInstance(
long inst)
177 synchronized (mInstanceState)
179 if (mInstanceState.get(inst,
false))
181 freerdp_disconnect(inst);
183 while (mInstanceState.get(inst,
false))
187 mInstanceState.wait();
189 catch (InterruptedException e)
191 throw new RuntimeException();
198 public static boolean connect(
long inst)
200 synchronized (mInstanceState)
202 if (mInstanceState.get(inst,
false))
204 throw new RuntimeException(
"instance already connected");
207 return freerdp_connect(inst);
210 public static boolean disconnect(
long inst)
212 synchronized (mInstanceState)
214 if (mInstanceState.get(inst,
false))
216 return freerdp_disconnect(inst);
222 public static boolean cancelConnection(
long inst)
224 return freerdp_disconnect(inst);
227 private static String addFlag(String name,
boolean enabled)
236 public static boolean setConnectionInfo(Context context,
long inst, BookmarkBase bookmark)
238 BookmarkBase.ScreenSettings screenSettings = bookmark.getActiveScreenSettings();
239 BookmarkBase.AdvancedSettings advanced = bookmark.getAdvancedSettings();
240 BookmarkBase.DebugSettings debug = bookmark.getDebugSettings();
243 ArrayList<String> args =
new ArrayList<>();
248 final String clientName = ApplicationSettingsActivity.getClientName(context);
249 if (!clientName.isEmpty())
251 args.add(
"/client-hostname:" + clientName);
253 String certName =
"";
254 if (bookmark.getType() != BookmarkBase.TYPE_MANUAL)
259 int port = bookmark.getPort();
260 String hostname = bookmark.getHostname();
262 args.add(
"/v:" + hostname);
263 args.add(
"/port:" + port);
265 final int level = advanced.getTlsSecLevel();
266 List<String> tls =
new ArrayList<>();
270 tls.add(
"seclevel:" + level);
273 final int tlsMinLevel = advanced.getTlsMinLevel();
274 if (tlsMinLevel >= 0)
276 tls.add(
"enforce:" + tlsMinLevel);
281 StringBuilder sb =
new StringBuilder();
290 args.add(
"/tls:" + sb);
293 arg = bookmark.getUsername();
296 args.add(
"/u:" + arg);
298 arg = bookmark.getDomain();
301 args.add(
"/d:" + arg);
303 arg = bookmark.getPassword();
306 args.add(
"/p:" + arg);
309 args.add(String.format(java.util.Locale.US,
"/size:%dx%d", screenSettings.getWidth(),
310 screenSettings.getHeight()));
311 args.add(
"/bpp:" + screenSettings.getColors());
313 if (screenSettings.isCustomScale())
315 args.add(
"/scale-desktop:" + screenSettings.getScaleDesktop());
316 args.add(
"/scale-device:" + screenSettings.getScaleDevice());
320 args.add(
"/scale:" + screenSettings.getScalePreset());
323 if (advanced.getConsoleMode())
328 if (advanced.getVmConnectMode())
330 String guid = advanced.getVmConnectGuid();
332 args.add(
"/vmconnect:" + guid);
334 args.add(
"/vmconnect");
337 switch (advanced.getSecurity())
340 args.add(
"/sec:nla");
343 args.add(
"/sec:tls");
346 args.add(
"/sec:rdp");
352 if (!certName.isEmpty())
354 args.add(
"/cert-name:" + certName);
357 BookmarkBase.PerformanceFlags flags = bookmark.getActivePerformanceFlags();
358 if (flags.getRemoteFX())
361 args.add(
"/network:auto");
367 args.add(
"/network:auto");
370 if (flags.getH264() && mHasH264)
372 args.add(
"/gfx:AVC444");
373 args.add(
"/network:auto");
376 args.add(addFlag(
"wallpaper", flags.getWallpaper()));
377 args.add(addFlag(
"window-drag", flags.getFullWindowDrag()));
378 args.add(addFlag(
"menu-anims", flags.getMenuAnimations()));
379 args.add(addFlag(
"themes", flags.getTheming()));
380 args.add(addFlag(
"fonts", flags.getFontSmoothing()));
381 args.add(addFlag(
"aero", flags.getDesktopComposition()));
383 if (!advanced.getRemoteProgram().isEmpty())
385 args.add(
"/shell:" + advanced.getRemoteProgram());
388 if (!advanced.getWorkDir().isEmpty())
390 args.add(
"/shell-dir:" + advanced.getWorkDir());
393 args.add(addFlag(
"async-channels", debug.getAsyncChannel()));
394 args.add(addFlag(
"async-update", debug.getAsyncUpdate()));
396 if (advanced.getRedirectSDCard())
398 String path = android.os.Environment.getExternalStorageDirectory().getPath();
399 args.add(
"/drive:sdcard," + path);
402 String info = advanced.getLoadBalanceInfo();
405 args.add(
"/load-balance-info:" + info);
407 args.add(
"/clipboard");
410 if (advanced.getRedirectPrinter())
411 args.add(
"/printer:aFreeRDP Print,Microsoft Print to PDF,default");
414 if (bookmark.getType() == BookmarkBase.TYPE_MANUAL && bookmark.getEnableGatewaySettings())
416 BookmarkBase.GatewaySettings gateway = bookmark.getGatewaySettings();
418 StringBuilder carg =
new StringBuilder();
419 carg.append(String.format(java.util.Locale.US,
"/gateway:g:%s:%d",
420 gateway.getHostname(), gateway.getPort()));
422 arg = gateway.getUsername();
425 carg.append(
",u:" + arg);
427 arg = gateway.getDomain();
430 carg.append(
",d:" + arg);
432 arg = gateway.getPassword();
435 carg.append(
",p:" + arg);
437 args.add(carg.toString());
443 args.add(
"/audio-mode:" + advanced.getRedirectSound());
444 if (advanced.getRedirectSound() == 0)
449 if (advanced.getRedirectMicrophone())
451 args.add(
"/microphone");
454 args.add(
"/kbd:unicode:on");
455 args.add(
"/cert:ignore");
456 args.add(
"/log-level:" + debug.getDebugLevel());
457 String[] arrayArgs = args.toArray(
new String[0]);
458 return freerdp_parse_arguments(inst, arrayArgs);
461 public static boolean setConnectionInfo(Context context,
long inst, Uri openUri)
463 ArrayList<String> args =
new ArrayList<>();
472 final String clientName = ApplicationSettingsActivity.getClientName(context);
473 if (!clientName.isEmpty())
475 args.add(
"/client-hostname:" + clientName);
479 String hostname = openUri.getHost();
480 int port = openUri.getPort();
481 if (hostname !=
null)
483 hostname = hostname + ((port == -1) ?
"" : (
":" + port));
484 args.add(
"/v:" + hostname);
487 String user = openUri.getUserInfo();
490 args.add(
"/u:" + user);
493 for (String key : openUri.getQueryParameterNames())
495 String value = openUri.getQueryParameter(key);
503 else if (value.equals(
"-") || value.equals(
"+"))
507 args.add(value + key);
513 if (key.equals(
"drive") && value.equals(
"sdcard"))
516 String path = android.os.Environment.getExternalStorageDirectory().getPath();
517 value =
"sdcard," + path;
520 args.add(
"/" + key +
":" + value);
524 String[] arrayArgs = args.toArray(
new String[0]);
525 return freerdp_parse_arguments(inst, arrayArgs);
528 public static boolean updateGraphics(
long inst, Bitmap bitmap,
int x,
int y,
int width,
531 return freerdp_update_graphics(inst, bitmap, x, y, width, height);
534 public static boolean sendCursorEvent(
long inst,
int x,
int y,
int flags)
536 return freerdp_send_cursor_event(inst, x, y, flags);
539 public static boolean sendKeyEvent(
long inst,
int keycode,
boolean down)
541 return freerdp_send_key_event(inst, keycode, down);
544 public static boolean sendUnicodeKeyEvent(
long inst,
int keycode,
boolean down)
546 return freerdp_send_unicodekey_event(inst, keycode, down);
549 public static boolean isUnicodeInputSupported(
long inst)
551 return freerdp_is_unicode_input_supported(inst);
554 public static boolean sendClipboardData(
long inst, String data)
556 return freerdp_send_clipboard_data(inst, data);
559 public static boolean sendClipboardImageData(
long inst,
byte[] data, String mimeType)
561 return freerdp_send_clipboard_image_data(inst, data, mimeType);
564 public static boolean sendMonitorLayout(
long inst,
int width,
int height)
566 return freerdp_send_monitor_layout(inst, width, height);
569 private static void OnConnectionSuccess(
long inst)
571 if (listener !=
null)
572 listener.OnConnectionSuccess(inst);
573 synchronized (mInstanceState)
575 mInstanceState.append(inst,
true);
576 mInstanceState.notifyAll();
580 private static void OnConnectionFailure(
long inst)
582 if (listener !=
null)
583 listener.OnConnectionFailure(inst);
584 synchronized (mInstanceState)
586 mInstanceState.remove(inst);
587 mInstanceState.notifyAll();
591 private static void OnPreConnect(
long inst)
593 if (listener !=
null)
594 listener.OnPreConnect(inst);
597 private static void OnDisconnecting(
long inst)
599 if (listener !=
null)
600 listener.OnDisconnecting(inst);
603 private static void OnDisconnected(
long inst)
605 if (listener !=
null)
606 listener.OnDisconnected(inst);
607 synchronized (mInstanceState)
609 mInstanceState.remove(inst);
610 mInstanceState.notifyAll();
614 private static void OnSettingsChanged(
long inst,
int width,
int height,
int bpp)
616 SessionState s = GlobalApp.getSession(inst);
620 if (uiEventListener !=
null)
621 uiEventListener.OnSettingsChanged(width, height, bpp);
624 private static boolean OnAuthenticate(
long inst, StringBuilder username, StringBuilder domain,
625 StringBuilder password)
627 SessionState s = GlobalApp.getSession(inst);
631 if (uiEventListener !=
null)
632 return uiEventListener.OnAuthenticate(username, domain, password);
636 private static boolean OnGatewayAuthenticate(
long inst, StringBuilder username,
637 StringBuilder domain, StringBuilder password)
639 SessionState s = GlobalApp.getSession(inst);
643 if (uiEventListener !=
null)
644 return uiEventListener.OnGatewayAuthenticate(username, domain, password);
648 private static int OnVerifyCertificateEx(
long inst, String host,
long port, String commonName,
649 String subject, String issuer, String fingerprint,
652 SessionState s = GlobalApp.getSession(inst);
656 if (uiEventListener !=
null)
657 return uiEventListener.OnVerifiyCertificateEx(host, port, commonName, subject, issuer,
662 private static int OnVerifyChangedCertificateEx(
long inst, String host,
long port,
663 String commonName, String subject,
664 String issuer, String fingerprint,
665 String oldSubject, String oldIssuer,
666 String oldFingerprint,
long flags)
668 SessionState s = GlobalApp.getSession(inst);
672 if (uiEventListener !=
null)
673 return uiEventListener.OnVerifyChangedCertificateEx(host, port, commonName, subject,
674 issuer, fingerprint, oldSubject,
675 oldIssuer, oldFingerprint, flags);
679 private static void OnGraphicsUpdate(
long inst,
int x,
int y,
int width,
int height)
681 SessionState s = GlobalApp.getSession(inst);
685 if (uiEventListener !=
null)
686 uiEventListener.OnGraphicsUpdate(x, y, width, height);
689 private static void OnGraphicsResize(
long inst,
int width,
int height,
int bpp)
691 SessionState s = GlobalApp.getSession(inst);
695 if (uiEventListener !=
null)
696 uiEventListener.OnGraphicsResize(width, height, bpp);
699 private static void OnRemoteClipboardChanged(
long inst, String data)
701 SessionState s = GlobalApp.getSession(inst);
705 if (uiEventListener !=
null)
706 uiEventListener.OnRemoteClipboardChanged(data);
709 private static void OnRemoteClipboardImageChanged(
long inst,
byte[] data)
711 SessionState s = GlobalApp.getSession(inst);
715 if (uiEventListener !=
null)
716 uiEventListener.OnRemoteClipboardImageChanged(data);
719 private static void OnPointerSet(
long inst,
int[] pixels,
int width,
int height,
int hotX,
722 SessionState s = GlobalApp.getSession(inst);
726 if (uiEventListener !=
null)
727 uiEventListener.OnPointerSet(pixels, width, height, hotX, hotY);
730 private static void OnPointerSetNull(
long inst)
732 SessionState s = GlobalApp.getSession(inst);
736 if (uiEventListener !=
null)
737 uiEventListener.OnPointerSetNull();
740 private static void OnPointerSetDefault(
long inst)
742 SessionState s = GlobalApp.getSession(inst);
746 if (uiEventListener !=
null)
747 uiEventListener.OnPointerSetDefault();
750 public static String getVersion()
752 return freerdp_get_version();
757 void OnPreConnect(
long instance);
759 void OnConnectionSuccess(
long instance);
761 void OnConnectionFailure(
long instance);
763 void OnDisconnecting(
long instance);
765 void OnDisconnected(
long instance);
770 void OnSettingsChanged(
int width,
int height,
int bpp);
772 boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
773 StringBuilder password);
775 boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
776 StringBuilder password);
778 int OnVerifiyCertificateEx(String host,
long port, String commonName, String subject, String issuer,
779 String fingerprint,
long flags);
781 int OnVerifyChangedCertificateEx(String host,
long port, String commonName, String subject, String issuer,
782 String fingerprint, String oldSubject, String oldIssuer,
783 String oldFingerprint,
long flags);
785 void OnGraphicsUpdate(
int x,
int y,
int width,
int height);
787 void OnGraphicsResize(
int width,
int height,
int bpp);
789 void OnRemoteClipboardChanged(String data);
791 void OnRemoteClipboardImageChanged(
byte[] data);
793 void OnPointerSet(
int[] pixels,
int width,
int height,
int hotX,
int hotY);
795 void OnPointerSetNull();
797 void OnPointerSetDefault();