Chromium Code Reviews| 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 |