OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.app.Activity; | 7 import android.app.Activity; |
8 import android.app.AlertDialog; | 8 import android.app.AlertDialog; |
9 import android.app.ProgressDialog; | 9 import android.app.ProgressDialog; |
10 import android.content.Context; | 10 import android.content.Context; |
(...skipping 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 /** | 32 /** |
33 * Initializes the Chromium remoting library, and provides JNI calls into it. | 33 * Initializes the Chromium remoting library, and provides JNI calls into it. |
34 * All interaction with the native code is centralized in this class. | 34 * All interaction with the native code is centralized in this class. |
35 */ | 35 */ |
36 @JNINamespace("remoting") | 36 @JNINamespace("remoting") |
37 public class JniInterface { | 37 public class JniInterface { |
38 /** The status code indicating successful connection. */ | 38 /** The status code indicating successful connection. */ |
39 private static final int SUCCESSFUL_CONNECTION = 3; | 39 private static final int SUCCESSFUL_CONNECTION = 3; |
40 | 40 |
41 /** The application context. */ | |
42 private static Activity sContext = null; | |
43 | |
44 /* | 41 /* |
45 * Library-loading state machine. | 42 * Library-loading state machine. |
46 */ | 43 */ |
47 /** Whether we've already loaded the library. */ | 44 /** Whether we've already loaded the library. */ |
48 private static boolean sLoaded = false; | 45 private static boolean sLoaded = false; |
49 | 46 |
47 /** The application context. */ | |
48 private static Activity sContext = null; | |
49 | |
50 /* | |
51 * Connection-initiating state machine. | |
52 */ | |
53 /** Whether the native code is attempting a connection. */ | |
54 private static boolean sConnected = false; | |
55 | |
56 /** Callback to signal upon successful connection. */ | |
57 private static Runnable sSuccessCallback = null; | |
58 | |
59 /** Dialog for reporting connection progress. */ | |
60 private static ProgressDialog sProgressIndicator = null; | |
61 | |
62 /** Callback to signal whenever we need to redraw. */ | |
63 private static Runnable sRedrawCallback = null; | |
64 | |
65 /** Bitmap holding a copy of the latest video frame. */ | |
66 private static Bitmap sFrameBitmap = null; | |
67 | |
68 /** Lock to protect the frame bitmap reference. */ | |
69 private static final Object sFrameLock = new Object(); | |
70 | |
71 /** Position of cursor hot-spot. */ | |
72 private static Point sCursorHotspot = new Point(); | |
73 | |
74 /** Bitmap holding the cursor shape. */ | |
75 private static Bitmap sCursorBitmap = null; | |
76 | |
50 /** | 77 /** |
51 * To be called once from the main Activity. Any subsequent calls will updat e the application | 78 * To be called once from the main Activity. Any subsequent calls will updat e the application |
52 * context, but not reload the library. This is useful e.g. when the activit y is closed and the | 79 * context, but not reload the library. This is useful e.g. when the activit y is closed and the |
53 * user later wants to return to the application. | 80 * user later wants to return to the application. |
54 */ | 81 */ |
55 public static void loadLibrary(Activity context) { | 82 public static void loadLibrary(Activity context) { |
56 sContext = context; | 83 sContext = context; |
57 | 84 |
58 synchronized(JniInterface.class) { | 85 synchronized(JniInterface.class) { |
59 if (sLoaded) return; | 86 if (sLoaded) return; |
60 } | 87 } |
61 | 88 |
62 System.loadLibrary("remoting_client_jni"); | 89 System.loadLibrary("remoting_client_jni"); |
63 | 90 |
64 nativeLoadNative(context); | 91 nativeLoadNative(context); |
65 sLoaded = true; | 92 sLoaded = true; |
66 } | 93 } |
67 | 94 |
68 /** Performs the native portion of the initialization. */ | 95 /** Performs the native portion of the initialization. */ |
69 private static native void nativeLoadNative(Context context); | 96 private static native void nativeLoadNative(Context context); |
70 | 97 |
71 /* | 98 /* |
72 * API/OAuth2 keys access. | 99 * API/OAuth2 keys access. |
73 */ | 100 */ |
74 public static native String nativeGetApiKey(); | 101 public static native String nativeGetApiKey(); |
75 public static native String nativeGetClientId(); | 102 public static native String nativeGetClientId(); |
76 public static native String nativeGetClientSecret(); | 103 public static native String nativeGetClientSecret(); |
77 | 104 |
78 /* | |
79 * Connection-initiating state machine. | |
80 */ | |
81 /** Whether the native code is attempting a connection. */ | |
82 private static boolean sConnected = false; | |
83 | |
84 /** Callback to signal upon successful connection. */ | |
85 private static Runnable sSuccessCallback = null; | |
86 | |
87 /** Dialog for reporting connection progress. */ | |
88 private static ProgressDialog sProgressIndicator = null; | |
89 | |
90 /** Attempts to form a connection to the user-selected host. */ | 105 /** Attempts to form a connection to the user-selected host. */ |
91 public static void connectToHost(String username, String authToken, | 106 public static void connectToHost(String username, String authToken, |
92 String hostJid, String hostId, String hostPubkey, Runnable successCa llback) { | 107 String hostJid, String hostId, String hostPubkey, Runnable successCa llback) { |
93 synchronized(JniInterface.class) { | 108 synchronized(JniInterface.class) { |
94 if (!sLoaded) return; | 109 if (!sLoaded) return; |
95 | 110 |
96 if (sConnected) { | 111 if (sConnected) { |
97 disconnectFromHost(); | 112 disconnectFromHost(); |
98 } | 113 } |
99 } | 114 } |
100 | 115 |
101 sSuccessCallback = successCallback; | 116 sSuccessCallback = successCallback; |
102 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE) ; | 117 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE) ; |
103 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, | 118 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, |
104 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_ secret", "")); | 119 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_ secret", "")); |
105 sConnected = true; | 120 sConnected = true; |
106 } | 121 } |
107 | 122 |
123 /** Performs the native portion of the connection. */ | |
124 private static native void nativeConnect(String username, String authToken, String hostJid, | |
125 String hostId, String hostPubkey, String pairId, String pairSecret); | |
126 | |
108 /** Severs the connection and cleans up. */ | 127 /** Severs the connection and cleans up. */ |
109 public static void disconnectFromHost() { | 128 public static void disconnectFromHost() { |
110 synchronized(JniInterface.class) { | 129 synchronized(JniInterface.class) { |
111 if (!sLoaded || !sConnected) return; | 130 if (!sLoaded || !sConnected) return; |
112 | 131 |
113 if (sProgressIndicator != null) { | 132 if (sProgressIndicator != null) { |
114 sProgressIndicator.dismiss(); | 133 sProgressIndicator.dismiss(); |
115 sProgressIndicator = null; | 134 sProgressIndicator = null; |
116 } | 135 } |
117 } | 136 } |
118 | 137 |
119 nativeDisconnect(); | 138 nativeDisconnect(); |
120 sSuccessCallback = null; | 139 sSuccessCallback = null; |
121 sConnected = false; | 140 sConnected = false; |
122 | 141 |
123 // Drop the reference to free the Bitmap for GC. | 142 // Drop the reference to free the Bitmap for GC. |
124 synchronized (sFrameLock) { | 143 synchronized (sFrameLock) { |
125 sFrameBitmap = null; | 144 sFrameBitmap = null; |
126 } | 145 } |
127 } | 146 } |
128 | 147 |
129 /** Performs the native portion of the connection. */ | |
130 private static native void nativeConnect(String username, String authToken, String hostJid, | |
131 String hostId, String hostPubkey, String pairId, String pairSecret); | |
132 | |
133 /** Performs the native portion of the cleanup. */ | 148 /** Performs the native portion of the cleanup. */ |
134 private static native void nativeDisconnect(); | 149 private static native void nativeDisconnect(); |
135 | 150 |
136 /** Position of cursor hotspot within cursor image. */ | |
137 public static Point getCursorHotspot() { return sCursorHotspot; } | |
138 | |
139 /** Returns the current cursor shape. */ | |
140 public static Bitmap getCursorBitmap() { return sCursorBitmap; } | |
141 | |
142 /* | |
143 * Entry points *from* the native code. | |
144 */ | |
Lambros
2013/11/15 19:36:28
I removed this comment, which accounts for the mis
| |
145 /** Callback to signal whenever we need to redraw. */ | |
146 private static Runnable sRedrawCallback = null; | |
147 | |
148 /** Bitmap holding a copy of the latest video frame. */ | |
149 private static Bitmap sFrameBitmap = null; | |
150 | |
151 /** Lock to protect the frame bitmap reference. */ | |
152 private static final Object sFrameLock = new Object(); | |
153 | |
154 /** Position of cursor hot-spot. */ | |
155 private static Point sCursorHotspot = new Point(); | |
156 | |
157 /** Bitmap holding the cursor shape. */ | |
158 private static Bitmap sCursorBitmap = null; | |
159 | |
160 /** Reports whenever the connection status changes. */ | 151 /** Reports whenever the connection status changes. */ |
161 @CalledByNative | 152 @CalledByNative |
162 private static void reportConnectionStatus(int state, int error) { | 153 private static void reportConnectionStatus(int state, int error) { |
163 if (state < SUCCESSFUL_CONNECTION && error == 0) { | 154 if (state < SUCCESSFUL_CONNECTION && error == 0) { |
164 // The connection is still being established, so we'll report the cu rrent progress. | 155 // The connection is still being established, so we'll report the cu rrent progress. |
165 synchronized (JniInterface.class) { | 156 synchronized (JniInterface.class) { |
166 if (sProgressIndicator == null) { | 157 if (sProgressIndicator == null) { |
167 sProgressIndicator = ProgressDialog.show(sContext, sContext. | 158 sProgressIndicator = ProgressDialog.show(sContext, sContext. |
168 getString(R.string.progress_title), sContext.getReso urces(). | 159 getString(R.string.progress_title), sContext.getReso urces(). |
169 getStringArray(R.array.protoc_states)[state], true, true, | 160 getStringArray(R.array.protoc_states)[state], true, true, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 @Override | 255 @Override |
265 public void onCancel(DialogInterface dialog) { | 256 public void onCancel(DialogInterface dialog) { |
266 // The user backed out of the dialog (equivalent to the cancel button). | 257 // The user backed out of the dialog (equivalent to the cancel button). |
267 pinDialog.getButton(AlertDialog.BUTTON_NEGATIVE).perform Click(); | 258 pinDialog.getButton(AlertDialog.BUTTON_NEGATIVE).perform Click(); |
268 } | 259 } |
269 }); | 260 }); |
270 | 261 |
271 pinDialog.show(); | 262 pinDialog.show(); |
272 } | 263 } |
273 | 264 |
265 /** Performs the native response to the user's PIN. */ | |
266 private static native void nativeAuthenticationResponse(String pin, boolean createPair); | |
267 | |
274 /** Saves newly-received pairing credentials to permanent storage. */ | 268 /** Saves newly-received pairing credentials to permanent storage. */ |
275 @CalledByNative | 269 @CalledByNative |
276 private static void commitPairingCredentials(String host, byte[] id, byte[] secret) { | 270 private static void commitPairingCredentials(String host, byte[] id, byte[] secret) { |
277 synchronized (sContext) { | 271 synchronized (sContext) { |
278 sContext.getPreferences(Activity.MODE_PRIVATE).edit(). | 272 sContext.getPreferences(Activity.MODE_PRIVATE).edit(). |
279 putString(host + "_id", new String(id)). | 273 putString(host + "_id", new String(id)). |
280 putString(host + "_secret", new String(secret)). | 274 putString(host + "_secret", new String(secret)). |
281 apply(); | 275 apply(); |
282 } | 276 } |
283 } | 277 } |
284 | 278 |
279 /** Moves the mouse cursor, possibly while clicking the specified (nonnegati ve) button. */ | |
280 public static void mouseAction(int x, int y, int whichButton, boolean button Down) { | |
281 if (!sConnected) { | |
282 return; | |
283 } | |
284 | |
285 nativeMouseAction(x, y, whichButton, buttonDown); | |
286 } | |
287 | |
288 /** Passes mouse information to the native handling code. */ | |
289 private static native void nativeMouseAction(int x, int y, int whichButton, boolean buttonDown); | |
290 | |
291 /** Presses and releases the specified (nonnegative) key. */ | |
292 public static void keyboardAction(int keyCode, boolean keyDown) { | |
293 if (!sConnected) { | |
294 return; | |
295 } | |
296 | |
297 nativeKeyboardAction(keyCode, keyDown); | |
298 } | |
299 | |
300 /** Passes key press information to the native handling code. */ | |
301 private static native void nativeKeyboardAction(int keyCode, boolean keyDown ); | |
302 | |
285 /** | 303 /** |
286 * Sets the redraw callback to the provided functor. Provide a value of null whenever the | 304 * Sets the redraw callback to the provided functor. Provide a value of null whenever the |
287 * window is no longer visible so that we don't continue to draw onto it. | 305 * window is no longer visible so that we don't continue to draw onto it. |
288 */ | 306 */ |
289 public static void provideRedrawCallback(Runnable redrawCallback) { | 307 public static void provideRedrawCallback(Runnable redrawCallback) { |
290 sRedrawCallback = redrawCallback; | 308 sRedrawCallback = redrawCallback; |
291 } | 309 } |
292 | 310 |
293 /** Forces the native graphics thread to redraw to the canvas. */ | 311 /** Forces the native graphics thread to redraw to the canvas. */ |
294 public static boolean redrawGraphics() { | 312 public static boolean redrawGraphics() { |
295 synchronized(JniInterface.class) { | 313 synchronized(JniInterface.class) { |
296 if (!sConnected || sRedrawCallback == null) return false; | 314 if (!sConnected || sRedrawCallback == null) return false; |
297 } | 315 } |
298 | 316 |
299 nativeScheduleRedraw(); | 317 nativeScheduleRedraw(); |
300 return true; | 318 return true; |
301 } | 319 } |
302 | 320 |
321 /** Schedules a redraw on the native graphics thread. */ | |
322 private static native void nativeScheduleRedraw(); | |
323 | |
303 /** Performs the redrawing callback. This is a no-op if the window isn't vis ible. */ | 324 /** Performs the redrawing callback. This is a no-op if the window isn't vis ible. */ |
304 @CalledByNative | 325 @CalledByNative |
305 private static void redrawGraphicsInternal() { | 326 private static void redrawGraphicsInternal() { |
306 if (sRedrawCallback != null) { | 327 if (sRedrawCallback != null) { |
307 sRedrawCallback.run(); | 328 sRedrawCallback.run(); |
308 } | 329 } |
309 } | 330 } |
310 | 331 |
311 /** | 332 /** |
312 * Returns a bitmap of the latest video frame. Called on the native graphics thread when | 333 * Returns a bitmap of the latest video frame. Called on the native graphics thread when |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 public static void updateCursorShape(int width, int height, int hotspotX, in t hotspotY, | 378 public static void updateCursorShape(int width, int height, int hotspotX, in t hotspotY, |
358 ByteBuffer buffer) { | 379 ByteBuffer buffer) { |
359 sCursorHotspot = new Point(hotspotX, hotspotY); | 380 sCursorHotspot = new Point(hotspotX, hotspotY); |
360 | 381 |
361 int[] data = new int[width * height]; | 382 int[] data = new int[width * height]; |
362 buffer.order(ByteOrder.LITTLE_ENDIAN); | 383 buffer.order(ByteOrder.LITTLE_ENDIAN); |
363 buffer.asIntBuffer().get(data, 0, data.length); | 384 buffer.asIntBuffer().get(data, 0, data.length); |
364 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); | 385 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); |
365 } | 386 } |
366 | 387 |
367 /** Moves the mouse cursor, possibly while clicking the specified (nonnegati ve) button. */ | 388 /** Position of cursor hotspot within cursor image. */ |
368 public static void mouseAction(int x, int y, int whichButton, boolean button Down) { | 389 public static Point getCursorHotspot() { return sCursorHotspot; } |
369 if (!sConnected) { | |
370 return; | |
371 } | |
372 | 390 |
373 nativeMouseAction(x, y, whichButton, buttonDown); | 391 /** Returns the current cursor shape. */ |
374 } | 392 public static Bitmap getCursorBitmap() { return sCursorBitmap; } |
375 | |
376 /** Presses and releases the specified (nonnegative) key. */ | |
377 public static void keyboardAction(int keyCode, boolean keyDown) { | |
378 if (!sConnected) { | |
379 return; | |
380 } | |
381 | |
382 nativeKeyboardAction(keyCode, keyDown); | |
383 } | |
384 | |
385 /** Performs the native response to the user's PIN. */ | |
386 private static native void nativeAuthenticationResponse(String pin, boolean createPair); | |
387 | |
388 /** Schedules a redraw on the native graphics thread. */ | |
389 private static native void nativeScheduleRedraw(); | |
390 | |
391 /** Passes mouse information to the native handling code. */ | |
392 private static native void nativeMouseAction(int x, int y, int whichButton, boolean buttonDown); | |
393 | |
394 /** Passes key press information to the native handling code. */ | |
395 private static native void nativeKeyboardAction(int keyCode, boolean keyDown ); | |
396 } | 393 } |
OLD | NEW |