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; |
11 import android.content.DialogInterface; | 11 import android.content.DialogInterface; |
12 import android.content.SharedPreferences; | 12 import android.content.SharedPreferences; |
13 import android.graphics.Bitmap; | 13 import android.graphics.Bitmap; |
14 import android.graphics.Point; | 14 import android.graphics.Point; |
15 import android.os.Looper; | 15 import android.os.Looper; |
16 import android.text.InputType; | 16 import android.text.InputType; |
17 import android.util.Log; | 17 import android.util.Log; |
18 import android.view.KeyEvent; | 18 import android.view.KeyEvent; |
19 import android.view.View; | 19 import android.view.View; |
20 import android.view.inputmethod.EditorInfo; | 20 import android.view.inputmethod.EditorInfo; |
21 import android.widget.CheckBox; | 21 import android.widget.CheckBox; |
22 import android.widget.TextView; | 22 import android.widget.TextView; |
23 import android.widget.Toast; | 23 import android.widget.Toast; |
24 | 24 |
25 import org.chromium.base.CalledByNative; | |
26 import org.chromium.base.JNINamespace; | |
25 import org.chromium.chromoting.R; | 27 import org.chromium.chromoting.R; |
26 | 28 |
27 import java.nio.ByteBuffer; | 29 import java.nio.ByteBuffer; |
28 import java.nio.ByteOrder; | 30 import java.nio.ByteOrder; |
29 | 31 |
30 /** | 32 /** |
31 * Initializes the Chromium remoting library, and provides JNI calls into it. | 33 * Initializes the Chromium remoting library, and provides JNI calls into it. |
32 * All interaction with the native code is centralized in this class. | 34 * All interaction with the native code is centralized in this class. |
33 */ | 35 */ |
36 @JNINamespace("remoting") | |
34 public class JniInterface { | 37 public class JniInterface { |
35 /** The status code indicating successful connection. */ | 38 /** The status code indicating successful connection. */ |
36 private static final int SUCCESSFUL_CONNECTION = 3; | 39 private static final int SUCCESSFUL_CONNECTION = 3; |
37 | 40 |
38 /** The application context. */ | 41 /** The application context. */ |
39 private static Activity sContext = null; | 42 private static Activity sContext = null; |
40 | 43 |
41 /* | 44 /* |
42 * Library-loading state machine. | 45 * Library-loading state machine. |
43 */ | 46 */ |
44 /** Whether we've already loaded the library. */ | 47 /** Whether we've already loaded the library. */ |
45 private static boolean sLoaded = false; | 48 private static boolean sLoaded = false; |
46 | 49 |
47 /** | 50 /** |
48 * To be called once from the main Activity. Any subsequent calls will updat e the application | 51 * To be called once from the main Activity. Any subsequent calls will updat e the application |
49 * context, but not reload the library. This is useful e.g. when the activit y is closed and the | 52 * context, but not reload the library. This is useful e.g. when the activit y is closed and the |
50 * user later wants to return to the application. | 53 * user later wants to return to the application. |
51 */ | 54 */ |
52 public static void loadLibrary(Activity context) { | 55 public static void loadLibrary(Activity context) { |
53 sContext = context; | 56 sContext = context; |
54 | 57 |
55 synchronized(JniInterface.class) { | 58 synchronized(JniInterface.class) { |
56 if (sLoaded) return; | 59 if (sLoaded) return; |
57 } | 60 } |
58 | 61 |
59 System.loadLibrary("remoting_client_jni"); | 62 System.loadLibrary("remoting_client_jni"); |
63 | |
64 Log.e("jni", "*** 1"); | |
65 | |
60 loadNative(context); | 66 loadNative(context); |
61 sLoaded = true; | 67 sLoaded = true; |
62 } | 68 } |
63 | 69 |
64 /** Performs the native portion of the initialization. */ | 70 /** Performs the native portion of the initialization. */ |
65 private static native void loadNative(Context context); | 71 private static native void loadNative(Context context); |
digit1
2013/10/19 09:50:04
Hint: You must call this function "nativeLoadNativ
Lambros
2013/10/23 17:35:23
Done.
| |
66 | 72 |
67 /* | 73 /* |
68 * API/OAuth2 keys access. | 74 * API/OAuth2 keys access. |
69 */ | 75 */ |
70 public static native String getApiKey(); | 76 public static native String getApiKey(); |
71 public static native String getClientId(); | 77 public static native String getClientId(); |
72 public static native String getClientSecret(); | 78 public static native String getClientSecret(); |
73 | 79 |
74 /* | 80 /* |
75 * Connection-initiating state machine. | 81 * Connection-initiating state machine. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 /** Lock to protect the frame bitmap reference. */ | 153 /** Lock to protect the frame bitmap reference. */ |
148 private static final Object sFrameLock = new Object(); | 154 private static final Object sFrameLock = new Object(); |
149 | 155 |
150 /** Position of cursor hot-spot. */ | 156 /** Position of cursor hot-spot. */ |
151 private static Point sCursorHotspot = new Point(); | 157 private static Point sCursorHotspot = new Point(); |
152 | 158 |
153 /** Bitmap holding the cursor shape. */ | 159 /** Bitmap holding the cursor shape. */ |
154 private static Bitmap sCursorBitmap = null; | 160 private static Bitmap sCursorBitmap = null; |
155 | 161 |
156 /** Reports whenever the connection status changes. */ | 162 /** Reports whenever the connection status changes. */ |
163 @CalledByNative | |
157 private static void reportConnectionStatus(int state, int error) { | 164 private static void reportConnectionStatus(int state, int error) { |
158 if (state < SUCCESSFUL_CONNECTION && error == 0) { | 165 if (state < SUCCESSFUL_CONNECTION && error == 0) { |
159 // The connection is still being established, so we'll report the cu rrent progress. | 166 // The connection is still being established, so we'll report the cu rrent progress. |
160 synchronized (JniInterface.class) { | 167 synchronized (JniInterface.class) { |
161 if (sProgressIndicator == null) { | 168 if (sProgressIndicator == null) { |
162 sProgressIndicator = ProgressDialog.show(sContext, sContext. | 169 sProgressIndicator = ProgressDialog.show(sContext, sContext. |
163 getString(R.string.progress_title), sContext.getReso urces(). | 170 getString(R.string.progress_title), sContext.getReso urces(). |
164 getStringArray(R.array.protoc_states)[state], true, true, | 171 getStringArray(R.array.protoc_states)[state], true, true, |
165 new DialogInterface.OnCancelListener() { | 172 new DialogInterface.OnCancelListener() { |
166 @Override | 173 @Override |
(...skipping 27 matching lines...) Expand all Loading... | |
194 } else { | 201 } else { |
195 Toast.makeText(sContext, sContext.getResources().getStringArray( | 202 Toast.makeText(sContext, sContext.getResources().getStringArray( |
196 R.array.protoc_states)[state] + (error == 0 ? "" : ": " + | 203 R.array.protoc_states)[state] + (error == 0 ? "" : ": " + |
197 sContext.getResources().getStringArray(R.array.protoc_er rors)[error]), | 204 sContext.getResources().getStringArray(R.array.protoc_er rors)[error]), |
198 Toast.LENGTH_LONG).show(); | 205 Toast.LENGTH_LONG).show(); |
199 } | 206 } |
200 } | 207 } |
201 } | 208 } |
202 | 209 |
203 /** Prompts the user to enter a PIN. */ | 210 /** Prompts the user to enter a PIN. */ |
211 @CalledByNative | |
204 private static void displayAuthenticationPrompt(boolean pairingSupported) { | 212 private static void displayAuthenticationPrompt(boolean pairingSupported) { |
205 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); | 213 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); |
206 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); | 214 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); |
207 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); | 215 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); |
208 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); | 216 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); |
209 | 217 |
210 final View pinEntry = sContext.getLayoutInflater().inflate(R.layout.pin_ dialog, null); | 218 final View pinEntry = sContext.getLayoutInflater().inflate(R.layout.pin_ dialog, null); |
211 pinPrompt.setView(pinEntry); | 219 pinPrompt.setView(pinEntry); |
212 | 220 |
213 final TextView pinTextView = (TextView)pinEntry.findViewById(R.id.pin_di alog_text); | 221 final TextView pinTextView = (TextView)pinEntry.findViewById(R.id.pin_di alog_text); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 public void onCancel(DialogInterface dialog) { | 267 public void onCancel(DialogInterface dialog) { |
260 // The user backed out of the dialog (equivalent to the cancel button). | 268 // The user backed out of the dialog (equivalent to the cancel button). |
261 pinDialog.getButton(AlertDialog.BUTTON_NEGATIVE).perform Click(); | 269 pinDialog.getButton(AlertDialog.BUTTON_NEGATIVE).perform Click(); |
262 } | 270 } |
263 }); | 271 }); |
264 | 272 |
265 pinDialog.show(); | 273 pinDialog.show(); |
266 } | 274 } |
267 | 275 |
268 /** Saves newly-received pairing credentials to permanent storage. */ | 276 /** Saves newly-received pairing credentials to permanent storage. */ |
277 @CalledByNative | |
269 private static void commitPairingCredentials(String host, byte[] id, byte[] secret) { | 278 private static void commitPairingCredentials(String host, byte[] id, byte[] secret) { |
270 synchronized (sContext) { | 279 synchronized (sContext) { |
271 sContext.getPreferences(Activity.MODE_PRIVATE).edit(). | 280 sContext.getPreferences(Activity.MODE_PRIVATE).edit(). |
272 putString(host + "_id", new String(id)). | 281 putString(host + "_id", new String(id)). |
273 putString(host + "_secret", new String(secret)). | 282 putString(host + "_secret", new String(secret)). |
274 apply(); | 283 apply(); |
275 } | 284 } |
276 } | 285 } |
277 | 286 |
278 /** | 287 /** |
279 * Sets the redraw callback to the provided functor. Provide a value of null whenever the | 288 * Sets the redraw callback to the provided functor. Provide a value of null whenever the |
280 * window is no longer visible so that we don't continue to draw onto it. | 289 * window is no longer visible so that we don't continue to draw onto it. |
281 */ | 290 */ |
282 public static void provideRedrawCallback(Runnable redrawCallback) { | 291 public static void provideRedrawCallback(Runnable redrawCallback) { |
283 sRedrawCallback = redrawCallback; | 292 sRedrawCallback = redrawCallback; |
284 } | 293 } |
285 | 294 |
286 /** Forces the native graphics thread to redraw to the canvas. */ | 295 /** Forces the native graphics thread to redraw to the canvas. */ |
287 public static boolean redrawGraphics() { | 296 public static boolean redrawGraphics() { |
288 synchronized(JniInterface.class) { | 297 synchronized(JniInterface.class) { |
289 if (!sConnected || sRedrawCallback == null) return false; | 298 if (!sConnected || sRedrawCallback == null) return false; |
290 } | 299 } |
291 | 300 |
292 scheduleRedrawNative(); | 301 scheduleRedrawNative(); |
293 return true; | 302 return true; |
294 } | 303 } |
295 | 304 |
296 /** Performs the redrawing callback. This is a no-op if the window isn't vis ible. */ | 305 /** Performs the redrawing callback. This is a no-op if the window isn't vis ible. */ |
306 @CalledByNative | |
297 private static void redrawGraphicsInternal() { | 307 private static void redrawGraphicsInternal() { |
298 if (sRedrawCallback != null) | 308 if (sRedrawCallback != null) { |
299 sRedrawCallback.run(); | 309 sRedrawCallback.run(); |
310 } | |
300 } | 311 } |
301 | 312 |
302 /** | 313 /** |
303 * Returns a bitmap of the latest video frame. Called on the native graphics thread when | 314 * Returns a bitmap of the latest video frame. Called on the native graphics thread when |
304 * DesktopView is repainted. | 315 * DesktopView is repainted. |
305 */ | 316 */ |
306 public static Bitmap getVideoFrame() { | 317 public static Bitmap getVideoFrame() { |
307 if (Looper.myLooper() == Looper.getMainLooper()) { | 318 if (Looper.myLooper() == Looper.getMainLooper()) { |
308 Log.w("jniiface", "Canvas being redrawn on UI thread"); | 319 Log.w("jniiface", "Canvas being redrawn on UI thread"); |
309 } | 320 } |
310 | 321 |
311 if (!sConnected) { | 322 if (!sConnected) { |
312 return null; | 323 return null; |
313 } | 324 } |
314 | 325 |
315 synchronized (sFrameLock) { | 326 synchronized (sFrameLock) { |
316 return sFrameBitmap; | 327 return sFrameBitmap; |
317 } | 328 } |
318 } | 329 } |
319 | 330 |
320 /** | 331 /** |
321 * Sets a new video frame. Called from native code on the native graphics th read when a new | 332 * Sets a new video frame. Called on the native graphics thread when a new f rame is allocated. |
322 * frame is allocated. | |
323 */ | 333 */ |
334 @CalledByNative | |
324 private static void setVideoFrame(Bitmap bitmap) { | 335 private static void setVideoFrame(Bitmap bitmap) { |
325 if (Looper.myLooper() == Looper.getMainLooper()) { | 336 if (Looper.myLooper() == Looper.getMainLooper()) { |
326 Log.w("jniiface", "Video frame updated on UI thread"); | 337 Log.w("jniiface", "Video frame updated on UI thread"); |
327 } | 338 } |
328 | 339 |
329 synchronized (sFrameLock) { | 340 synchronized (sFrameLock) { |
330 sFrameBitmap = bitmap; | 341 sFrameBitmap = bitmap; |
331 } | 342 } |
332 } | 343 } |
333 | 344 |
334 /** | 345 /** |
335 * Creates a new Bitmap to hold video frame pixels. Called by native code wh ich stores a global | 346 * Creates a new Bitmap to hold video frame pixels. Called by native code wh ich stores a global |
336 * reference to the Bitmap and writes the decoded frame pixels to it. | 347 * reference to the Bitmap and writes the decoded frame pixels to it. |
337 */ | 348 */ |
349 @CalledByNative | |
338 private static Bitmap newBitmap(int width, int height) { | 350 private static Bitmap newBitmap(int width, int height) { |
339 return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | 351 return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); |
340 } | 352 } |
341 | 353 |
342 /** | 354 /** |
343 * Updates the cursor shape. This is called from native code on the graphics thread when | 355 * Updates the cursor shape. This is called on the graphics thread when rece iving a new cursor |
344 * receiving a new cursor shape from the host. | 356 * shape from the host. |
345 */ | 357 */ |
358 @CalledByNative | |
346 public static void updateCursorShape(int width, int height, int hotspotX, in t hotspotY, | 359 public static void updateCursorShape(int width, int height, int hotspotX, in t hotspotY, |
347 ByteBuffer buffer) { | 360 ByteBuffer buffer) { |
348 sCursorHotspot = new Point(hotspotX, hotspotY); | 361 sCursorHotspot = new Point(hotspotX, hotspotY); |
349 | 362 |
350 int[] data = new int[width * height]; | 363 int[] data = new int[width * height]; |
351 buffer.order(ByteOrder.LITTLE_ENDIAN); | 364 buffer.order(ByteOrder.LITTLE_ENDIAN); |
352 buffer.asIntBuffer().get(data, 0, data.length); | 365 buffer.asIntBuffer().get(data, 0, data.length); |
353 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); | 366 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A RGB_8888); |
354 } | 367 } |
355 | 368 |
(...skipping 20 matching lines...) Expand all Loading... | |
376 | 389 |
377 /** Schedules a redraw on the native graphics thread. */ | 390 /** Schedules a redraw on the native graphics thread. */ |
378 private static native void scheduleRedrawNative(); | 391 private static native void scheduleRedrawNative(); |
379 | 392 |
380 /** Passes mouse information to the native handling code. */ | 393 /** Passes mouse information to the native handling code. */ |
381 private static native void mouseActionNative(int x, int y, int whichButton, boolean buttonDown); | 394 private static native void mouseActionNative(int x, int y, int whichButton, boolean buttonDown); |
382 | 395 |
383 /** Passes key press information to the native handling code. */ | 396 /** Passes key press information to the native handling code. */ |
384 private static native void keyboardActionNative(int keyCode, boolean keyDown ); | 397 private static native void keyboardActionNative(int keyCode, boolean keyDown ); |
385 } | 398 } |
OLD | NEW |