This source file includes following definitions.
- JNINamespace
- INITIALIZING
- CONNECTING
- AUTHENTICATED
- CONNECTED
- FAILED
- CLOSED
- value
- fromValue
- OK
- PEER_IS_OFFLINE
- SESSION_REJECTED
- INCOMPATIBLE_PROTOCOL
- AUTHENTICATION_FAILED
- CHANNEL_CONNECTION_ERROR
- SIGNALING_ERROR
- SIGNALING_TIMEOUT
- HOST_OVERLOAD
- UNKNOWN_ERROR
- value
- message
- fromValue
- onConnectionState
- loadLibrary
- nativeLoadNative
- nativeGetApiKey
- nativeGetClientId
- nativeGetClientSecret
- connectToHost
- nativeConnect
- disconnectFromHost
- nativeDisconnect
- reportConnectionStatus
- displayAuthenticationPrompt
- nativeAuthenticationResponse
- commitPairingCredentials
- sendMouseEvent
- nativeSendMouseEvent
- sendMouseWheelEvent
- nativeSendMouseWheelEvent
- sendKeyEvent
- nativeSendKeyEvent
- sendTextEvent
- nativeSendTextEvent
- provideRedrawCallback
- redrawGraphics
- nativeScheduleRedraw
- redrawGraphicsInternal
- getVideoFrame
- setVideoFrame
- newBitmap
- updateCursorShape
- getCursorHotspot
- getCursorBitmap
package org.chromium.chromoting.jni;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.chromoting.R;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@JNINamespace("remoting")
public class JniInterface {
private static boolean sLoaded = false;
private static Activity sContext = null;
public interface ConnectionListener {
public enum State {
INITIALIZING(0),
CONNECTING(1),
AUTHENTICATED(2),
CONNECTED(3),
FAILED(4),
CLOSED(5);
private final int mValue;
State(int value) {
mValue = value;
}
public int value() {
return mValue;
}
public static State fromValue(int value) {
return values()[value];
}
}
public enum Error {
OK(0, 0),
PEER_IS_OFFLINE(1, R.string.error_host_is_offline),
SESSION_REJECTED(2, R.string.error_invalid_access_code),
INCOMPATIBLE_PROTOCOL(3, R.string.error_incompatible_protocol),
AUTHENTICATION_FAILED(4, R.string.error_invalid_access_code),
CHANNEL_CONNECTION_ERROR(5, R.string.error_p2p_failure),
SIGNALING_ERROR(6, R.string.error_p2p_failure),
SIGNALING_TIMEOUT(7, R.string.error_p2p_failure),
HOST_OVERLOAD(8, R.string.error_host_overload),
UNKNOWN_ERROR(9, R.string.error_unexpected);
private final int mValue;
private final int mMessage;
Error(int value, int message) {
mValue = value;
mMessage = message;
}
public int value() {
return mValue;
}
public int message() {
return mMessage;
}
public static Error fromValue(int value) {
return values()[value];
}
}
void onConnectionState(State state, Error error);
}
private static boolean sConnected = false;
private static ConnectionListener sConnectionListener = null;
private static Runnable sRedrawCallback = null;
private static Bitmap sFrameBitmap = null;
private static final Object sFrameLock = new Object();
private static Point sCursorHotspot = new Point();
private static Bitmap sCursorBitmap = null;
public static void loadLibrary(Activity context) {
sContext = context;
if (sLoaded) return;
System.loadLibrary("remoting_client_jni");
nativeLoadNative(context);
sLoaded = true;
}
private static native void nativeLoadNative(Context context);
public static native String nativeGetApiKey();
public static native String nativeGetClientId();
public static native String nativeGetClientSecret();
public static void connectToHost(String username, String authToken,
String hostJid, String hostId, String hostPubkey, ConnectionListener listener) {
disconnectFromHost();
sConnectionListener = listener;
SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE);
nativeConnect(username, authToken, hostJid, hostId, hostPubkey,
prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_secret", ""));
sConnected = true;
}
private static native void nativeConnect(String username, String authToken, String hostJid,
String hostId, String hostPubkey, String pairId, String pairSecret);
public static void disconnectFromHost() {
if (!sConnected) return;
sConnectionListener.onConnectionState(ConnectionListener.State.CLOSED,
ConnectionListener.Error.OK);
nativeDisconnect();
sConnectionListener = null;
sConnected = false;
synchronized (sFrameLock) {
sFrameBitmap = null;
}
}
private static native void nativeDisconnect();
@CalledByNative
private static void reportConnectionStatus(int state, int error) {
sConnectionListener.onConnectionState(ConnectionListener.State.fromValue(state),
ConnectionListener.Error.fromValue(error));
}
@CalledByNative
private static void displayAuthenticationPrompt(boolean pairingSupported) {
AlertDialog.Builder pinPrompt = new AlertDialog.Builder(sContext);
pinPrompt.setTitle(sContext.getString(R.string.title_authenticate));
pinPrompt.setMessage(sContext.getString(R.string.pin_message_android));
pinPrompt.setIcon(android.R.drawable.ic_lock_lock);
final View pinEntry = sContext.getLayoutInflater().inflate(R.layout.pin_dialog, null);
pinPrompt.setView(pinEntry);
final TextView pinTextView = (TextView)pinEntry.findViewById(R.id.pin_dialog_text);
final CheckBox pinCheckBox = (CheckBox)pinEntry.findViewById(R.id.pin_dialog_check);
if (!pairingSupported) {
pinCheckBox.setChecked(false);
pinCheckBox.setVisibility(View.GONE);
}
pinPrompt.setPositiveButton(
R.string.connect_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.i("jniiface", "User provided a PIN code");
nativeAuthenticationResponse(String.valueOf(pinTextView.getText()),
pinCheckBox.isChecked(), Build.MODEL);
}
});
pinPrompt.setNegativeButton(
R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.i("jniiface", "User canceled pin entry prompt");
disconnectFromHost();
}
});
final AlertDialog pinDialog = pinPrompt.create();
pinTextView.setOnEditorActionListener(
new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
pinDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
pinDialog.dismiss();
return true;
}
});
pinDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
pinDialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick();
}
});
pinDialog.show();
}
private static native void nativeAuthenticationResponse(String pin, boolean createPair,
String deviceName);
@CalledByNative
private static void commitPairingCredentials(String host, byte[] id, byte[] secret) {
sContext.getPreferences(Activity.MODE_PRIVATE).edit().
putString(host + "_id", new String(id)).
putString(host + "_secret", new String(secret)).
apply();
}
public static void sendMouseEvent(int x, int y, int whichButton, boolean buttonDown) {
if (!sConnected) {
return;
}
nativeSendMouseEvent(x, y, whichButton, buttonDown);
}
private static native void nativeSendMouseEvent(int x, int y, int whichButton,
boolean buttonDown);
public static void sendMouseWheelEvent(int deltaX, int deltaY) {
if (!sConnected) {
return;
}
nativeSendMouseWheelEvent(deltaX, deltaY);
}
private static native void nativeSendMouseWheelEvent(int deltaX, int deltaY);
public static void sendKeyEvent(int keyCode, boolean keyDown) {
if (!sConnected) {
return;
}
nativeSendKeyEvent(keyCode, keyDown);
}
private static native void nativeSendKeyEvent(int keyCode, boolean keyDown);
public static void sendTextEvent(String text) {
if (!sConnected) {
return;
}
nativeSendTextEvent(text);
}
private static native void nativeSendTextEvent(String text);
public static void provideRedrawCallback(Runnable redrawCallback) {
sRedrawCallback = redrawCallback;
}
public static boolean redrawGraphics() {
if (!sConnected || sRedrawCallback == null) return false;
nativeScheduleRedraw();
return true;
}
private static native void nativeScheduleRedraw();
@CalledByNative
private static void redrawGraphicsInternal() {
Runnable callback = sRedrawCallback;
if (callback != null) {
callback.run();
}
}
public static Bitmap getVideoFrame() {
if (Looper.myLooper() == Looper.getMainLooper()) {
Log.w("jniiface", "Canvas being redrawn on UI thread");
}
synchronized (sFrameLock) {
return sFrameBitmap;
}
}
@CalledByNative
private static void setVideoFrame(Bitmap bitmap) {
if (Looper.myLooper() == Looper.getMainLooper()) {
Log.w("jniiface", "Video frame updated on UI thread");
}
synchronized (sFrameLock) {
sFrameBitmap = bitmap;
}
}
@CalledByNative
private static Bitmap newBitmap(int width, int height) {
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
@CalledByNative
public static void updateCursorShape(int width, int height, int hotspotX, int hotspotY,
ByteBuffer buffer) {
sCursorHotspot = new Point(hotspotX, hotspotY);
int[] data = new int[width * height];
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.asIntBuffer().get(data, 0, data.length);
sCursorBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.ARGB_8888);
}
public static Point getCursorHotspot() { return sCursorHotspot; }
public static Bitmap getCursorBitmap() { return sCursorBitmap; }
}