FreeRDP
Loading...
Searching...
No Matches
SessionActivity.java
1/*
2 Android Session Activity
3
4 Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
5
6 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7 If a copy of the MPL was not distributed with this file, You can obtain one at
8 http://mozilla.org/MPL/2.0/.
9 */
10
11package com.freerdp.freerdpcore.presentation;
12
13import android.app.AlertDialog;
14import android.app.UiModeManager;
15import android.content.Context;
16import android.content.DialogInterface;
17import android.content.Intent;
18import android.content.SharedPreferences;
19import android.content.res.Configuration;
20import android.graphics.Bitmap;
21import android.graphics.Bitmap.Config;
22import android.graphics.Rect;
23import android.graphics.drawable.BitmapDrawable;
24import android.inputmethodservice.KeyboardView;
25import android.net.Uri;
26import android.os.Build;
27import android.os.Bundle;
28import android.os.Handler;
29import android.os.Looper;
30import android.os.Message;
31
32import androidx.activity.OnBackPressedCallback;
33import androidx.annotation.NonNull;
34import androidx.appcompat.app.AppCompatActivity;
35import androidx.core.view.WindowCompat;
36import androidx.core.view.WindowInsetsCompat;
37import androidx.core.view.WindowInsetsControllerCompat;
38import androidx.lifecycle.ViewModelProvider;
39
40import android.util.Log;
41import android.view.KeyEvent;
42import android.view.Menu;
43import android.view.MenuItem;
44import android.view.MotionEvent;
45import android.view.ScaleGestureDetector;
46import android.view.View;
47import android.view.ViewConfiguration;
48import android.view.ViewTreeObserver.OnGlobalLayoutListener;
49import android.view.WindowManager;
50import android.widget.Toast;
51
52import com.freerdp.freerdpcore.R;
53import com.freerdp.freerdpcore.application.GlobalApp;
54import com.freerdp.freerdpcore.application.SessionState;
55import com.freerdp.freerdpcore.domain.BookmarkBase;
56import com.freerdp.freerdpcore.domain.ConnectionReference;
57import com.freerdp.freerdpcore.services.LibFreeRDP;
58import com.freerdp.freerdpcore.utils.ClipboardManagerProxy;
59
60import java.util.Collection;
61import java.util.Iterator;
62
63public class SessionActivity extends AppCompatActivity
64 implements LibFreeRDP.UIEventListener, ClipboardManagerProxy.OnClipboardChangedListener
65{
66 public static final String PARAM_CONNECTION_REFERENCE = "conRef";
67 public static final String PARAM_INSTANCE = "instance";
68 private static final String TAG = "FreeRDP.SessionActivity";
69 private Bitmap bitmap;
70 private SessionState session;
71 private SessionView sessionView;
72 private TouchPointerView touchPointerView;
73
74 private static final int REFRESH_SESSIONVIEW = 1;
75 private static final int DISPLAY_TOAST = 2;
76 private static final int GRAPHICS_CHANGED = 6;
77
78 private final Handler uiHandler = new Handler(Looper.getMainLooper()) {
79 @Override public void handleMessage(Message msg)
80 {
81 switch (msg.what)
82 {
83 case GRAPHICS_CHANGED:
84 {
85 sessionView.onSurfaceChange(session);
86 scrollView.requestLayout();
87 break;
88 }
89 case REFRESH_SESSIONVIEW:
90 {
91 sessionView.invalidateRegion();
92 break;
93 }
94 case DISPLAY_TOAST:
95 {
96 Toast errorToast = Toast.makeText(getApplicationContext(), msg.obj.toString(),
97 Toast.LENGTH_LONG);
98 errorToast.show();
99 break;
100 }
101 }
102 }
103 };
104
105 private int screen_width;
106 private int screen_height;
107
108 private boolean connectCancelledByUser = false;
109 private boolean sessionRunning = false;
110 private long backPressedTime = 0;
111
112 private SessionViewModel sessionViewModel;
113 private ScrollView2D scrollView;
114 private ClipboardManagerProxy mClipboardManager;
115 private SessionInputManager inputManager;
116 private SessionDialogs dialogs;
117
118 private void hideSystemBars()
119 {
120 boolean hideStatusBar = ApplicationSettingsActivity.getHideStatusBar(this);
121 boolean hideNavBar = ApplicationSettingsActivity.getHideNavigationBar(this);
122 boolean hideActionBar = ApplicationSettingsActivity.getHideActionBar(this);
123
124 // Action bar is independent of status bar and API level.
125 if (getSupportActionBar() != null)
126 {
127 if (hideActionBar)
128 getSupportActionBar().hide();
129 else
130 getSupportActionBar().show();
131 }
132
133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
134 {
135 WindowInsetsControllerCompat controller =
136 WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
137 int toHide = 0;
138 if (hideStatusBar)
139 toHide |= WindowInsetsCompat.Type.statusBars();
140 if (hideNavBar)
141 toHide |= WindowInsetsCompat.Type.navigationBars();
142
143 if (toHide != 0)
144 {
145 controller.hide(toHide);
146 controller.setSystemBarsBehavior(
147 WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
148 }
149 else
150 {
151 controller.show(WindowInsetsCompat.Type.systemBars());
152 }
153 }
154 else
155 {
156 // API < 30: use deprecated setSystemUiVisibility.
157 int flags = 0;
158 if (hideStatusBar)
159 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
160 if (hideNavBar)
161 flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
162 if (flags != 0)
163 flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
164
165 getWindow().getDecorView().setSystemUiVisibility(flags);
166 }
167 }
168
169 @Override public void onCreate(Bundle savedInstanceState)
170 {
171 super.onCreate(savedInstanceState);
172
173 hideSystemBars();
174
175 this.setContentView(R.layout.session);
176
177 Log.v(TAG, "Session.onCreate");
178
179 // ATTENTION: We use the onGlobalLayout notification to start our
180 // session.
181 // This is because only then we can know the exact size of our session
182 // when using fit screen
183 // accounting for any status bars etc. that Android might throws on us.
184 // A bit weird looking
185 // but this is the only way ...
186 final View activityRootView = findViewById(R.id.session_root_view);
187 activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
188 new OnGlobalLayoutListener() {
189 @Override public void onGlobalLayout()
190 {
191 screen_width = activityRootView.getWidth();
192 screen_height = activityRootView.getHeight();
193
194 // start session
195 if (!sessionRunning && getIntent() != null)
196 {
197 processIntent(getIntent());
198 sessionRunning = true;
199 }
200 }
201 });
202
203 sessionView = findViewById(R.id.sessionView);
204 sessionView.requestFocus();
205
206 touchPointerView = findViewById(R.id.touchPointerView);
207
208 KeyboardView keyboardView = findViewById(R.id.extended_keyboard);
209 KeyboardView modifiersKeyboardView = findViewById(R.id.extended_keyboard_header);
210
211 scrollView = findViewById(R.id.sessionScrollView);
212 sessionViewModel = new ViewModelProvider(this).get(SessionViewModel.class);
213 sessionViewModel.getState().observe(this, this::onConnectionStateChanged);
214
215 dialogs = new SessionDialogs(this, new SessionDialogs.OnUserCancelListener() {
216 @Override public void onUserCancel()
217 {
218 connectCancelledByUser = true;
219 }
220 });
221
222 // Wire up the input manager (instance is attached later in bindSession()).
223 inputManager = new SessionInputManager(this, scrollView, sessionView, touchPointerView,
224 keyboardView, modifiersKeyboardView);
225 sessionView.setSessionViewListener(inputManager);
226 touchPointerView.setTouchPointerListener(inputManager);
227 sessionView.setScaleGestureDetector(
228 new ScaleGestureDetector(this, inputManager.getPinchZoomListener()));
229
230 mClipboardManager = ClipboardManagerProxy.getClipboardManager(this);
231 mClipboardManager.addClipboardChangedListener(this);
232
233 getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
234 @Override public void handleOnBackPressed()
235 {
236 handleBackPressed();
237 }
238 });
239
240 hideSystemBars();
241 }
242
243 @Override public void onWindowFocusChanged(boolean hasFocus)
244 {
245 super.onWindowFocusChanged(hasFocus);
246 if (hasFocus)
247 hideSystemBars();
248 mClipboardManager.getPrimaryClipManually();
249 }
250
251 @Override protected void onStart()
252 {
253 super.onStart();
254 Log.v(TAG, "Session.onStart");
255 }
256
257 @Override protected void onRestart()
258 {
259 super.onRestart();
260 Log.v(TAG, "Session.onRestart");
261 }
262
263 @Override protected void onResume()
264 {
265 super.onResume();
266 Log.v(TAG, "Session.onResume");
267 }
268
269 @Override protected void onPause()
270 {
271 super.onPause();
272 Log.v(TAG, "Session.onPause");
273
274 // hide any visible keyboards
275 inputManager.hideKeyboards();
276 }
277
278 @Override protected void onStop()
279 {
280 super.onStop();
281 Log.v(TAG, "Session.onStop");
282 }
283
284 @Override protected void onDestroy()
285 {
286 if (connectThread != null)
287 {
288 connectThread.interrupt();
289 }
290 super.onDestroy();
291 Log.v(TAG, "Session.onDestroy");
292
293 // Cancel running disconnect timers.
294 GlobalApp.cancelDisconnectTimer();
295
296 // Disconnect all remaining sessions.
297 Collection<SessionState> sessions = GlobalApp.getSessions();
298 for (SessionState session : sessions)
299 LibFreeRDP.disconnect(session.getInstance());
300
301 // unregister freerdp session listener
302 sessionViewModel.unregister();
303
304 // remove clipboard listener
305 mClipboardManager.removeClipboardboardChangedListener(this);
306
307 // free session
308 GlobalApp.freeSession(session.getInstance());
309
310 session = null;
311 }
312
313 @Override public void onConfigurationChanged(Configuration newConfig)
314 {
315 super.onConfigurationChanged(newConfig);
316
317 // reload keyboard resources (changed from landscape)
318 inputManager.reloadKeyboards();
319
320 hideSystemBars();
321 }
322
323 private void processIntent(Intent intent)
324 {
325 // get either session instance or create one from a bookmark/uri
326 Bundle bundle = intent.getExtras();
327 Uri openUri = intent.getData();
328 if (openUri != null)
329 {
330 // Launched from URI, e.g:
331 // freerdp://user@ip:port/connect?sound=&rfx=&p=password&clipboard=%2b&themes=-
332 connect(openUri);
333 }
334 else if (bundle.containsKey(PARAM_INSTANCE))
335 {
336 int inst = bundle.getInt(PARAM_INSTANCE);
337 session = GlobalApp.getSession(inst);
338 bitmap = session.getSurface().getBitmap();
339 bindSession();
340 }
341 else if (bundle.containsKey(PARAM_CONNECTION_REFERENCE))
342 {
343 String refStr = bundle.getString(PARAM_CONNECTION_REFERENCE);
344 if (ConnectionReference.isHostnameReference(refStr))
345 {
346 BookmarkBase bookmark = new BookmarkBase();
347 bookmark.setHostname(ConnectionReference.getHostname(refStr));
348 connect(bookmark);
349 }
350 else if (ConnectionReference.isBookmarkReference(refStr))
351 {
352 sessionViewModel.loadBookmarkById(ConnectionReference.getBookmarkId(refStr),
353 bookmark -> {
354 if (bookmark != null)
355 connect(bookmark);
356 else
357 closeSessionActivity(RESULT_CANCELED);
358 });
359 }
360 else
361 {
362 closeSessionActivity(RESULT_CANCELED);
363 }
364 }
365 else
366 {
367 // no session found - exit
368 closeSessionActivity(RESULT_CANCELED);
369 }
370 }
371
372 private void connect(BookmarkBase bookmark)
373 {
374 session = GlobalApp.createSession(bookmark, getApplicationContext());
375
376 BookmarkBase.ScreenSettings screenSettings =
377 session.getBookmark().getActiveScreenSettings();
378 Log.v(TAG, "Screen Resolution: " + screenSettings.getResolutionString());
379 if (screenSettings.isAutomatic())
380 {
381 if ((getResources().getConfiguration().screenLayout &
382 Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE)
383 {
384 // large screen device i.e. tablet: simply use screen info
385 screenSettings.setHeight(screen_height);
386 screenSettings.setWidth(screen_width);
387 }
388 else
389 {
390 // small screen device i.e. phone:
391 // Automatic uses the largest side length of the screen and
392 // makes a 16:10 resolution setting out of it
393 int screenMax = Math.max(screen_width, screen_height);
394 screenSettings.setHeight(screenMax);
395 screenSettings.setWidth((int)((float)screenMax * 1.6f));
396 }
397 }
398 if (screenSettings.isFitScreen())
399 {
400 screenSettings.setHeight(screen_height);
401 screenSettings.setWidth(screen_width);
402 }
403
404 connectWithTitle(bookmark.getLabel());
405 }
406
407 private void connect(Uri openUri)
408 {
409 session = GlobalApp.createSession(openUri, getApplicationContext());
410
411 connectWithTitle(openUri.getAuthority());
412 }
413
414 static class ConnectThread extends Thread
415 {
416 private final SessionState runnableSession;
417 private final Context context;
418
419 public ConnectThread(@NonNull Context context, @NonNull SessionState session)
420 {
421 this.context = context;
422 runnableSession = session;
423 }
424
425 public void run()
426 {
427 runnableSession.connect(context.getApplicationContext());
428 }
429 }
430
431 private ConnectThread connectThread = null;
432
433 private void connectWithTitle(String title)
434 {
435 session.setUIEventListener(this);
436
437 sessionViewModel.register(session.getInstance());
438
439 dialogs.showProgress(title, () -> {
440 connectCancelledByUser = true;
441 LibFreeRDP.cancelConnection(session.getInstance());
442 });
443
444 connectThread = new ConnectThread(getApplicationContext(), session);
445 connectThread.start();
446 }
447
448 // binds the current session to the activity by wiring it up with the
449 // sessionView and updating all internal objects accordingly
450 private void bindSession()
451 {
452 Log.v(TAG, "bindSession called");
453 session.setUIEventListener(this);
454 sessionView.onSurfaceChange(session);
455 scrollView.requestLayout();
456
457 Bitmap surface = session.getSurface() != null ? session.getSurface().getBitmap() : null;
458 inputManager.attachSession(session.getInstance(), surface);
459 inputManager.setScreenSize(screen_width, screen_height);
460 hideSystemBars();
461 }
462
463 private void closeSessionActivity(int resultCode)
464 {
465 // Go back to home activity (and send intent data back to home)
466 setResult(resultCode, getIntent());
467 finish();
468 }
469
470 @Override public boolean onCreateOptionsMenu(Menu menu)
471 {
472 getMenuInflater().inflate(R.menu.session_menu, menu);
473 return true;
474 }
475
476 @Override public boolean onOptionsItemSelected(MenuItem item)
477 {
478 // refer to http://tools.android.com/tips/non-constant-fields why we
479 // can't use switch/case here ..
480 int itemId = item.getItemId();
481
482 if (itemId == R.id.session_touch_pointer)
483 {
484 inputManager.toggleTouchPointer();
485 }
486 else if (itemId == R.id.session_sys_keyboard)
487 {
488 inputManager.toggleSystemKeyboard();
489 }
490 else if (itemId == R.id.session_ext_keyboard)
491 {
492 inputManager.toggleExtendedKeyboard();
493 }
494 else if (itemId == R.id.session_disconnect)
495 {
496 inputManager.hideKeyboards();
497 LibFreeRDP.disconnect(session.getInstance());
498 }
499
500 return true;
501 }
502
503 public void handleBackPressed()
504 {
505 // hide keyboards (if any visible) or send alt+f4 to the session
506 if (inputManager.isAnyKeyboardVisible())
507 {
508 inputManager.hideKeyboards();
509 return;
510 }
511 if (inputManager.handleBackAsAltF4())
512 {
513 return;
514 }
515 if (System.currentTimeMillis() - backPressedTime < 2000)
516 {
517 LibFreeRDP.disconnect(session.getInstance());
518 }
519 else
520 {
521 backPressedTime = System.currentTimeMillis();
522 Toast.makeText(this, R.string.session_double_back_to_exit, Toast.LENGTH_SHORT).show();
523 }
524 }
525
526 @Override public boolean onKeyLongPress(int keyCode, KeyEvent event)
527 {
528 if (inputManager.onAndroidKeyLongPress(keyCode))
529 return true;
530 return super.onKeyLongPress(keyCode, event);
531 }
532
533 // android keyboard input handling
534 // We always use the unicode value to process input from the android
535 // keyboard except if key modifiers
536 // (like Win, Alt, Ctrl) are activated. In this case we will send the
537 // virtual key code to allow key
538 // combinations (like Win + E to open the explorer).
539 @Override public boolean onKeyDown(int keycode, KeyEvent event)
540 {
541 if (keycode == KeyEvent.KEYCODE_BACK)
542 return super.onKeyDown(keycode, event);
543 return inputManager.onAndroidKeyEvent(event);
544 }
545
546 @Override public boolean onKeyUp(int keycode, KeyEvent event)
547 {
548 if (keycode == KeyEvent.KEYCODE_BACK)
549 return super.onKeyUp(keycode, event);
550 return inputManager.onAndroidKeyEvent(event);
551 }
552
553 // onKeyMultiple is called for input of some special characters like umlauts
554 // and some symbol characters
555 @Override public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
556 {
557 return inputManager.onAndroidKeyEvent(event);
558 }
559
560 // ****************************************************************************
561 // KeyboardMapper.KeyProcessingListener — delegated to SessionInputManager
562
563 // ****************************************************************************
564 // LibFreeRDP UI event listener implementation
565 @Override public void OnSettingsChanged(int width, int height, int bpp)
566 {
567
568 if (bpp > 16)
569 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
570 else
571 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
572
573 session.setSurface(new BitmapDrawable(getResources(), bitmap));
574
575 if (inputManager != null)
576 inputManager.setBitmap(bitmap);
577
578 if (session.getBookmark() == null)
579 {
580 // Return immediately if we launch from URI
581 return;
582 }
583 // check this settings and initial settings - if they are not equal the
584 // server doesn't support our settings
585 // FIXME: the additional check (settings.getWidth() != width + 1) is for
586 // the RDVH bug fix to avoid accidental notifications
587 // (refer to android_freerdp.c for more info on this problem)
588 BookmarkBase.ScreenSettings settings = session.getBookmark().getActiveScreenSettings();
589 if ((settings.getWidth() != width && settings.getWidth() != width + 1) ||
590 settings.getHeight() != height || settings.getColors() != bpp)
591 uiHandler.sendMessage(Message.obtain(
592 null, DISPLAY_TOAST, getResources().getText(R.string.info_capabilities_changed)));
593 }
594
595 @Override public void OnGraphicsUpdate(int x, int y, int width, int height)
596 {
597 LibFreeRDP.updateGraphics(session.getInstance(), bitmap, x, y, width, height);
598
599 sessionView.addInvalidRegion(new Rect(x, y, x + width, y + height));
600
601 /*
602 * since sessionView can only be modified from the UI thread any
603 * modifications to it need to be scheduled
604 */
605
606 uiHandler.sendEmptyMessage(REFRESH_SESSIONVIEW);
607 }
608
609 @Override public void OnGraphicsResize(int width, int height, int bpp)
610 {
611 // replace bitmap
612 if (bpp > 16)
613 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
614 else
615 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
616 session.setSurface(new BitmapDrawable(getResources(), bitmap));
617
618 if (inputManager != null)
619 inputManager.setBitmap(bitmap);
620
621 /*
622 * since sessionView can only be modified from the UI thread any
623 * modifications to it need to be scheduled
624 */
625 uiHandler.sendEmptyMessage(GRAPHICS_CHANGED);
626 }
627
628 @Override
629 public boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
630 StringBuilder password)
631 {
632 return dialogs.promptCredentials(username, domain, password);
633 }
634
635 @Override
636 public boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
637 StringBuilder password)
638 {
639 return dialogs.promptCredentials(username, domain, password);
640 }
641
642 @Override
643 public int OnVerifiyCertificateEx(String host, long port, String commonName, String subject,
644 String issuer, String fingerprint, long flags)
645 {
646 if (ApplicationSettingsActivity.getAcceptAllCertificates(this))
647 return 0;
648 return dialogs.verifyCertificate(host, port, subject, issuer, fingerprint, flags);
649 }
650
651 @Override
652 public int OnVerifyChangedCertificateEx(String host, long port, String commonName,
653 String subject, String issuer, String fingerprint,
654 String oldSubject, String oldIssuer,
655 String oldFingerprint, long flags)
656 {
657 if (ApplicationSettingsActivity.getAcceptAllCertificates(this))
658 return 0;
659 return dialogs.verifyChangedCertificate(host, port, subject, issuer, fingerprint, flags);
660 }
661
662 @Override public void OnRemoteClipboardChanged(String data)
663 {
664 Log.v(TAG, "OnRemoteClipboardChanged: " + data);
665 mClipboardManager.setClipboardData(data);
666 }
667
668 // ****************************************************************************
669 // SessionView.SessionViewListener and TouchPointerView.TouchPointerListener
670 // — delegated to SessionInputManager
671
672 @Override public boolean onGenericMotionEvent(MotionEvent e)
673 {
674 super.onGenericMotionEvent(e);
675 return inputManager != null && inputManager.onGenericMotionEvent(e);
676 }
677
678 // ****************************************************************************
679 // ClipboardManagerProxy.OnClipboardChangedListener
680 @Override public void onClipboardChanged(String data)
681 {
682 Log.v(TAG, "onClipboardChanged: " + data);
683 LibFreeRDP.sendClipboardData(session.getInstance(), data);
684 }
685
686 private void onConnectionStateChanged(SessionViewModel.ConnectionState state)
687 {
688 if (session == null)
689 return;
690 switch (state)
691 {
692 case CONNECTED:
693 onSessionConnected();
694 break;
695 case FAILED:
696 onSessionFailed();
697 break;
698 case DISCONNECTED:
699 onSessionDisconnected();
700 break;
701 default:
702 break;
703 }
704 }
705
706 private void onSessionConnected()
707 {
708 Log.v(TAG, "onSessionConnected");
709
710 if (connectCancelledByUser)
711 {
712 LibFreeRDP.disconnect(session.getInstance());
713 closeSessionActivity(RESULT_CANCELED);
714 return;
715 }
716
717 // bind session
718 bindSession();
719
720 if (ApplicationSettingsActivity.getKeepScreenOnWhenConnected(this))
721 {
722 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
723 }
724
725 dialogs.dismissProgress();
726
727 if (session.getBookmark() == null)
728 {
729 // Return immediately if we launch from URI
730 return;
731 }
732
733 // add hostname to history if quick connect was used
734 Bundle bundle = getIntent().getExtras();
735 if (bundle != null && bundle.containsKey(PARAM_CONNECTION_REFERENCE))
736 {
737 if (ConnectionReference.isHostnameReference(
738 bundle.getString(PARAM_CONNECTION_REFERENCE)))
739 {
740 assert session.getBookmark().getType() == BookmarkBase.TYPE_MANUAL;
741 sessionViewModel.recordQuickConnectHistory(session.getBookmark().getHostname());
742 }
743 }
744 }
745
746 private void onSessionFailed()
747 {
748 Log.v(TAG, "onSessionFailed");
749
750 // cancel any pending input events
751 if (inputManager != null)
752 inputManager.cancelPendingEvents();
753
754 dialogs.dismissProgress();
755
756 // post error message on UI thread
757 if (!connectCancelledByUser)
758 uiHandler.sendMessage(Message.obtain(
759 null, DISPLAY_TOAST, getResources().getText(R.string.error_connection_failure)));
760
761 closeSessionActivity(RESULT_CANCELED);
762 }
763
764 private void onSessionDisconnected()
765 {
766 Log.v(TAG, "onSessionDisconnected");
767
768 // cancel any pending input events
769 if (inputManager != null)
770 inputManager.cancelPendingEvents();
771
772 if (ApplicationSettingsActivity.getKeepScreenOnWhenConnected(this))
773 {
774 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
775 }
776
777 dialogs.dismissProgress();
778
779 session.setUIEventListener(null);
780 closeSessionActivity(RESULT_OK);
781 }
782}