Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/jni/Client.java

Issue 1537183002: Refactor Chromoting JNI code to use jni/Client (Java changes only). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Suppress FindBugs warning Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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;
7 import org.chromium.base.annotations.JNINamespace; 12 import org.chromium.base.annotations.JNINamespace;
13 import org.chromium.base.annotations.SuppressFBWarnings;
14 import org.chromium.chromoting.CapabilityManager;
15 import org.chromium.chromoting.SessionAuthenticator;
16
17 import java.nio.ByteBuffer;
18 import java.nio.ByteOrder;
8 19
9 /** 20 /**
10 * Class to manage a client connection to the host. This class controls the life time of the 21 * Class to manage a client connection to the host. This class controls the life time of the
11 * corresponding C++ object which implements the connection. A new object should be created for 22 * corresponding C++ object which implements the connection. A new object should be created for
12 * each connection to the host, so that notifications from a connection are alwa ys sent to the 23 * each connection to the host, so that notifications from a connection are alwa ys sent to the
13 * right object. 24 * right object.
14 */ 25 */
15 @JNINamespace("remoting") 26 @JNINamespace("remoting")
16 public class Client { 27 public class Client {
28 private static final String TAG = "Chromoting";
29
17 // Pointer to the C++ object, cast to a |long|. 30 // Pointer to the C++ object, cast to a |long|.
18 private long mNativeJniClient; 31 private long mNativeJniClient;
19 32
20 public void init() { 33 // The global Client instance (may be null). This needs to be a global singl eton so that the
34 // Client can be passed between Activities.
35 private static Client sClient;
36
37 // Called on the UI thread.
38 public Client() {
39 if (sClient != null) {
40 throw new RuntimeException("Client instance already created.");
41 }
42
43 sClient = this;
21 mNativeJniClient = nativeInit(); 44 mNativeJniClient = nativeInit();
22 } 45 }
23 46
24 private native long nativeInit(); 47 private native long nativeInit();
25 48
49 // Called on the UI thread. Suppress FindBugs warning, since |sClient| is on ly used on the
50 // UI thread.
51 @SuppressFBWarnings("LI_LAZY_INIT_STATIC")
26 public void destroy() { 52 public void destroy() {
27 nativeDestroy(mNativeJniClient); 53 if (sClient != null) {
54 disconnectFromHost();
55 nativeDestroy(mNativeJniClient);
56 sClient = null;
57 }
28 } 58 }
29 59
30 private native void nativeDestroy(long nativeJniClient); 60 private native void nativeDestroy(long nativeJniClient);
61
62 /** Returns the current Client instance, or null. */
63 public static Client getInstance() {
64 return sClient;
65 }
66
67 /** Used for authentication-related UX during connection. Accessed on the UI thread. */
68 private SessionAuthenticator mAuthenticator;
69
70 /** Whether the native code is attempting a connection. Accessed on the UI t hread. */
71 private boolean mConnected;
72
73 /** Notified upon successful connection or disconnection. Accessed on the UI thread. */
74 private ConnectionListener mConnectionListener;
75
76 /**
77 * Callback invoked on the graphics thread to repaint the desktop. Accessed on the UI and
78 * graphics threads.
79 */
80 private Runnable mRedrawCallback;
81
82 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and graphics threads. */
83 private Bitmap mFrameBitmap;
84
85 /** Protects access to {@link mFrameBitmap}. */
86 private final Object mFrameLock = new Object();
87
88 /** Position of cursor hot-spot. Accessed on the graphics thread. */
89 private Point mCursorHotspot = new Point();
90
91 /** Bitmap holding the cursor shape. Accessed on the graphics thread. */
92 private Bitmap mCursorBitmap;
93
94 /** Capability Manager through which capabilities and extensions are handled . */
95 private CapabilityManager mCapabilityManager = new CapabilityManager();
96
97 public CapabilityManager getCapabilityManager() {
98 return mCapabilityManager;
99 }
100
101 /** Returns whether the client is connected. */
102 public boolean isConnected() {
103 return mConnected;
104 }
105
106 /** Attempts to form a connection to the user-selected host. Called on the U I thread. */
107 public void connectToHost(String username, String authToken, String hostJid,
108 String hostId, String hostPubkey, SessionAuthenticator authenticator , String flags,
109 ConnectionListener listener) {
110 disconnectFromHost();
111
112 mConnectionListener = listener;
113 mAuthenticator = authenticator;
114 JniInterface.nativeConnect(username, authToken, hostJid, hostId, hostPub key,
115 mAuthenticator.getPairingId(hostId), mAuthenticator.getPairingSe cret(hostId),
116 mCapabilityManager.getLocalCapabilities(), flags);
117 mConnected = true;
118 }
119
120 /** Severs the connection and cleans up. Called on the UI thread. */
121 public void disconnectFromHost() {
122 if (!mConnected) {
123 return;
124 }
125
126 mConnectionListener.onConnectionState(
127 ConnectionListener.State.CLOSED, ConnectionListener.Error.OK);
128
129 disconnectFromHostWithoutNotification();
130 }
131
132 /** Same as disconnectFromHost() but without notifying the ConnectionListene r. */
133 private void disconnectFromHostWithoutNotification() {
134 if (!mConnected) {
135 return;
136 }
137
138 JniInterface.nativeDisconnect();
139 mConnectionListener = null;
140 mConnected = false;
141 mCapabilityManager.onHostDisconnect();
142
143 // Drop the reference to free the Bitmap for GC.
144 synchronized (mFrameLock) {
145 mFrameBitmap = null;
146 }
147 }
148
149 /** Called by native code whenever the connection status changes. Called on the UI thread. */
150 void onConnectionState(int stateCode, int errorCode) {
151 ConnectionListener.State state = ConnectionListener.State.fromValue(stat eCode);
152 ConnectionListener.Error error = ConnectionListener.Error.fromValue(erro rCode);
153 mConnectionListener.onConnectionState(state, error);
154 if (state == ConnectionListener.State.FAILED || state == ConnectionListe ner.State.CLOSED) {
155 // Disconnect from the host here, otherwise the next time connectToH ost() is called,
156 // it will try to disconnect, triggering an incorrect status notific ation.
157
158 // TODO(lambroslambrou): Connection state notifications for separate sessions should
159 // go to separate Client instances. Once this is true, we can remove this line and
160 // simplify the disconnectFromHost() code.
161 disconnectFromHostWithoutNotification();
162 }
163 }
164
165 /**
166 * Called by JniInterface (from native code) to prompt the user to enter a P IN. Called on the
167 * UI thread.
168 */
169 void displayAuthenticationPrompt(boolean pairingSupported) {
170 mAuthenticator.displayAuthenticationPrompt(pairingSupported);
171 }
172
173 /**
174 * Called by the SessionAuthenticator after the user enters a PIN.
175 * @param pin The entered PIN.
176 * @param createPair Whether to create a new pairing for this client.
177 * @param deviceName The device name to appear in the pairing registry. Only used if createPair
178 * is true.
179 */
180 public void handleAuthenticationResponse(
181 String pin, boolean createPair, String deviceName) {
182 assert mConnected;
183 JniInterface.nativeAuthenticationResponse(pin, createPair, deviceName);
184 }
185
186 /**
187 * Called by JniInterface (from native code), to save newly-received pairing credentials to
188 * permanent storage. Called on the UI thread.
189 */
190 void commitPairingCredentials(String host, String id, String secret) {
191 mAuthenticator.commitPairingCredentials(host, id, secret);
192 }
193
194 /**
195 * Moves the mouse cursor, possibly while clicking the specified (nonnegativ e) button. Called
196 * on the UI thread.
197 */
198 public void sendMouseEvent(int x, int y, int whichButton, boolean buttonDown ) {
199 if (!mConnected) {
200 return;
201 }
202
203 JniInterface.nativeSendMouseEvent(x, y, whichButton, buttonDown);
204 }
205
206 /** Injects a mouse-wheel event with delta values. Called on the UI thread. */
207 public void sendMouseWheelEvent(int deltaX, int deltaY) {
208 if (!mConnected) {
209 return;
210 }
211
212 JniInterface.nativeSendMouseWheelEvent(deltaX, deltaY);
213 }
214
215 /**
216 * Presses or releases the specified key. Called on the UI thread. If scanCo de is not zero then
217 * keyCode is ignored.
218 */
219 public boolean sendKeyEvent(int scanCode, int keyCode, boolean keyDown) {
220 if (!mConnected) {
221 return false;
222 }
223
224 return JniInterface.nativeSendKeyEvent(scanCode, keyCode, keyDown);
225 }
226
227 /** Sends TextEvent to the host. Called on the UI thread. */
228 public void sendTextEvent(String text) {
229 if (!mConnected) {
230 return;
231 }
232
233 JniInterface.nativeSendTextEvent(text);
234 }
235
236 /** Sends an array of TouchEvents to the host. Called on the UI thread. */
237 public void sendTouchEvent(TouchEventData.EventType eventType, TouchEventDat a[] data) {
238 if (!mConnected) {
239 return;
240 }
241
242 JniInterface.nativeSendTouchEvent(eventType.value(), data);
243 }
244
245 /**
246 * Enables or disables the video channel. Called on the UI thread in respons e to Activity
247 * lifecycle events.
248 */
249 public void enableVideoChannel(boolean enable) {
250 if (!mConnected) {
251 return;
252 }
253
254 JniInterface.nativeEnableVideoChannel(enable);
255 }
256
257 /**
258 * Sets the redraw callback to the provided functor. Provide a value of null whenever the
259 * window is no longer visible so that we don't continue to draw onto it. Ca lled on the UI
260 * thread.
261 */
262 public void provideRedrawCallback(Runnable redrawCallback) {
263 mRedrawCallback = redrawCallback;
264 }
265
266 /** Forces the native graphics thread to redraw to the canvas. Called on the UI thread. */
267 public boolean redrawGraphics() {
268 if (!mConnected || mRedrawCallback == null) return false;
269
270 JniInterface.nativeScheduleRedraw();
271 return true;
272 }
273
274 /**
275 * Called by JniInterface to perform the redrawing callback requested by
276 * {@link #redrawGraphics}. This is a no-op if the window isn't visible (the callback is null).
277 * Called on the graphics thread.
278 */
279 void redrawGraphicsInternal() {
280 Runnable callback = mRedrawCallback;
281 if (callback != null) {
282 callback.run();
283 }
284 }
285
286 /**
287 * Returns a bitmap of the latest video frame. Called on the native graphics thread when
288 * DesktopView is repainted.
289 */
290 public Bitmap getVideoFrame() {
291 if (Looper.myLooper() == Looper.getMainLooper()) {
292 Log.w(TAG, "Canvas being redrawn on UI thread");
293 }
294
295 synchronized (mFrameLock) {
296 return mFrameBitmap;
297 }
298 }
299
300 /**
301 * Called by JniInterface (from native code) to set a new video frame. Calle d on the native
302 * graphics thread when a new frame is allocated.
303 */
304 void setVideoFrame(Bitmap bitmap) {
305 if (Looper.myLooper() == Looper.getMainLooper()) {
306 Log.w(TAG, "Video frame updated on UI thread");
307 }
308
309 synchronized (mFrameLock) {
310 mFrameBitmap = bitmap;
311 }
312 }
313
314 /**
315 * Creates a new Bitmap to hold video frame pixels. Called by JniInterface ( from native code),
316 * and the returned Bitmap is referenced by native code which writes the dec oded frame pixels
317 * to it.
318 */
319 static Bitmap newBitmap(int width, int height) {
320 return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
321 }
322
323 /**
324 * Called by JniInterface (from native code) to update the cursor shape. Thi s is called on the
325 * graphics thread when receiving a new cursor shape from the host.
326 */
327 void updateCursorShape(
328 int width, int height, int hotspotX, int hotspotY, ByteBuffer buffer ) {
329 mCursorHotspot = new Point(hotspotX, hotspotY);
330
331 int[] data = new int[width * height];
332 buffer.order(ByteOrder.LITTLE_ENDIAN);
333 buffer.asIntBuffer().get(data, 0, data.length);
334 mCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888);
335 }
336
337 /** Position of cursor hotspot within cursor image. Called on the graphics t hread. */
338 public Point getCursorHotspot() {
339 return mCursorHotspot;
340 }
341
342 /** Returns the current cursor shape. Called on the graphics thread. */
343 public Bitmap getCursorBitmap() {
344 return mCursorBitmap;
345 }
346
347 //
348 // Third Party Authentication
349 //
350
351 /**
352 * Called by JniInterface (from native code), to pop up a third party login page to fetch the
353 * token required for authentication.
354 */
355 void fetchThirdPartyToken(String tokenUrl, String clientId, String scope) {
356 mAuthenticator.fetchThirdPartyToken(tokenUrl, clientId, scope);
357 }
358
359 /**
360 * Called by the SessionAuthenticator to pass the |token| and |sharedSecret| to native code to
361 * continue authentication.
362 */
363 public void onThirdPartyTokenFetched(String token, String sharedSecret) {
364 if (!mConnected) {
365 return;
366 }
367
368 JniInterface.nativeOnThirdPartyTokenFetched(token, sharedSecret);
369 }
370
371 //
372 // Host and Client Capabilities
373 //
374
375 /**
376 * Called by JniInterface (from native code) to set the list of negotiated c apabilities between
377 * host and client. Called on the UI thread.
378 */
379 void setCapabilities(String capabilities) {
380 mCapabilityManager.setNegotiatedCapabilities(capabilities);
381 }
382
383 //
384 // Extension Message Handling
385 //
386
387 /**
388 * Called by JniInterface (from native code), to pass on the deconstructed E xtensionMessage to
389 * the app. Called on the UI thread.
390 */
391 void handleExtensionMessage(String type, String data) {
392 mCapabilityManager.onExtensionMessage(type, data);
393 }
394
395 /** Sends an extension message to the Chromoting host. Called on the UI thre ad. */
396 public void sendExtensionMessage(String type, String data) {
397 if (!mConnected) {
398 return;
399 }
400
401 JniInterface.nativeSendExtensionMessage(type, data);
402 }
31 } 403 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698