Merge "First stab at attaching native event dispatching." into gingerbread

This commit is contained in:
Dianne Hackborn
2010-06-22 11:22:37 -07:00
committed by Android (Google) Code Review
19 changed files with 606 additions and 175 deletions

View File

@ -26306,6 +26306,8 @@
deprecated="not deprecated"
visibility="public"
>
<implements name="android.view.InputConsumer.Callback">
</implements>
<implements name="android.view.SurfaceHolder.Callback">
</implements>
<constructor name="NativeActivity"
@ -26316,6 +26318,32 @@
visibility="public"
>
</constructor>
<method name="onInputConsumerCreated"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="consumer" type="android.view.InputConsumer">
</parameter>
</method>
<method name="onInputConsumerDestroyed"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="consumer" type="android.view.InputConsumer">
</parameter>
</method>
<method name="surfaceChanged"
return="void"
abstract="false"
@ -172813,6 +172841,49 @@
</parameter>
</constructor>
</class>
<class name="InputConsumer"
extends="java.lang.Object"
abstract="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</class>
<interface name="InputConsumer.Callback"
abstract="true"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<method name="onInputConsumerCreated"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="consumer" type="android.view.InputConsumer">
</parameter>
</method>
<method name="onInputConsumerDestroyed"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="consumer" type="android.view.InputConsumer">
</parameter>
</method>
</interface>
<class name="KeyCharacterMap"
extends="java.lang.Object"
abstract="false"
@ -187266,6 +187337,19 @@
<parameter name="event" type="android.view.MotionEvent">
</parameter>
</method>
<method name="takeInputChannel"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="callback" type="android.view.InputConsumer.Callback">
</parameter>
</method>
<method name="takeKeyEvents"
return="void"
abstract="true"

View File

