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; | |
10 import android.content.Context; | 9 import android.content.Context; |
11 import android.content.DialogInterface; | 10 import android.content.DialogInterface; |
12 import android.content.SharedPreferences; | 11 import android.content.SharedPreferences; |
13 import android.graphics.Bitmap; | 12 import android.graphics.Bitmap; |
14 import android.graphics.Point; | 13 import android.graphics.Point; |
15 import android.os.Looper; | 14 import android.os.Looper; |
16 import android.util.Log; | 15 import android.util.Log; |
17 import android.view.KeyEvent; | 16 import android.view.KeyEvent; |
18 import android.view.View; | 17 import android.view.View; |
19 import android.widget.CheckBox; | 18 import android.widget.CheckBox; |
20 import android.widget.TextView; | 19 import android.widget.TextView; |
21 import android.widget.Toast; | 20 import android.widget.Toast; |
22 | 21 |
23 import org.chromium.base.CalledByNative; | 22 import org.chromium.base.CalledByNative; |
24 import org.chromium.base.JNINamespace; | 23 import org.chromium.base.JNINamespace; |
25 import org.chromium.chromoting.R; | 24 import org.chromium.chromoting.R; |
26 | 25 |
27 import java.nio.ByteBuffer; | 26 import java.nio.ByteBuffer; |
28 import java.nio.ByteOrder; | 27 import java.nio.ByteOrder; |
29 | 28 |
30 /** | 29 /** |
31 * Initializes the Chromium remoting library, and provides JNI calls into it. | 30 * Initializes the Chromium remoting library, and provides JNI calls into it. |
32 * All interaction with the native code is centralized in this class. | 31 * All interaction with the native code is centralized in this class. |
33 */ | 32 */ |
34 @JNINamespace("remoting") | 33 @JNINamespace("remoting") |
35 public class JniInterface { | 34 public class JniInterface { |
36 /** The status code indicating successful connection. */ | |
37 private static final int SUCCESSFUL_CONNECTION = 3; | |
38 | |
39 /* | 35 /* |
40 * Library-loading state machine. | 36 * Library-loading state machine. |
41 */ | 37 */ |
42 /** Whether the library has been loaded. Accessed on the UI thread. */ | 38 /** Whether the library has been loaded. Accessed on the UI thread. */ |
43 private static boolean sLoaded = false; | 39 private static boolean sLoaded = false; |
44 | 40 |
45 /** The application context. Accessed on the UI thread. */ | 41 /** The application context. Accessed on the UI thread. */ |
46 private static Activity sContext = null; | 42 private static Activity sContext = null; |
47 | 43 |
| 44 /** Interface used for connection state notifications. */ |
| 45 public interface ConnectionListener { |
| 46 /** |
| 47 * This enum must match the C++ enumeration remoting::protocol::Connecti
onToHost::State. |
| 48 */ |
| 49 public enum State { |
| 50 INITIALIZING(0), |
| 51 CONNECTING(1), |
| 52 AUTHENTICATED(2), |
| 53 CONNECTED(3), |
| 54 FAILED(4), |
| 55 CLOSED(5); |
| 56 |
| 57 private final int mValue; |
| 58 |
| 59 State(int value) { |
| 60 mValue = value; |
| 61 } |
| 62 |
| 63 public int value() { |
| 64 return mValue; |
| 65 } |
| 66 |
| 67 public static State fromValue(int value) { |
| 68 return values()[value]; |
| 69 } |
| 70 } |
| 71 |
| 72 /** |
| 73 * This enum must match the C++ enumeration remoting::protocol::ErrorCod
e. |
| 74 */ |
| 75 public enum Error { |
| 76 OK(0), |
| 77 PEER_IS_OFFLINE(1), |
| 78 SESSION_REJECTED(2), |
| 79 INCOMPATIBLE_PROTOCOL(3), |
| 80 AUTHENTICATION_FAILED(4), |
| 81 CHANNEL_CONNECTION_ERROR(5), |
| 82 SIGNALING_ERROR(6), |
| 83 SIGNALING_TIMEOUT(7), |
| 84 HOST_OVERLOAD(8), |
| 85 UNKNOWN_ERROR(9); |
| 86 |
| 87 private final int mValue; |
| 88 |
| 89 Error(int value) { |
| 90 mValue = value; |
| 91 } |
| 92 |
| 93 public int value() { |
| 94 return mValue; |
| 95 } |
| 96 |
| 97 public static Error fromValue(int value) { |
| 98 return values()[value]; |
| 99 } |
| 100 } |
| 101 |
| 102 /** |
| 103 * Notified on connection state change. |
| 104 * @param state The new connection state. |
| 105 * @param error The error code, if state is STATE_FAILED. |
| 106 */ |
| 107 void onConnectionState(State state, Error error); |
| 108 } |
| 109 |
48 /* | 110 /* |
49 * Connection-initiating state machine. | 111 * Connection-initiating state machine. |
50 */ | 112 */ |
51 /** Whether the native code is attempting a connection. Accessed on the UI t
hread. */ | 113 /** Whether the native code is attempting a connection. Accessed on the UI t
hread. */ |
52 private static boolean sConnected = false; | 114 private static boolean sConnected = false; |
53 | 115 |
54 /** Callback to signal upon successful connection. Accessed on the UI thread
. */ | 116 /** Notified upon successful connection or disconnection. Accessed on the UI
thread. */ |
55 private static Runnable sSuccessCallback = null; | 117 private static ConnectionListener sConnectionListener = null; |
56 | |
57 /** Dialog for reporting connection progress. Accessed on the UI thread. */ | |
58 private static ProgressDialog sProgressIndicator = null; | |
59 | |
60 // Protects access to |sProgressIndicator|. Used only to silence FindBugs wa
rnings - the | |
61 // variable it protects is only accessed on a single thread. | |
62 // TODO(lambroslambrou): Refactor the ProgressIndicator into a separate clas
s. | |
63 private static Object sProgressIndicatorLock = new Object(); | |
64 | 118 |
65 /** | 119 /** |
66 * Callback invoked on the graphics thread to repaint the desktop. Accessed
on the UI and | 120 * Callback invoked on the graphics thread to repaint the desktop. Accessed
on the UI and |
67 * graphics threads. | 121 * graphics threads. |
68 */ | 122 */ |
69 private static Runnable sRedrawCallback = null; | 123 private static Runnable sRedrawCallback = null; |
70 | 124 |
71 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and
graphics threads. */ | 125 /** Bitmap holding a copy of the latest video frame. Accessed on the UI and
graphics threads. */ |
72 private static Bitmap sFrameBitmap = null; | 126 private static Bitmap sFrameBitmap = null; |
73 | 127 |
(...skipping 27 matching lines...) Expand all Loading... |
101 | 155 |
102 /* | 156 /* |
103 * API/OAuth2 keys access. | 157 * API/OAuth2 keys access. |
104 */ | 158 */ |
105 public static native String nativeGetApiKey(); | 159 public static native String nativeGetApiKey(); |
106 public static native String nativeGetClientId(); | 160 public static native String nativeGetClientId(); |
107 public static native String nativeGetClientSecret(); | 161 public static native String nativeGetClientSecret(); |
108 | 162 |
109 /** Attempts to form a connection to the user-selected host. Called on the U
I thread. */ | 163 /** Attempts to form a connection to the user-selected host. Called on the U
I thread. */ |
110 public static void connectToHost(String username, String authToken, | 164 public static void connectToHost(String username, String authToken, |
111 String hostJid, String hostId, String hostPubkey, Runnable successCa
llback) { | 165 String hostJid, String hostId, String hostPubkey, ConnectionListener
listener) { |
112 disconnectFromHost(); | 166 disconnectFromHost(); |
113 | 167 |
114 sSuccessCallback = successCallback; | 168 sConnectionListener = listener; |
115 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE)
; | 169 SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE)
; |
116 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, | 170 nativeConnect(username, authToken, hostJid, hostId, hostPubkey, |
117 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_
secret", "")); | 171 prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_
secret", "")); |
118 sConnected = true; | 172 sConnected = true; |
119 } | 173 } |
120 | 174 |
121 /** Performs the native portion of the connection. */ | 175 /** Performs the native portion of the connection. */ |
122 private static native void nativeConnect(String username, String authToken,
String hostJid, | 176 private static native void nativeConnect(String username, String authToken,
String hostJid, |
123 String hostId, String hostPubkey, String pairId, String pairSecret); | 177 String hostId, String hostPubkey, String pairId, String pairSecret); |
124 | 178 |
125 /** Severs the connection and cleans up. Called on the UI thread. */ | 179 /** Severs the connection and cleans up. Called on the UI thread. */ |
126 public static void disconnectFromHost() { | 180 public static void disconnectFromHost() { |
127 if (!sConnected) return; | 181 if (!sConnected) return; |
128 | 182 |
129 synchronized (sProgressIndicatorLock) { | 183 sConnectionListener.onConnectionState(ConnectionListener.State.CLOSED, |
130 if (sProgressIndicator != null) { | 184 ConnectionListener.Error.OK); |
131 sProgressIndicator.dismiss(); | |
132 sProgressIndicator = null; | |
133 } | |
134 } | |
135 | 185 |
136 nativeDisconnect(); | 186 nativeDisconnect(); |
137 sSuccessCallback = null; | 187 sConnectionListener = null; |
138 sConnected = false; | 188 sConnected = false; |
139 | 189 |
140 // Drop the reference to free the Bitmap for GC. | 190 // Drop the reference to free the Bitmap for GC. |
141 synchronized (sFrameLock) { | 191 synchronized (sFrameLock) { |
142 sFrameBitmap = null; | 192 sFrameBitmap = null; |
143 } | 193 } |
144 } | 194 } |
145 | 195 |
146 /** Performs the native portion of the cleanup. */ | 196 /** Performs the native portion of the cleanup. */ |
147 private static native void nativeDisconnect(); | 197 private static native void nativeDisconnect(); |
148 | 198 |
149 /** Reports whenever the connection status changes. Called on the UI thread.
*/ | 199 /** Reports whenever the connection status changes. Called on the UI thread.
*/ |
150 @CalledByNative | 200 @CalledByNative |
151 private static void reportConnectionStatus(int state, int error) { | 201 private static void reportConnectionStatus(int state, int error) { |
152 if (state < SUCCESSFUL_CONNECTION && error == 0) { | 202 sConnectionListener.onConnectionState(ConnectionListener.State.fromValue
(state), |
153 // The connection is still being established, so we'll report the cu
rrent progress. | 203 ConnectionListener.Error.fromValue(error)); |
154 synchronized (sProgressIndicatorLock) { | |
155 if (sProgressIndicator == null) { | |
156 sProgressIndicator = ProgressDialog.show(sContext, sContext. | |
157 getString(R.string.progress_title), sContext.getReso
urces(). | |
158 getStringArray(R.array.protoc_states)[state], true,
true, | |
159 new DialogInterface.OnCancelListener() { | |
160 @Override | |
161 public void onCancel(DialogInterface dialog) { | |
162 Log.i("jniiface", "User canceled connection
initiation"); | |
163 disconnectFromHost(); | |
164 } | |
165 }); | |
166 } else { | |
167 sProgressIndicator.setMessage( | |
168 sContext.getResources().getStringArray(R.array.proto
c_states)[state]); | |
169 } | |
170 } | |
171 } else { | |
172 // The connection is complete or has failed, so we can lose the prog
ress indicator. | |
173 synchronized (sProgressIndicatorLock) { | |
174 if (sProgressIndicator != null) { | |
175 sProgressIndicator.dismiss(); | |
176 sProgressIndicator = null; | |
177 } | |
178 } | |
179 | |
180 if (state == SUCCESSFUL_CONNECTION) { | |
181 Toast.makeText(sContext, sContext.getResources(). | |
182 getStringArray(R.array.protoc_states)[state], Toast.LENG
TH_SHORT).show(); | |
183 | |
184 // Actually display the remote desktop. | |
185 sSuccessCallback.run(); | |
186 } else { | |
187 Toast.makeText(sContext, sContext.getResources().getStringArray( | |
188 R.array.protoc_states)[state] + (error == 0 ? "" : ": "
+ | |
189 sContext.getResources().getStringArray(R.array.protoc_er
rors)[error]), | |
190 Toast.LENGTH_LONG).show(); | |
191 } | |
192 } | |
193 } | 204 } |
194 | 205 |
195 /** Prompts the user to enter a PIN. Called on the UI thread. */ | 206 /** Prompts the user to enter a PIN. Called on the UI thread. */ |
196 @CalledByNative | 207 @CalledByNative |
197 private static void displayAuthenticationPrompt(boolean pairingSupported) { | 208 private static void displayAuthenticationPrompt(boolean pairingSupported) { |
198 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); | 209 AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext); |
199 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); | 210 pinPrompt.setTitle(sContext.getString(R.string.pin_entry_title)); |
200 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); | 211 pinPrompt.setMessage(sContext.getString(R.string.pin_entry_message)); |
201 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); | 212 pinPrompt.setIcon(android.R.drawable.ic_lock_lock); |
202 | 213 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 buffer.asIntBuffer().get(data, 0, data.length); | 403 buffer.asIntBuffer().get(data, 0, data.length); |
393 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A
RGB_8888); | 404 sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.A
RGB_8888); |
394 } | 405 } |
395 | 406 |
396 /** Position of cursor hotspot within cursor image. Called on the graphics t
hread. */ | 407 /** Position of cursor hotspot within cursor image. Called on the graphics t
hread. */ |
397 public static Point getCursorHotspot() { return sCursorHotspot; } | 408 public static Point getCursorHotspot() { return sCursorHotspot; } |
398 | 409 |
399 /** Returns the current cursor shape. Called on the graphics thread. */ | 410 /** Returns the current cursor shape. Called on the graphics thread. */ |
400 public static Bitmap getCursorBitmap() { return sCursorBitmap; } | 411 public static Bitmap getCursorBitmap() { return sCursorBitmap; } |
401 } | 412 } |
OLD | NEW |