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_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)
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.<ManualBookmark>
get().getPort();
260 String hostname = bookmark.<ManualBookmark>
get().getHostname();
262 args.add(
"/v:" + hostname);
263 args.add(
"/port:" + 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:" + 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);
310 BookmarkBase.PerformanceFlags flags = bookmark.getActivePerformanceFlags();
311 if (flags.getRemoteFX())
314 args.add(
"/network:auto");
320 args.add(
"/network:auto");
323 if (flags.getH264() && mHasH264)
325 args.add(
"/gfx:AVC444");
326 args.add(
"/network:auto");
329 args.add(addFlag(
"wallpaper", flags.getWallpaper()));
330 args.add(addFlag(
"window-drag", flags.getFullWindowDrag()));
331 args.add(addFlag(
"menu-anims", flags.getMenuAnimations()));
332 args.add(addFlag(
"themes", flags.getTheming()));
333 args.add(addFlag(
"fonts", flags.getFontSmoothing()));
334 args.add(addFlag(
"aero", flags.getDesktopComposition()));
336 if (!advanced.getRemoteProgram().isEmpty())
338 args.add(
"/shell:" + advanced.getRemoteProgram());
341 if (!advanced.getWorkDir().isEmpty())
343 args.add(
"/shell-dir:" + advanced.getWorkDir());
346 args.add(addFlag(
"async-channels", debug.getAsyncChannel()));
347 args.add(addFlag(
"async-update", debug.getAsyncUpdate()));
349 if (advanced.getRedirectSDCard())
351 String path = android.os.Environment.getExternalStorageDirectory().getPath();
352 args.add(
"/drive:sdcard," + path);
355 args.add(
"/clipboard");
358 if (bookmark.getType() == BookmarkBase.TYPE_MANUAL &&
359 bookmark.<ManualBookmark>
get().getEnableGatewaySettings())
361 ManualBookmark.GatewaySettings gateway =
362 bookmark.<ManualBookmark>
get().getGatewaySettings();
365 String.format(
"/gateway:g:%s:%d", gateway.getHostname(), gateway.getPort());
367 arg = gateway.getUsername();
370 carg.append(
",u:" + arg);
372 arg = gateway.getDomain();
375 carg.append(
",d:" + arg);
377 arg = gateway.getPassword();
380 cargs.append(
",p:" + arg);
382 args.add(String.format(
"/gateway:g:%s:%d", gateway.getHostname(), gateway.getPort()));
388 args.add(
"/audio-mode:" + advanced.getRedirectSound());
389 if (advanced.getRedirectSound() == 0)
394 if (advanced.getRedirectMicrophone())
396 args.add(
"/microphone");
399 args.add(
"/kbd:unicode:on");
400 args.add(
"/cert:ignore");
401 args.add(
"/log-level:" + debug.getDebugLevel());
402 String[] arrayArgs = args.toArray(
new String[0]);
403 return freerdp_parse_arguments(inst, arrayArgs);
406 public static boolean setConnectionInfo(Context context,
long inst, Uri openUri)
408 ArrayList<String> args =
new ArrayList<>();
417 final String clientName = ApplicationSettingsActivity.getClientName(context);
418 if (!clientName.isEmpty())
420 args.add(
"/client-hostname:" + clientName);
424 String hostname = openUri.getHost();
425 int port = openUri.getPort();
426 if (hostname !=
null)
428 hostname = hostname + ((port == -1) ?
"" : (
":" + port));
429 args.add(
"/v:" + hostname);
432 String user = openUri.getUserInfo();
435 args.add(
"/u:" + user);
438 for (String key : openUri.getQueryParameterNames())
440 String value = openUri.getQueryParameter(key);
448 else if (value.equals(
"-") || value.equals(
"+"))
452 args.add(value + key);
458 if (key.equals(
"drive") && value.equals(
"sdcard"))
461 String path = android.os.Environment.getExternalStorageDirectory().getPath();
462 value =
"sdcard," + path;
465 args.add(
"/" + key +
":" + value);
469 String[] arrayArgs = args.toArray(
new String[0]);
470 return freerdp_parse_arguments(inst, arrayArgs);
473 public static boolean updateGraphics(
long inst, Bitmap bitmap,
int x,
int y,
int width,
476 return freerdp_update_graphics(inst, bitmap, x, y, width, height);
479 public static boolean sendCursorEvent(
long inst,
int x,
int y,
int flags)
481 return freerdp_send_cursor_event(inst, x, y, flags);
484 public static boolean sendKeyEvent(
long inst,
int keycode,
boolean down)
486 return freerdp_send_key_event(inst, keycode, down);
489 public static boolean sendUnicodeKeyEvent(
long inst,
int keycode,
boolean down)
491 return freerdp_send_unicodekey_event(inst, keycode, down);
494 public static boolean sendClipboardData(
long inst, String data)
496 return freerdp_send_clipboard_data(inst, data);
499 private static void OnConnectionSuccess(
long inst)
501 if (listener !=
null)
502 listener.OnConnectionSuccess(inst);
503 synchronized (mInstanceState)
505 mInstanceState.append(inst,
true);
506 mInstanceState.notifyAll();
510 private static void OnConnectionFailure(
long inst)
512 if (listener !=
null)
513 listener.OnConnectionFailure(inst);
514 synchronized (mInstanceState)
516 mInstanceState.remove(inst);
517 mInstanceState.notifyAll();
521 private static void OnPreConnect(
long inst)
523 if (listener !=
null)
524 listener.OnPreConnect(inst);
527 private static void OnDisconnecting(
long inst)
529 if (listener !=
null)
530 listener.OnDisconnecting(inst);
533 private static void OnDisconnected(
long inst)
535 if (listener !=
null)
536 listener.OnDisconnected(inst);
537 synchronized (mInstanceState)
539 mInstanceState.remove(inst);
540 mInstanceState.notifyAll();
544 private static void OnSettingsChanged(
long inst,
int width,
int height,
int bpp)
546 SessionState s = GlobalApp.getSession(inst);
550 if (uiEventListener !=
null)
551 uiEventListener.OnSettingsChanged(width, height, bpp);
554 private static boolean OnAuthenticate(
long inst, StringBuilder username, StringBuilder domain,
555 StringBuilder password)
557 SessionState s = GlobalApp.getSession(inst);
561 if (uiEventListener !=
null)
562 return uiEventListener.OnAuthenticate(username, domain, password);
566 private static boolean OnGatewayAuthenticate(
long inst, StringBuilder username,
567 StringBuilder domain, StringBuilder password)
569 SessionState s = GlobalApp.getSession(inst);
573 if (uiEventListener !=
null)
574 return uiEventListener.OnGatewayAuthenticate(username, domain, password);
578 private static int OnVerifyCertificateEx(
long inst, String host,
long port, String commonName,
579 String subject, String issuer, String fingerprint,
582 SessionState s = GlobalApp.getSession(inst);
586 if (uiEventListener !=
null)
587 return uiEventListener.OnVerifiyCertificateEx(host, port, commonName, subject, issuer,
592 private static int OnVerifyChangedCertificateEx(
long inst, String host,
long port,
593 String commonName, String subject,
594 String issuer, String fingerprint,
595 String oldSubject, String oldIssuer,
596 String oldFingerprint,
long flags)
598 SessionState s = GlobalApp.getSession(inst);
602 if (uiEventListener !=
null)
603 return uiEventListener.OnVerifyChangedCertificateEx(host, port, commonName, subject,
604 issuer, fingerprint, oldSubject,
605 oldIssuer, oldFingerprint, flags);
609 private static void OnGraphicsUpdate(
long inst,
int x,
int y,
int width,
int height)
611 SessionState s = GlobalApp.getSession(inst);
615 if (uiEventListener !=
null)
616 uiEventListener.OnGraphicsUpdate(x, y, width, height);
619 private static void OnGraphicsResize(
long inst,
int width,
int height,
int bpp)
621 SessionState s = GlobalApp.getSession(inst);
625 if (uiEventListener !=
null)
626 uiEventListener.OnGraphicsResize(width, height, bpp);
629 private static void OnRemoteClipboardChanged(
long inst, String data)
631 SessionState s = GlobalApp.getSession(inst);
635 if (uiEventListener !=
null)
636 uiEventListener.OnRemoteClipboardChanged(data);
639 public static String getVersion()
641 return freerdp_get_version();
646 void OnPreConnect(
long instance);
648 void OnConnectionSuccess(
long instance);
650 void OnConnectionFailure(
long instance);
652 void OnDisconnecting(
long instance);
654 void OnDisconnected(
long instance);
659 void OnSettingsChanged(
int width,
int height,
int bpp);
661 boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
662 StringBuilder password);
664 boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
665 StringBuilder password);
667 int OnVerifiyCertificateEx(String host,
long port, String commonName, String subject, String issuer,
668 String fingerprint,
long flags);
670 int OnVerifyChangedCertificateEx(String host,
long port, String commonName, String subject, String issuer,
671 String fingerprint, String oldSubject, String oldIssuer,
672 String oldFingerprint,
long flags);
674 void OnGraphicsUpdate(
int x,
int y,
int width,
int height);
676 void OnGraphicsResize(
int width,
int height,
int bpp);
678 void OnRemoteClipboardChanged(String data);