@ -6,6 +6,8 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.InputChannel;
import android.view.InputConsumer;
import android.view.SurfaceHolder;
import java.io.File;
@ -14,7 +16,8 @@ import java.io.File;
* Convenience for implementing an activity that will be implemented
* purely in native code. That is, a game (or game-like thing).
*/
public class NativeActivity extends Activity implements SurfaceHolder.Callback {
public class NativeActivity extends Activity implements SurfaceHolder.Callback,
InputConsumer.Callback {
public static final String META_DATA_LIB_NAME = "android.app.lib_name";
private int mNativeHandle;
@ -33,6 +36,8 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback {
private native void onSurfaceChangedNative(int handle, SurfaceHolder holder,
int format, int width, int height);
private native void onSurfaceDestroyedNative(int handle, SurfaceHolder holder);
private native void onInputChannelCreatedNative(int handle, InputChannel channel);
private native void onInputChannelDestroyedNative(int handle, InputChannel channel);
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -40,6 +45,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback {
ActivityInfo ai;
getWindow().takeSurface(this);
getWindow().takeInputChannel(this);
try {
ai = getPackageManager().getActivityInfo(
@ -138,4 +144,12 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback {
public void surfaceDestroyed(SurfaceHolder holder) {
onSurfaceDestroyedNative(mNativeHandle, holder);
}
public void onInputConsumerCreated(InputConsumer consumer) {
onInputChannelCreatedNative(mNativeHandle, consumer.getInputChannel());
}
public void onInputConsumerDestroyed(InputConsumer consumer) {
onInputChannelDestroyedNative(mNativeHandle, consumer.getInputChannel());
}
}

View File

@ -22,8 +22,9 @@ import android.util.Slog;
/**
* An input channel specifies the file descriptors used to send input events to
* a window in another process. It is Parcelable so that it can be transmitted
* to the ViewRoot through a Binder transaction as part of registering the Window.
* a window in another process. It is Parcelable so that it can be sent
* to the process that is to receive events. Only one thread should be reading
* from an InputChannel at a time.
* @hide
*/
public final class InputChannel implements Parcelable {

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
/**
* Handle for consuming raw input events.
*/
public class InputConsumer {
public static interface Callback {
void onInputConsumerCreated(InputConsumer consumer);
void onInputConsumerDestroyed(InputConsumer consumer);
}
final InputChannel mChannel;
/** @hide */
public InputConsumer(InputChannel channel) {
mChannel = channel;
}
/** @hide */
public InputChannel getInputChannel() {
return mChannel;
}
}

View File

@ -154,7 +154,9 @@ public final class ViewRoot extends Handler implements ViewParent,
final View.AttachInfo mAttachInfo;
InputChannel mInputChannel;
InputConsumer.Callback mInputConsumerCallback;
InputConsumer mInputConsumer;
final Rect mTempRect; // used in the transaction to not thrash the heap.
final Rect mVisRect; // used to retrieve visible rect of focused view.
@ -555,8 +557,17 @@ public final class ViewRoot extends Handler implements ViewParent,
}
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
if (view instanceof RootViewSurfaceTaker) {
mInputConsumerCallback =
((RootViewSurfaceTaker)view).willYouTakeTheInputConsumer();
}
if (mInputConsumerCallback != null) {
mInputConsumer = new InputConsumer(mInputChannel);
mInputConsumerCallback.onInputConsumerCreated(mInputConsumer);
} else {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}
}
view.assignParent(this);
@ -1736,7 +1747,12 @@ public final class ViewRoot extends Handler implements ViewParent,
if (WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH) {
if (mInputChannel != null) {
InputQueue.unregisterInputChannel(mInputChannel);
if (mInputConsumerCallback != null) {
mInputConsumerCallback.onInputConsumerDestroyed(mInputConsumer);
mInputConsumerCallback = null;
} else {
InputQueue.unregisterInputChannel(mInputChannel);
}
mInputChannel.dispose();
mInputChannel = null;
}

View File

@ -480,6 +480,13 @@ public abstract class Window {
*/
public abstract void takeSurface(SurfaceHolder.Callback callback);
/**
* Take ownership of this window's InputChannel. The window will no
* longer read and dispatch input events from the channel; it is your
* responsibility to do so.
*/
public abstract void takeInputChannel(InputConsumer.Callback callback);
/**
* Return whether this window is being displayed with a floating style
* (based on the {@link android.R.attr#windowIsFloating} attribute in

View File

@ -1,5 +1,6 @@
package com.android.internal.view;
import android.view.InputConsumer;
import android.view.SurfaceHolder;
/** hahahah */
@ -8,4 +9,5 @@ public interface RootViewSurfaceTaker {
void setSurfaceType(int type);
void setSurfaceFormat(int format);
void setSurfaceKeepScreenOn(boolean keepOn);
InputConsumer.Callback willYouTakeTheInputConsumer();
}

View File

@ -18,8 +18,10 @@
#include <utils/Log.h>
#include "JNIHelp.h"
#include "android_view_InputChannel.h"
#include <android_runtime/AndroidRuntime.h>
#include <android/native_activity.h>
#include <ui/InputTransport.h>
#include <dlfcn.h>
@ -33,9 +35,13 @@ struct NativeCode {
dlhandle = _dlhandle;
createActivityFunc = _createFunc;
surface = NULL;
inputChannel = NULL;
nativeInputQueue = NULL;
}
~NativeCode() {
setSurface(NULL);
setInputChannel(NULL);
if (callbacks.onDestroy != NULL) {
callbacks.onDestroy(&activity);
}
@ -55,6 +61,31 @@ struct NativeCode {
}
}
status_t setInputChannel(jobject _channel) {
if (inputChannel != NULL) {
delete nativeInputQueue;
activity.env->DeleteGlobalRef(inputChannel);
}
inputChannel = NULL;
nativeInputQueue = NULL;
if (_channel != NULL) {
inputChannel = activity.env->NewGlobalRef(_channel);
sp<InputChannel> ic =
android_view_InputChannel_getInputChannel(activity.env, _channel);
if (ic != NULL) {
nativeInputQueue = new input_queue_t(ic);
if (nativeInputQueue->getConsumer().initialize() != android::OK) {
delete nativeInputQueue;
nativeInputQueue = NULL;
return UNKNOWN_ERROR;
}
} else {
return UNKNOWN_ERROR;
}
}
return OK;
}
android_activity_t activity;
android_activity_callbacks_t callbacks;
@ -62,6 +93,8 @@ struct NativeCode {
android_activity_create_t* createActivityFunc;
jobject surface;
jobject inputChannel;
struct input_queue_t* nativeInputQueue;
};
static jint
@ -217,6 +250,38 @@ onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surfa
}
}
static void
onInputChannelCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject channel)
{
if (handle != 0) {
NativeCode* code = (NativeCode*)handle;
status_t err = code->setInputChannel(channel);
if (err != OK) {
jniThrowException(env, "java/lang/IllegalStateException",
"Error setting input channel");
return;
}
if (code->callbacks.onInputQueueCreated != NULL) {
code->callbacks.onInputQueueCreated(&code->activity,
code->nativeInputQueue);
}
}
}
static void
onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject channel)
{
if (handle != 0) {
NativeCode* code = (NativeCode*)handle;
if (code->nativeInputQueue != NULL
&& code->callbacks.onInputQueueDestroyed != NULL) {
code->callbacks.onInputQueueDestroyed(&code->activity,
code->nativeInputQueue);
}
code->setInputChannel(NULL);
}
}
static const JNINativeMethod g_methods[] = {
{ "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native },
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
@ -230,6 +295,8 @@ static const JNINativeMethod g_methods[] = {
{ "onSurfaceCreatedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceCreated_native },
{ "onSurfaceChangedNative", "(ILandroid/view/SurfaceHolder;III)V", (void*)onSurfaceChanged_native },
{ "onSurfaceDestroyedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceDestroyed_native },
{ "onInputChannelCreatedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelCreated_native },
{ "onInputChannelDestroyedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelDestroyed_native },
};
static const char* const kNativeActivityPathName = "android/app/NativeActivity";
@ -248,4 +315,4 @@ int register_android_app_NativeActivity(JNIEnv* env)
g_methods, NELEM(g_methods));
}
}
} // namespace android

View File

@ -19,9 +19,9 @@
#include "jni.h"
namespace android {
#include <ui/InputTransport.h>
class InputChannel;
namespace android {
typedef void (*InputChannelObjDisposeCallback)(JNIEnv* env, jobject inputChannelObj,
const sp<InputChannel>& inputChannel, void* data);

View File

@ -40,6 +40,11 @@ enum {
*/
#define MAX_POINTERS 10
/*
* Declare a concrete type for the NDK's input event forward declaration.
*/
struct input_event_t { };
namespace android {
/*
@ -128,8 +133,6 @@ struct PointerCoords {
/*
* Input events.
*/
struct input_event_t { };
class InputEvent : public input_event_t {
public:
virtual ~InputEvent() { }

View File

@ -330,4 +330,24 @@ private:
} // namespace android
/*
* NDK input queue API.
*/
struct input_queue_t {
public:
/* Creates a consumer associated with an input channel. */
explicit input_queue_t(const android::sp<android::InputChannel>& channel);
/* Destroys the consumer and releases its input channel. */
~input_queue_t();
inline android::InputConsumer& getConsumer() { return mConsumer; }
android::status_t consume(android::InputEvent** event);
private:
android::InputConsumer mConsumer;
android::PreallocatedInputEventFactory mInputEventFactory;
};
#endif // _UI_INPUT_TRANSPORT_H

View File

@ -88,166 +88,3 @@ void MotionEvent::offsetLocation(float xOffset, float yOffset) {
}
} // namespace android
// NDK APIs
using android::InputEvent;
using android::KeyEvent;
using android::MotionEvent;
int32_t input_event_get_type(const input_event_t* event) {
return reinterpret_cast<const InputEvent*>(event)->getType();
}
int32_t input_event_get_device_id(const input_event_t* event) {
return reinterpret_cast<const InputEvent*>(event)->getDeviceId();
}
int32_t input_event_get_nature(const input_event_t* event) {
return reinterpret_cast<const InputEvent*>(event)->getNature();
}
int32_t key_event_get_action(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getAction();
}
int32_t key_event_get_flags(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getFlags();
}
int32_t key_event_get_key_code(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getKeyCode();
}
int32_t key_event_get_scan_code(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getScanCode();
}
int32_t key_event_get_meta_state(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getMetaState();
}
int32_t key_event_get_repeat_count(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getRepeatCount();
}
int64_t key_event_get_down_time(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getDownTime();
}
int64_t key_event_get_event_time(const input_event_t* key_event) {
return reinterpret_cast<const KeyEvent*>(key_event)->getEventTime();
}
int32_t motion_event_get_action(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getAction();
}
int32_t motion_event_get_meta_state(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getMetaState();
}
int32_t motion_event_get_edge_flags(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getEdgeFlags();
}
int64_t motion_event_get_down_time(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getDownTime();
}
int64_t motion_event_get_event_time(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getEventTime();
}
float motion_event_get_x_offset(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getXOffset();
}
float motion_event_get_y_offset(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getYOffset();
}
float motion_event_get_x_precision(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getXPrecision();
}
float motion_event_get_y_precision(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getYPrecision();
}
size_t motion_event_get_pointer_count(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getPointerCount();
}
int32_t motion_event_get_pointer_id(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getPointerId(pointer_index);
}
float motion_event_get_raw_x(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getRawX(pointer_index);
}
float motion_event_get_raw_y(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getRawY(pointer_index);
}
float motion_event_get_x(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getX(pointer_index);
}
float motion_event_get_y(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getY(pointer_index);
}
float motion_event_get_pressure(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getPressure(pointer_index);
}
float motion_event_get_size(const input_event_t* motion_event, size_t pointer_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getSize(pointer_index);
}
size_t motion_event_get_history_size(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistorySize();
}
int64_t motion_event_get_historical_event_time(input_event_t* motion_event,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalEventTime(
history_index);
}
float motion_event_get_historical_raw_x(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalRawX(
pointer_index, history_index);
}
float motion_event_get_historical_raw_y(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalRawY(
pointer_index, history_index);
}
float motion_event_get_historical_x(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalX(
pointer_index, history_index);
}
float motion_event_get_historical_y(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalY(
pointer_index, history_index);
}
float motion_event_get_historical_pressure(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalPressure(
pointer_index, history_index);
}
float motion_event_get_historical_size(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalSize(
pointer_index, history_index);
}

View File

@ -686,3 +686,22 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
}
} // namespace android
// --- input_queue_t ---
using android::InputEvent;
using android::InputChannel;
using android::InputConsumer;
using android::sp;
using android::status_t;
input_queue_t::input_queue_t(const sp<InputChannel>& channel) :
mConsumer(channel) {
}
input_queue_t::~input_queue_t() {
}
status_t input_queue_t::consume(InputEvent** event) {
return mConsumer.consume(&mInputEventFactory, event);
}

26
native/android/Android.mk Normal file
View File

@ -0,0 +1,26 @@
BASE_PATH := $(call my-dir)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
# our source files
#
LOCAL_SRC_FILES:= \
activity.cpp \
input.cpp
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libcutils \
libutils \
libbinder \
libui
LOCAL_C_INCLUDES += \
frameworks/base/native/include \
frameworks/base/core/jni/android \
dalvik/libnativehelper/include/nativehelper
LOCAL_MODULE:= libandroid
include $(BUILD_SHARED_LIBRARY)

View File

233
native/android/input.cpp Normal file
View File

@ -0,0 +1,233 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "input"
#include <utils/Log.h>
#include <android/input.h>
#include <ui/Input.h>
#include <ui/InputTransport.h>
#include <poll.h>
using android::InputEvent;
using android::KeyEvent;
using android::MotionEvent;
int32_t input_event_get_type(const input_event_t* event) {
return static_cast<const InputEvent*>(event)->getType();
}
int32_t input_event_get_device_id(const input_event_t* event) {
return static_cast<const InputEvent*>(event)->getDeviceId();
}
int32_t input_event_get_nature(const input_event_t* event) {
return static_cast<const InputEvent*>(event)->getNature();
}
int32_t key_event_get_action(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getAction();
}
int32_t key_event_get_flags(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getFlags();
}
int32_t key_event_get_key_code(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getKeyCode();
}
int32_t key_event_get_scan_code(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getScanCode();
}
int32_t key_event_get_meta_state(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getMetaState();
}
int32_t key_event_get_repeat_count(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getRepeatCount();
}
int64_t key_event_get_down_time(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getDownTime();
}
int64_t key_event_get_event_time(const input_event_t* key_event) {
return static_cast<const KeyEvent*>(key_event)->getEventTime();
}
int32_t motion_event_get_action(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getAction();
}
int32_t motion_event_get_meta_state(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getMetaState();
}
int32_t motion_event_get_edge_flags(const input_event_t* motion_event) {
return reinterpret_cast<const MotionEvent*>(motion_event)->getEdgeFlags();
}
int64_t motion_event_get_down_time(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getDownTime();
}
int64_t motion_event_get_event_time(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getEventTime();
}
float motion_event_get_x_offset(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getXOffset();
}
float motion_event_get_y_offset(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getYOffset();
}
float motion_event_get_x_precision(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getXPrecision();
}
float motion_event_get_y_precision(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getYPrecision();
}
size_t motion_event_get_pointer_count(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getPointerCount();
}
int32_t motion_event_get_pointer_id(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getPointerId(pointer_index);
}
float motion_event_get_raw_x(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getRawX(pointer_index);
}
float motion_event_get_raw_y(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getRawY(pointer_index);
}
float motion_event_get_x(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getX(pointer_index);
}
float motion_event_get_y(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getY(pointer_index);
}
float motion_event_get_pressure(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getPressure(pointer_index);
}
float motion_event_get_size(const input_event_t* motion_event, size_t pointer_index) {
return static_cast<const MotionEvent*>(motion_event)->getSize(pointer_index);
}
size_t motion_event_get_history_size(const input_event_t* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getHistorySize();
}
int64_t motion_event_get_historical_event_time(input_event_t* motion_event,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalEventTime(
history_index);
}
float motion_event_get_historical_raw_x(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalRawX(
pointer_index, history_index);
}
float motion_event_get_historical_raw_y(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalRawY(
pointer_index, history_index);
}
float motion_event_get_historical_x(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalX(
pointer_index, history_index);
}
float motion_event_get_historical_y(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalY(
pointer_index, history_index);
}
float motion_event_get_historical_pressure(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalPressure(
pointer_index, history_index);
}
float motion_event_get_historical_size(input_event_t* motion_event, size_t pointer_index,
size_t history_index) {
return static_cast<const MotionEvent*>(motion_event)->getHistoricalSize(
pointer_index, history_index);
}
int input_queue_get_fd(input_queue_t* queue) {
return queue->getConsumer().getChannel()->getReceivePipeFd();
}
int input_queue_has_events(input_queue_t* queue) {
struct pollfd pfd;
pfd.fd = queue->getConsumer().getChannel()->getReceivePipeFd();
pfd.events = POLLIN;
pfd.revents = 0;
int nfd = poll(&pfd, 1, 0);
if (nfd <= 0) return nfd;
return pfd.revents == POLLIN ? 1 : -1;
}
int32_t input_queue_get_event(input_queue_t* queue, input_event_t** outEvent) {
*outEvent = NULL;
int32_t res = queue->getConsumer().receiveDispatchSignal();
if (res != android::OK) {
LOGE("channel '%s' ~ Failed to receive dispatch signal. status=%d",
queue->getConsumer().getChannel()->getName().string(), res);
return -1;
}
InputEvent* myEvent = NULL;
res = queue->consume(&myEvent);
if (res != android::OK) {
LOGW("channel '%s' ~ Failed to consume input event. status=%d",
queue->getConsumer().getChannel()->getName().string(), res);
queue->getConsumer().sendFinishedSignal();
return -1;
}
*outEvent = myEvent;
return 0;
}
void input_queue_finish_event(input_queue_t* queue, input_event_t* event,
int handled) {
int32_t res = queue->getConsumer().sendFinishedSignal();
if (res != android::OK) {
LOGW("Failed to send finished signal on channel '%s'. status=%d",
queue->getConsumer().getChannel()->getName().string(), res);
}
}

View File

@ -523,6 +523,42 @@ float motion_event_get_historical_pressure(input_event_t* motion_event, size_t p
float motion_event_get_historical_size(input_event_t* motion_event, size_t pointer_index,
size_t history_index);
/*
* Input queue
*
* An input queue is the facility through which you retrieve input
* events.
*/
struct input_queue_t;
typedef struct input_queue_t input_queue_t;
/*
* Return a file descriptor for the queue, which you
* can use to determine if there are events available. This
* is typically used with select() or poll() to multiplex
* with other kinds of events.
*/
int input_queue_get_fd(input_queue_t* queue);
/*
* Returns true if there are one or more events available in the
* input queue. Returns 1 if the queue has events; 0 if
* it does not have events; and a negative value if there is an error.
*/
int input_queue_has_events(input_queue_t* queue);
/*
* Returns the next available event from the queue. Returns a negative
* value if no events are available or an error has occurred.
*/
int32_t input_queue_get_event(input_queue_t* queue, input_event_t** outEvent);
/*
* Report that dispatching has finished with the given event.
* This must be called after receiving an event with input_queue_get_event().
*/
void input_queue_finish_event(input_queue_t* queue, input_event_t* event, int handled);
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,8 @@
#include <jni.h>
#include <android/input.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -144,6 +146,19 @@ typedef struct android_activity_callbacks_t {
* returning from here.
*/
void (*onSurfaceDestroyed)(android_activity_t* activity, android_surface_t* surface);
/**
* The input queue for this native activity's window has been created.
* You can use the given input queue to start retrieving input events.
*/
void (*onInputQueueCreated)(android_activity_t* activity, input_queue_t* queue);
/**
* The input queue for this native activity's window is being destroyed.
* You should no longer try to reference this object upon returning from this
* function.
*/
void (*onInputQueueDestroyed)(android_activity_t* activity, input_queue_t* queue);
/**
* The system is running low on memory. Use this callback to release

View File

@ -56,6 +56,7 @@ import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InputConsumer;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -70,6 +71,7 @@ import android.view.ViewManager;
import android.view.VolumePanel;
import android.view.Window;
import android.view.WindowManager;
import android.view.InputConsumer.Callback;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
@ -108,6 +110,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
SurfaceHolder.Callback mTakeSurfaceCallback;
BaseSurfaceHolder mSurfaceHolder;
InputConsumer.Callback mTakeInputChannelCallback;
private boolean mIsFloating;
private LayoutInflater mLayoutInflater;
@ -251,6 +255,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mTakeSurfaceCallback = callback;
}
public void takeInputChannel(InputConsumer.Callback callback) {
mTakeInputChannelCallback = callback;
}
@Override
public boolean isFloating() {
return mIsFloating;
@ -2037,6 +2045,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return mFeatureId < 0 ? mTakeSurfaceCallback : null;
}
public InputConsumer.Callback willYouTakeTheInputConsumer() {
return mFeatureId < 0 ? mTakeInputChannelCallback : null;
}
public void setSurfaceType(int type) {
PhoneWindow.this.setType(type);
}