Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chromoting.jni; | 5 package org.chromium.chromoting.jni; |
| 6 | 6 |
| 7 import android.graphics.Bitmap; | |
| 8 import android.graphics.Point; | |
| 9 import android.os.Looper; | |
| 10 | |
| 11 import org.chromium.base.Log; | |
| 12 import org.chromium.base.annotations.CalledByNative; | 7 import org.chromium.base.annotations.CalledByNative; |
| 13 import org.chromium.base.annotations.JNINamespace; | 8 import org.chromium.base.annotations.JNINamespace; |
| 14 import org.chromium.base.annotations.SuppressFBWarnings; | 9 import org.chromium.base.annotations.SuppressFBWarnings; |
| 15 import org.chromium.chromoting.CapabilityManager; | 10 import org.chromium.chromoting.CapabilityManager; |
| 16 import org.chromium.chromoting.SessionAuthenticator; | 11 import org.chromium.chromoting.SessionAuthenticator; |
| 17 | 12 |
| 18 import java.nio.ByteBuffer; | |
| 19 import java.nio.ByteOrder; | |
| 20 | |
| 21 /** | 13 /** |
| 22 * Class to manage a client connection to the host. This class controls the life time of the | 14 * Class to manage a client connection to the host. This class controls the life time of the |
| 23 * corresponding C++ object which implements the connection. A new object should be created for | 15 * corresponding C++ object which implements the connection. A new object should be created for |
| 24 * each connection to the host, so that notifications from a connection are alwa ys sent to the | 16 * each connection to the host, so that notifications from a connection are alwa ys sent to the |
| 25 * right object. | 17 * right object. |
| 26 */ | 18 */ |
| 27 @JNINamespace("remoting") | 19 @JNINamespace("remoting") |
| 28 public class Client { | 20 public class Client { |
| 29 private static final String TAG = "Chromoting"; | |
| 30 | |
| 31 // Pointer to the C++ object, cast to a |long|. | 21 // Pointer to the C++ object, cast to a |long|. |
| 32 private long mNativeJniClient; | 22 private long mNativeJniClient; |
| 33 | 23 |
| 24 // Reference has to be kept until the lifecycle of Client ends. Code may use getDisplay() | |
| 25 // without doing a null check. | |
| 26 private Display mDisplay; | |
| 27 | |
| 34 // The global Client instance (may be null). This needs to be a global singl eton so that the | 28 // The global Client instance (may be null). This needs to be a global singl eton so that the |
| 35 // Client can be passed between Activities. | 29 // Client can be passed between Activities. |
| 36 private static Client sClient; | 30 private static Client sClient; |
| 37 | 31 |
| 38 // Called on the UI thread. | 32 // Called on the UI thread. |
|
Lambros
2016/05/28 00:43:05
If everything is called on the UI thread, you can
Yuwei
2016/06/01 21:30:10
Done.
| |
| 39 public Client() { | 33 public Client() { |
| 40 if (sClient != null) { | 34 if (sClient != null) { |
| 41 throw new RuntimeException("Client instance already created."); | 35 throw new RuntimeException("Client instance already created."); |
| 42 } | 36 } |
| 43 | 37 |
| 44 sClient = this; | 38 sClient = this; |
| 45 mNativeJniClient = nativeInit(); | 39 mNativeJniClient = nativeInit(); |
| 46 } | 40 } |
| 47 | 41 |
| 42 /** | |
| 43 * | |
|
Lambros
2016/05/28 00:43:05
Better to provide a JavaDoc one-sentence summary,
Yuwei
2016/06/01 21:30:10
Done.
| |
| 44 * @return the display object. It will be null before calling connectToHost( ) but won't be null | |
| 45 * after calling disconnectFromHost(). | |
| 46 */ | |
| 47 public Display getDisplay() { | |
| 48 return mDisplay; | |
| 49 } | |
| 50 | |
| 48 // Called on the UI thread. Suppress FindBugs warning, since |sClient| is on ly used on the | 51 // Called on the UI thread. Suppress FindBugs warning, since |sClient| is on ly used on the |
| 49 // UI thread. | 52 // UI thread. |
| 50 @SuppressFBWarnings("LI_LAZY_INIT_STATIC") | 53 @SuppressFBWarnings("LI_LAZY_INIT_STATIC") |
| 51 public void destroy() { | 54 public void destroy() { |
| 52 if (sClient != null) { | 55 if (sClient != null) { |
| 53 disconnectFromHost(); | 56 disconnectFromHost(); |
| 54 nativeDestroy(mNativeJniClient); | 57 nativeDestroy(mNativeJniClient); |
| 55 sClient = null; | 58 sClient = null; |
| 56 } | 59 } |
| 57 } | 60 } |
| 58 | 61 |
| 59 /** Returns the current Client instance, or null. */ | 62 /** Returns the current Client instance, or null. */ |
| 60 public static Client getInstance() { | 63 public static Client getInstance() { |
| 61 return sClient; | 64 return sClient; |
| 62 } | 65 } |
| 63 | 66 |
| 64 /** Used for authentication-related UX during connection. Accessed on the UI thread. */ | 67 /** Used for authentication-related UX during connection. Accessed on the UI thread. */ |
| 65 private SessionAuthenticator mAuthenticator; | 68 private SessionAuthenticator mAuthenticator; |
| 66 | 69 |
| 67 /** Whether the native code is attempting a connection. Accessed on the UI t hread. */ | 70 /** Whether the native code is attempting a connection. Accessed on the UI t hread. */ |
| 68 private boolean mConnected; | 71 private boolean mConnected; |
| 69 | 72 |
| 70 /** Notified upon successful connection or disconnection. Accessed on the UI thread. */ | 73 /** Notified upon successful connection or disconnection. Accessed on the UI thread. */ |
| 71 private ConnectionListener mConnectionListener; | 74 private ConnectionListener mConnectionListener; |
| 72 | 75 |
| 73 /** | |
| 74 * Callback invoked on the graphics thread to repaint the desktop. Accessed on the UI and | |
| 75 * graphics threads. | |
| 76 */ | |
| 77 private Runnable mRedrawCallback; | |
| 78 | |
| 79 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and graphics threads. */ | |
| 80 private Bitmap mFrameBitmap; | |
| 81 | |
| 82 /** Protects access to {@link mFrameBitmap}. */ | |
| 83 private final Object mFrameLock = new Object(); | |
| 84 | |
| 85 /** Position of cursor hot-spot. Accessed on the graphics thread. */ | |
| 86 private Point mCursorHotspot = new Point(); | |
| 87 | |
| 88 /** Bitmap holding the cursor shape. Accessed on the graphics thread. */ | |
| 89 private Bitmap mCursorBitmap; | |
| 90 | |
| 91 /** Capability Manager through which capabilities and extensions are handled . */ | 76 /** Capability Manager through which capabilities and extensions are handled . */ |
| 92 private CapabilityManager mCapabilityManager = new CapabilityManager(); | 77 private CapabilityManager mCapabilityManager = new CapabilityManager(); |
| 93 | 78 |
| 94 public CapabilityManager getCapabilityManager() { | 79 public CapabilityManager getCapabilityManager() { |
| 95 return mCapabilityManager; | 80 return mCapabilityManager; |
| 96 } | 81 } |
| 97 | 82 |
| 98 /** Returns whether the client is connected. */ | 83 /** Returns whether the client is connected. */ |
| 99 public boolean isConnected() { | 84 public boolean isConnected() { |
| 100 return mConnected; | 85 return mConnected; |
| 101 } | 86 } |
| 102 | 87 |
| 103 /** Attempts to form a connection to the user-selected host. Called on the U I thread. */ | 88 /** Attempts to form a connection to the user-selected host. Called on the U I thread. */ |
| 104 public void connectToHost(String username, String authToken, String hostJid, | 89 public void connectToHost(String username, String authToken, String hostJid, |
| 105 String hostId, String hostPubkey, SessionAuthenticator authenticator , String flags, | 90 String hostId, String hostPubkey, SessionAuthenticator authenticator , String flags, |
| 106 ConnectionListener listener) { | 91 ConnectionListener listener) { |
| 107 disconnectFromHost(); | 92 disconnectFromHost(); |
| 108 | 93 |
| 109 mConnectionListener = listener; | 94 mConnectionListener = listener; |
| 110 mAuthenticator = authenticator; | 95 mAuthenticator = authenticator; |
| 111 nativeConnect(mNativeJniClient, username, authToken, hostJid, hostId, ho stPubkey, | 96 mDisplay = new Display(); |
| 112 mAuthenticator.getPairingId(hostId), mAuthenticator.getPairingSe cret(hostId), | 97 nativeConnect(mNativeJniClient, mDisplay.getNativePointer(), username, a uthToken, hostJid, |
| 113 mCapabilityManager.getLocalCapabilities(), flags); | 98 hostId, hostPubkey, mAuthenticator.getPairingId(hostId), |
| 99 mAuthenticator.getPairingSecret(hostId), mCapabilityManager.getL ocalCapabilities(), | |
| 100 flags); | |
| 114 mConnected = true; | 101 mConnected = true; |
| 115 } | 102 } |
| 116 | 103 |
| 117 /** Severs the connection and cleans up. Called on the UI thread. */ | 104 /** Severs the connection and cleans up. Called on the UI thread. */ |
| 118 public void disconnectFromHost() { | 105 public void disconnectFromHost() { |
| 119 if (!mConnected) { | 106 if (!mConnected) { |
| 120 return; | 107 return; |
| 121 } | 108 } |
| 122 | 109 |
| 123 mConnectionListener.onConnectionState( | 110 mConnectionListener.onConnectionState( |
| 124 ConnectionListener.State.CLOSED, ConnectionListener.Error.OK); | 111 ConnectionListener.State.CLOSED, ConnectionListener.Error.OK); |
| 125 | 112 |
| 126 disconnectFromHostWithoutNotification(); | 113 disconnectFromHostWithoutNotification(); |
| 127 } | 114 } |
| 128 | 115 |
| 129 /** Same as disconnectFromHost() but without notifying the ConnectionListene r. */ | 116 /** Same as disconnectFromHost() but without notifying the ConnectionListene r. */ |
| 130 private void disconnectFromHostWithoutNotification() { | 117 private void disconnectFromHostWithoutNotification() { |
| 131 if (!mConnected) { | 118 if (!mConnected) { |
| 132 return; | 119 return; |
| 133 } | 120 } |
| 134 | 121 |
| 135 nativeDisconnect(mNativeJniClient); | 122 nativeDisconnect(mNativeJniClient); |
| 136 mConnectionListener = null; | 123 mConnectionListener = null; |
| 137 mConnected = false; | 124 mConnected = false; |
| 138 mCapabilityManager.onHostDisconnect(); | 125 mCapabilityManager.onHostDisconnect(); |
| 139 | 126 |
| 140 // Drop the reference to free the Bitmap for GC. | 127 mDisplay.destroy(); |
| 141 synchronized (mFrameLock) { | |
| 142 mFrameBitmap = null; | |
| 143 } | |
| 144 } | 128 } |
| 145 | 129 |
| 146 /** Called on the UI thread whenever the connection status changes. */ | 130 /** Called on the UI thread whenever the connection status changes. */ |
| 147 @CalledByNative | 131 @CalledByNative |
| 148 void onConnectionState(int stateCode, int errorCode) { | 132 void onConnectionState(int stateCode, int errorCode) { |
| 149 ConnectionListener.State state = ConnectionListener.State.fromValue(stat eCode); | 133 ConnectionListener.State state = ConnectionListener.State.fromValue(stat eCode); |
| 150 ConnectionListener.Error error = ConnectionListener.Error.fromValue(erro rCode); | 134 ConnectionListener.Error error = ConnectionListener.Error.fromValue(erro rCode); |
| 151 mConnectionListener.onConnectionState(state, error); | 135 mConnectionListener.onConnectionState(state, error); |
| 152 if (state == ConnectionListener.State.FAILED || state == ConnectionListe ner.State.CLOSED) { | 136 if (state == ConnectionListener.State.FAILED || state == ConnectionListe ner.State.CLOSED) { |
| 153 // Disconnect from the host here, otherwise the next time connectToH ost() is called, | 137 // Disconnect from the host here, otherwise the next time connectToH ost() is called, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 * lifecycle events. | 229 * lifecycle events. |
| 246 */ | 230 */ |
| 247 public void enableVideoChannel(boolean enable) { | 231 public void enableVideoChannel(boolean enable) { |
| 248 if (!mConnected) { | 232 if (!mConnected) { |
| 249 return; | 233 return; |
| 250 } | 234 } |
| 251 | 235 |
| 252 nativeEnableVideoChannel(mNativeJniClient, enable); | 236 nativeEnableVideoChannel(mNativeJniClient, enable); |
| 253 } | 237 } |
| 254 | 238 |
| 255 /** | |
| 256 * Sets the redraw callback to the provided functor. Provide a value of null whenever the | |
| 257 * window is no longer visible so that we don't continue to draw onto it. Ca lled on the UI | |
| 258 * thread. | |
| 259 */ | |
| 260 public void provideRedrawCallback(Runnable redrawCallback) { | |
| 261 mRedrawCallback = redrawCallback; | |
| 262 } | |
| 263 | |
| 264 /** Forces the native graphics thread to redraw to the canvas. Called on the UI thread. */ | |
| 265 public boolean redrawGraphics() { | |
| 266 if (!mConnected || mRedrawCallback == null) return false; | |
| 267 | |
| 268 nativeScheduleRedraw(mNativeJniClient); | |
| 269 return true; | |
| 270 } | |
| 271 | |
| 272 /** | |
| 273 * Called on the graphics thread to perform the redrawing callback requested by | |
| 274 * {@link #redrawGraphics}. This is a no-op if the window isn't visible (the callback is null). | |
| 275 */ | |
| 276 @CalledByNative | |
| 277 void redrawGraphicsInternal() { | |
| 278 Runnable callback = mRedrawCallback; | |
| 279 if (callback != null) { | |
| 280 callback.run(); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 /** | |
| 285 * Returns a bitmap of the latest video frame. Called on the native graphics thread when | |
| 286 * DesktopView is repainted. | |
| 287 */ | |
| 288 public Bitmap getVideoFrame() { | |
| 289 if (Looper.myLooper() == Looper.getMainLooper()) { | |
| 290 Log.w(TAG, "Canvas being redrawn on UI thread"); | |
| 291 } | |
| 292 | |
| 293 synchronized (mFrameLock) { | |
| 294 return mFrameBitmap; | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 /** | |
| 299 * Set a new video frame. Called on the native graphics thread when a new fr ame is allocated. | |
| 300 */ | |
| 301 @CalledByNative | |
| 302 void setVideoFrame(Bitmap bitmap) { | |
| 303 if (Looper.myLooper() == Looper.getMainLooper()) { | |
| 304 Log.w(TAG, "Video frame updated on UI thread"); | |
| 305 } | |
| 306 | |
| 307 synchronized (mFrameLock) { | |
| 308 mFrameBitmap = bitmap; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 /** | |
| 313 * Creates a new Bitmap to hold video frame pixels. The returned Bitmap is r eferenced by native | |
| 314 * code which writes the decoded frame pixels to it. | |
| 315 */ | |
| 316 @CalledByNative | |
| 317 static Bitmap newBitmap(int width, int height) { | |
| 318 return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | |
| 319 } | |
| 320 | |
| 321 /** | |
| 322 * Updates the cursor shape. This is called on the graphics thread when rece iving a new cursor | |
| 323 * shape from the host. | |
| 324 */ | |
| 325 @CalledByNative | |
| 326 void updateCursorShape(int width, int height, int hotspotX, int hotspotY, By teBuffer buffer) { | |
| 327 mCursorHotspot = new Point(hotspotX, hotspotY); | |
| 328 | |
| 329 int[] data = new int[width * height]; | |
| 330 buffer.order(ByteOrder.LITTLE_ENDIAN); | |
| 331 buffer.asIntBuffer().get(data, 0, data.length); | |
| 332 mCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); | |
| 333 } | |
| 334 | |
| 335 /** Position of cursor hotspot within cursor image. Called on the graphics t hread. */ | |
| 336 public Point getCursorHotspot() { | |
| 337 return mCursorHotspot; | |
| 338 } | |
| 339 | |
| 340 /** Returns the current cursor shape. Called on the graphics thread. */ | |
| 341 public Bitmap getCursorBitmap() { | |
| 342 return mCursorBitmap; | |
| 343 } | |
| 344 | |
| 345 // | 239 // |
| 346 // Third Party Authentication | 240 // Third Party Authentication |
| 347 // | 241 // |
| 348 | 242 |
| 349 /** | 243 /** |
| 350 * Pops up a third party login page to fetch the token required for authenti cation. | 244 * Pops up a third party login page to fetch the token required for authenti cation. |
| 351 */ | 245 */ |
| 352 @CalledByNative | 246 @CalledByNative |
| 353 void fetchThirdPartyToken(String tokenUrl, String clientId, String scope) { | 247 void fetchThirdPartyToken(String tokenUrl, String clientId, String scope) { |
| 354 mAuthenticator.fetchThirdPartyToken(tokenUrl, clientId, scope); | 248 mAuthenticator.fetchThirdPartyToken(tokenUrl, clientId, scope); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 } | 291 } |
| 398 | 292 |
| 399 nativeSendExtensionMessage(mNativeJniClient, type, data); | 293 nativeSendExtensionMessage(mNativeJniClient, type, data); |
| 400 } | 294 } |
| 401 | 295 |
| 402 private native long nativeInit(); | 296 private native long nativeInit(); |
| 403 | 297 |
| 404 private native void nativeDestroy(long nativeJniClient); | 298 private native void nativeDestroy(long nativeJniClient); |
| 405 | 299 |
| 406 /** Performs the native portion of the connection. */ | 300 /** Performs the native portion of the connection. */ |
| 407 private native void nativeConnect(long nativeJniClient, String username, Str ing authToken, | 301 private native void nativeConnect(long nativeJniClient, long nativeJniDispla yHandler, |
| 408 String hostJid, String hostId, String hostPubkey, String pairId, Str ing pairSecret, | 302 String username, String authToken, String hostJid, String hostId, St ring hostPubkey, |
| 409 String capabilities, String flags); | 303 String pairId, String pairSecret, String capabilities, String flags) ; |
| 410 | 304 |
| 411 /** Native implementation of Client.handleAuthenticationResponse(). */ | 305 /** Native implementation of Client.handleAuthenticationResponse(). */ |
| 412 private native void nativeAuthenticationResponse( | 306 private native void nativeAuthenticationResponse( |
| 413 long nativeJniClient, String pin, boolean createPair, String deviceN ame); | 307 long nativeJniClient, String pin, boolean createPair, String deviceN ame); |
| 414 | 308 |
| 415 /** Performs the native portion of the cleanup. */ | 309 /** Performs the native portion of the cleanup. */ |
| 416 private native void nativeDisconnect(long nativeJniClient); | 310 private native void nativeDisconnect(long nativeJniClient); |
| 417 | 311 |
| 418 /** Schedules a redraw on the native graphics thread. */ | |
| 419 private native void nativeScheduleRedraw(long nativeJniClient); | |
| 420 | |
| 421 /** Passes authentication data to the native handling code. */ | 312 /** Passes authentication data to the native handling code. */ |
| 422 private native void nativeOnThirdPartyTokenFetched( | 313 private native void nativeOnThirdPartyTokenFetched( |
| 423 long nativeJniClient, String token, String sharedSecret); | 314 long nativeJniClient, String token, String sharedSecret); |
| 424 | 315 |
| 425 /** Passes mouse information to the native handling code. */ | 316 /** Passes mouse information to the native handling code. */ |
| 426 private native void nativeSendMouseEvent( | 317 private native void nativeSendMouseEvent( |
| 427 long nativeJniClient, int x, int y, int whichButton, boolean buttonD own); | 318 long nativeJniClient, int x, int y, int whichButton, boolean buttonD own); |
| 428 | 319 |
| 429 /** Passes mouse-wheel information to the native handling code. */ | 320 /** Passes mouse-wheel information to the native handling code. */ |
| 430 private native void nativeSendMouseWheelEvent(long nativeJniClient, int delt aX, int deltaY); | 321 private native void nativeSendMouseWheelEvent(long nativeJniClient, int delt aX, int deltaY); |
| 431 | 322 |
| 432 /** Passes key press information to the native handling code. */ | 323 /** Passes key press information to the native handling code. */ |
| 433 private native boolean nativeSendKeyEvent( | 324 private native boolean nativeSendKeyEvent( |
| 434 long nativeJniClient, int scanCode, int keyCode, boolean keyDown); | 325 long nativeJniClient, int scanCode, int keyCode, boolean keyDown); |
| 435 | 326 |
| 436 /** Passes text event information to the native handling code. */ | 327 /** Passes text event information to the native handling code. */ |
| 437 private native void nativeSendTextEvent(long nativeJniClient, String text); | 328 private native void nativeSendTextEvent(long nativeJniClient, String text); |
| 438 | 329 |
| 439 /** Passes touch event information to the native handling code. */ | 330 /** Passes touch event information to the native handling code. */ |
| 440 private native void nativeSendTouchEvent( | 331 private native void nativeSendTouchEvent( |
| 441 long nativeJniClient, int eventType, TouchEventData[] data); | 332 long nativeJniClient, int eventType, TouchEventData[] data); |
| 442 | 333 |
| 443 /** Native implementation of Client.enableVideoChannel() */ | 334 /** Native implementation of Client.enableVideoChannel() */ |
| 444 private native void nativeEnableVideoChannel(long nativeJniClient, boolean e nable); | 335 private native void nativeEnableVideoChannel(long nativeJniClient, boolean e nable); |
| 445 | 336 |
| 446 /** Passes extension message to the native code. */ | 337 /** Passes extension message to the native code. */ |
| 447 private native void nativeSendExtensionMessage(long nativeJniClient, String type, String data); | 338 private native void nativeSendExtensionMessage(long nativeJniClient, String type, String data); |
| 448 } | 339 } |
| OLD | NEW |