am 3c80a4a0: Implement default key handling for native code.
Merge commit '3c80a4a044865bdf1289c7896baffa1c082d835c' into gingerbread-plus-aosp * commit '3c80a4a044865bdf1289c7896baffa1c082d835c': Implement default key handling for native code.
This commit is contained in:
@@ -39,7 +39,6 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.text.Selection;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
@@ -6,9 +6,13 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.MessageQueue;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputQueue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -22,7 +26,12 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
private int mNativeHandle;
|
||||
|
||||
private native int loadNativeCode(String path);
|
||||
private InputQueue mCurInputQueue;
|
||||
private SurfaceHolder mCurSurfaceHolder;
|
||||
|
||||
private boolean mDestroyed;
|
||||
|
||||
private native int loadNativeCode(String path, MessageQueue queue);
|
||||
private native void unloadNativeCode(int handle);
|
||||
|
||||
private native void onStartNative(int handle);
|
||||
@@ -78,7 +87,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
||||
throw new IllegalArgumentException("Unable to find native library: " + libname);
|
||||
}
|
||||
|
||||
mNativeHandle = loadNativeCode(path);
|
||||
mNativeHandle = loadNativeCode(path, Looper.myQueue());
|
||||
if (mNativeHandle == 0) {
|
||||
throw new IllegalArgumentException("Unable to load native library: " + path);
|
||||
}
|
||||
@@ -87,6 +96,15 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mDestroyed = true;
|
||||
if (mCurSurfaceHolder != null) {
|
||||
onSurfaceDestroyedNative(mNativeHandle, mCurSurfaceHolder);
|
||||
mCurSurfaceHolder = null;
|
||||
}
|
||||
if (mCurInputQueue != null) {
|
||||
onInputChannelDestroyedNative(mNativeHandle, mCurInputQueue.getInputChannel());
|
||||
mCurInputQueue = null;
|
||||
}
|
||||
unloadNativeCode(mNativeHandle);
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -124,32 +142,58 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
onLowMemoryNative(mNativeHandle);
|
||||
if (!mDestroyed) {
|
||||
onLowMemoryNative(mNativeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
onWindowFocusChangedNative(mNativeHandle, hasFocus);
|
||||
if (!mDestroyed) {
|
||||
onWindowFocusChangedNative(mNativeHandle, hasFocus);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
onSurfaceCreatedNative(mNativeHandle, holder);
|
||||
if (!mDestroyed) {
|
||||
mCurSurfaceHolder = holder;
|
||||
onSurfaceCreatedNative(mNativeHandle, holder);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
onSurfaceChangedNative(mNativeHandle, holder, format, width, height);
|
||||
if (!mDestroyed) {
|
||||
mCurSurfaceHolder = holder;
|
||||
onSurfaceChangedNative(mNativeHandle, holder, format, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
onSurfaceDestroyedNative(mNativeHandle, holder);
|
||||
mCurSurfaceHolder = null;
|
||||
if (!mDestroyed) {
|
||||
onSurfaceDestroyedNative(mNativeHandle, holder);
|
||||
}
|
||||
}
|
||||
|
||||
public void onInputQueueCreated(InputQueue queue) {
|
||||
onInputChannelCreatedNative(mNativeHandle, queue.getInputChannel());
|
||||
if (!mDestroyed) {
|
||||
mCurInputQueue = queue;
|
||||
onInputChannelCreatedNative(mNativeHandle, queue.getInputChannel());
|
||||
}
|
||||
}
|
||||
|
||||
public void onInputQueueDestroyed(InputQueue queue) {
|
||||
onInputChannelDestroyedNative(mNativeHandle, queue.getInputChannel());
|
||||
mCurInputQueue = null;
|
||||
if (!mDestroyed) {
|
||||
onInputChannelDestroyedNative(mNativeHandle, queue.getInputChannel());
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchUnhandledKeyEvent(KeyEvent event) {
|
||||
View decor = getWindow().getDecorView();
|
||||
if (decor != null) {
|
||||
decor.dispatchKeyEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,33 +676,12 @@ public class KeyEvent implements Parcelable {
|
||||
* TODO: should the dpad keys be here? arguably, because they also shouldn't be menu shortcuts
|
||||
*/
|
||||
public final boolean isSystem() {
|
||||
switch (mKeyCode) {
|
||||
case KEYCODE_MENU:
|
||||
case KEYCODE_SOFT_RIGHT:
|
||||
case KEYCODE_HOME:
|
||||
case KEYCODE_BACK:
|
||||
case KEYCODE_CALL:
|
||||
case KEYCODE_ENDCALL:
|
||||
case KEYCODE_VOLUME_UP:
|
||||
case KEYCODE_VOLUME_DOWN:
|
||||
case KEYCODE_MUTE:
|
||||
case KEYCODE_POWER:
|
||||
case KEYCODE_HEADSETHOOK:
|
||||
case KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KEYCODE_MEDIA_STOP:
|
||||
case KEYCODE_MEDIA_NEXT:
|
||||
case KEYCODE_MEDIA_PREVIOUS:
|
||||
case KEYCODE_MEDIA_REWIND:
|
||||
case KEYCODE_MEDIA_FAST_FORWARD:
|
||||
case KEYCODE_CAMERA:
|
||||
case KEYCODE_FOCUS:
|
||||
case KEYCODE_SEARCH:
|
||||
case KEYCODE_PICTSYMBOLS:
|
||||
case KEYCODE_SWITCH_CHARSET:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return native_isSystemKey(mKeyCode);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public final boolean hasDefaultAction() {
|
||||
return native_hasDefaultAction(mKeyCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1226,4 +1205,7 @@ public class KeyEvent implements Parcelable {
|
||||
mDownTime = in.readLong();
|
||||
mEventTime = in.readLong();
|
||||
}
|
||||
|
||||
private native boolean native_isSystemKey(int keyCode);
|
||||
private native boolean native_hasDefaultAction(int keyCode);
|
||||
}
|
||||
|
||||
@@ -17,17 +17,63 @@
|
||||
#define LOG_TAG "NativeActivity"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include "android_view_InputChannel.h"
|
||||
#include <poll.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <ui/InputTransport.h>
|
||||
#include <utils/PollLoop.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include "JNIHelp.h"
|
||||
#include "android_os_MessageQueue.h"
|
||||
#include "android_view_InputChannel.h"
|
||||
#include "android_view_KeyEvent.h"
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
static struct {
|
||||
jclass clazz;
|
||||
|
||||
jmethodID dispatchUnhandledKeyEvent;
|
||||
} gNativeActivityClassInfo;
|
||||
|
||||
struct MyInputQueue : AInputQueue {
|
||||
explicit MyInputQueue(const android::sp<android::InputChannel>& channel, int workWrite)
|
||||
: AInputQueue(channel), mWorkWrite(workWrite) {
|
||||
}
|
||||
|
||||
virtual void doDefaultKey(android::KeyEvent* keyEvent) {
|
||||
mLock.lock();
|
||||
LOGI("Default key: pending=%d write=%d\n", mPendingKeys.size(), mWorkWrite);
|
||||
if (mPendingKeys.size() <= 0 && mWorkWrite >= 0) {
|
||||
int8_t cmd = 1;
|
||||
write(mWorkWrite, &cmd, sizeof(cmd));
|
||||
}
|
||||
mPendingKeys.add(keyEvent);
|
||||
mLock.unlock();
|
||||
}
|
||||
|
||||
KeyEvent* getNextEvent() {
|
||||
KeyEvent* event = NULL;
|
||||
|
||||
mLock.lock();
|
||||
if (mPendingKeys.size() > 0) {
|
||||
event = mPendingKeys[0];
|
||||
mPendingKeys.removeAt(0);
|
||||
}
|
||||
mLock.unlock();
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
int mWorkWrite;
|
||||
|
||||
Mutex mLock;
|
||||
Vector<KeyEvent*> mPendingKeys;
|
||||
};
|
||||
|
||||
struct NativeCode {
|
||||
NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
|
||||
memset(&activity, sizeof(activity), 0);
|
||||
@@ -37,14 +83,26 @@ struct NativeCode {
|
||||
surface = NULL;
|
||||
inputChannel = NULL;
|
||||
nativeInputQueue = NULL;
|
||||
mainWorkRead = mainWorkWrite = -1;
|
||||
}
|
||||
|
||||
~NativeCode() {
|
||||
if (activity.env != NULL && activity.clazz != NULL) {
|
||||
activity.env->DeleteGlobalRef(activity.clazz);
|
||||
}
|
||||
if (pollLoop != NULL && mainWorkRead >= 0) {
|
||||
pollLoop->removeCallback(mainWorkRead);
|
||||
}
|
||||
if (nativeInputQueue != NULL) {
|
||||
nativeInputQueue->mWorkWrite = -1;
|
||||
}
|
||||
setSurface(NULL);
|
||||
setInputChannel(NULL);
|
||||
if (callbacks.onDestroy != NULL) {
|
||||
callbacks.onDestroy(&activity);
|
||||
}
|
||||
if (mainWorkRead >= 0) close(mainWorkRead);
|
||||
if (mainWorkWrite >= 0) close(mainWorkWrite);
|
||||
if (dlhandle != NULL) {
|
||||
dlclose(dlhandle);
|
||||
}
|
||||
@@ -73,7 +131,7 @@ struct NativeCode {
|
||||
sp<InputChannel> ic =
|
||||
android_view_InputChannel_getInputChannel(activity.env, _channel);
|
||||
if (ic != NULL) {
|
||||
nativeInputQueue = new AInputQueue(ic);
|
||||
nativeInputQueue = new MyInputQueue(ic, mainWorkWrite);
|
||||
if (nativeInputQueue->getConsumer().initialize() != android::OK) {
|
||||
delete nativeInputQueue;
|
||||
nativeInputQueue = NULL;
|
||||
@@ -94,11 +152,36 @@ struct NativeCode {
|
||||
|
||||
jobject surface;
|
||||
jobject inputChannel;
|
||||
struct AInputQueue* nativeInputQueue;
|
||||
struct MyInputQueue* nativeInputQueue;
|
||||
|
||||
// These are used to wake up the main thread to process work.
|
||||
int mainWorkRead;
|
||||
int mainWorkWrite;
|
||||
sp<PollLoop> pollLoop;
|
||||
};
|
||||
|
||||
static bool mainWorkCallback(int fd, int events, void* data) {
|
||||
NativeCode* code = (NativeCode*)data;
|
||||
if ((events & POLLIN) != 0) {
|
||||
KeyEvent* keyEvent;
|
||||
while ((keyEvent=code->nativeInputQueue->getNextEvent()) != NULL) {
|
||||
jobject inputEventObj = android_view_KeyEvent_fromNative(
|
||||
code->activity.env, keyEvent);
|
||||
code->activity.env->CallVoidMethod(code->activity.clazz,
|
||||
gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj);
|
||||
int32_t res = code->nativeInputQueue->getConsumer().sendFinishedSignal();
|
||||
if (res != OK) {
|
||||
LOGW("Failed to send finished signal on channel '%s'. status=%d",
|
||||
code->nativeInputQueue->getConsumer().getChannel()->getName().string(), res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static jint
|
||||
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path)
|
||||
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue)
|
||||
{
|
||||
const char* pathStr = env->GetStringUTFChars(path, NULL);
|
||||
NativeCode* code = NULL;
|
||||
@@ -115,6 +198,24 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path)
|
||||
delete code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
code->pollLoop = android_os_MessageQueue_getPollLoop(env, messageQueue);
|
||||
if (code->pollLoop == NULL) {
|
||||
LOGW("Unable to retrieve MessageQueue's PollLoop");
|
||||
delete code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msgpipe[2];
|
||||
if (pipe(msgpipe)) {
|
||||
LOGW("could not create pipe: %s", strerror(errno));
|
||||
delete code;
|
||||
return 0;
|
||||
}
|
||||
code->mainWorkRead = msgpipe[0];
|
||||
code->mainWorkWrite = msgpipe[1];
|
||||
code->pollLoop->setCallback(code->mainWorkRead, POLLIN, mainWorkCallback, code);
|
||||
|
||||
code->activity.callbacks = &code->callbacks;
|
||||
if (env->GetJavaVM(&code->activity.vm) < 0) {
|
||||
LOGW("NativeActivity GetJavaVM failed");
|
||||
@@ -122,7 +223,7 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path)
|
||||
return 0;
|
||||
}
|
||||
code->activity.env = env;
|
||||
code->activity.clazz = clazz;
|
||||
code->activity.clazz = env->NewGlobalRef(clazz);
|
||||
code->createActivityFunc(&code->activity, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -288,7 +389,7 @@ onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native },
|
||||
{ "loadNativeCode", "(Ljava/lang/String;Landroid/os/MessageQueue;)I", (void*)loadNativeCode_native },
|
||||
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
|
||||
{ "onStartNative", "(I)V", (void*)onStart_native },
|
||||
{ "onResumeNative", "(I)V", (void*)onResume_native },
|
||||
@@ -306,15 +407,25 @@ static const JNINativeMethod g_methods[] = {
|
||||
|
||||
static const char* const kNativeActivityPathName = "android/app/NativeActivity";
|
||||
|
||||
#define FIND_CLASS(var, className) \
|
||||
var = env->FindClass(className); \
|
||||
LOG_FATAL_IF(! var, "Unable to find class " className); \
|
||||
var = jclass(env->NewGlobalRef(var));
|
||||
|
||||
#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
|
||||
var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
|
||||
LOG_FATAL_IF(! var, "Unable to find method" methodName);
|
||||
|
||||
int register_android_app_NativeActivity(JNIEnv* env)
|
||||
{
|
||||
//LOGD("register_android_app_NativeActivity");
|
||||
|
||||
jclass clazz;
|
||||
|
||||
clazz = env->FindClass(kNativeActivityPathName);
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity");
|
||||
|
||||
FIND_CLASS(gNativeActivityClassInfo.clazz, kNativeActivityPathName);
|
||||
|
||||
GET_METHOD_ID(gNativeActivityClassInfo.dispatchUnhandledKeyEvent,
|
||||
gNativeActivityClassInfo.clazz,
|
||||
"dispatchUnhandledKeyEvent", "(Landroid/view/KeyEvent;)V");
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(
|
||||
env, kNativeActivityPathName,
|
||||
g_methods, NELEM(g_methods));
|
||||
|
||||
@@ -76,8 +76,23 @@ void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t natur
|
||||
milliseconds_to_nanoseconds(eventTime));
|
||||
}
|
||||
|
||||
static jboolean native_isSystemKey(JNIEnv* env, jobject clazz, jint keyCode) {
|
||||
return KeyEvent::isSystemKey(keyCode);
|
||||
}
|
||||
|
||||
static jboolean native_hasDefaultAction(JNIEnv* env, jobject clazz, jint keyCode) {
|
||||
return KeyEvent::hasDefaultAction(keyCode);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "native_isSystemKey", "(I)Z", (void*)native_isSystemKey },
|
||||
{ "native_hasDefaultAction", "(I)Z", (void*)native_hasDefaultAction },
|
||||
};
|
||||
|
||||
static const char* const kKeyEventPathName = "android/view/KeyEvent";
|
||||
|
||||
#define FIND_CLASS(var, className) \
|
||||
var = env->FindClass(className); \
|
||||
LOG_FATAL_IF(! var, "Unable to find class " className); \
|
||||
@@ -92,8 +107,8 @@ void android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj, int32_t natur
|
||||
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
|
||||
|
||||
int register_android_view_KeyEvent(JNIEnv* env) {
|
||||
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
|
||||
|
||||
FIND_CLASS(gKeyEventClassInfo.clazz, kKeyEventPathName);
|
||||
|
||||
GET_METHOD_ID(gKeyEventClassInfo.ctor, gKeyEventClassInfo.clazz,
|
||||
"<init>", "(JJIIIIIII)V");
|
||||
|
||||
@@ -118,7 +133,9 @@ int register_android_view_KeyEvent(JNIEnv* env) {
|
||||
GET_FIELD_ID(gKeyEventClassInfo.mCharacters, gKeyEventClassInfo.clazz,
|
||||
"mCharacters", "Ljava/lang/String;");
|
||||
|
||||
return 0;
|
||||
return AndroidRuntime::registerNativeMethods(
|
||||
env, kKeyEventPathName,
|
||||
g_methods, NELEM(g_methods));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
inline int32_t getDeviceId() const { return mDeviceId; }
|
||||
|
||||
inline int32_t getNature() const { return mNature; }
|
||||
|
||||
|
||||
protected:
|
||||
void initialize(int32_t deviceId, int32_t nature);
|
||||
|
||||
@@ -179,6 +179,14 @@ public:
|
||||
|
||||
inline nsecs_t getEventTime() const { return mEventTime; }
|
||||
|
||||
// Return true if this event may have a default action implementation.
|
||||
static bool hasDefaultAction(int32_t keyCode);
|
||||
bool hasDefaultAction() const;
|
||||
|
||||
// Return true if this event represents a system key.
|
||||
static bool isSystemKey(int32_t keyCode);
|
||||
bool isSystemKey() const;
|
||||
|
||||
void initialize(
|
||||
int32_t deviceId,
|
||||
int32_t nature,
|
||||
|
||||
@@ -339,12 +339,14 @@ public:
|
||||
explicit AInputQueue(const android::sp<android::InputChannel>& channel);
|
||||
|
||||
/* Destroys the consumer and releases its input channel. */
|
||||
~AInputQueue();
|
||||
virtual ~AInputQueue();
|
||||
|
||||
inline android::InputConsumer& getConsumer() { return mConsumer; }
|
||||
|
||||
android::status_t consume(android::InputEvent** event);
|
||||
|
||||
virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
|
||||
|
||||
private:
|
||||
android::InputConsumer mConsumer;
|
||||
android::PreallocatedInputEventFactory mInputEventFactory;
|
||||
|
||||
@@ -20,6 +20,70 @@ void InputEvent::initialize(int32_t deviceId, int32_t nature) {
|
||||
|
||||
// class KeyEvent
|
||||
|
||||
bool KeyEvent::hasDefaultAction(int32_t keyCode) {
|
||||
switch (keyCode) {
|
||||
case KEYCODE_HOME:
|
||||
case KEYCODE_BACK:
|
||||
case KEYCODE_CALL:
|
||||
case KEYCODE_ENDCALL:
|
||||
case KEYCODE_VOLUME_UP:
|
||||
case KEYCODE_VOLUME_DOWN:
|
||||
case KEYCODE_POWER:
|
||||
case KEYCODE_CAMERA:
|
||||
case KEYCODE_HEADSETHOOK:
|
||||
case KEYCODE_MENU:
|
||||
case KEYCODE_NOTIFICATION:
|
||||
case KEYCODE_FOCUS:
|
||||
case KEYCODE_SEARCH:
|
||||
case KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KEYCODE_MEDIA_STOP:
|
||||
case KEYCODE_MEDIA_NEXT:
|
||||
case KEYCODE_MEDIA_PREVIOUS:
|
||||
case KEYCODE_MEDIA_REWIND:
|
||||
case KEYCODE_MEDIA_FAST_FORWARD:
|
||||
case KEYCODE_MUTE:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyEvent::hasDefaultAction() const {
|
||||
return hasDefaultAction(getKeyCode());
|
||||
}
|
||||
|
||||
bool KeyEvent::isSystemKey(int32_t keyCode) {
|
||||
switch (keyCode) {
|
||||
case KEYCODE_MENU:
|
||||
case KEYCODE_SOFT_RIGHT:
|
||||
case KEYCODE_HOME:
|
||||
case KEYCODE_BACK:
|
||||
case KEYCODE_CALL:
|
||||
case KEYCODE_ENDCALL:
|
||||
case KEYCODE_VOLUME_UP:
|
||||
case KEYCODE_VOLUME_DOWN:
|
||||
case KEYCODE_MUTE:
|
||||
case KEYCODE_POWER:
|
||||
case KEYCODE_HEADSETHOOK:
|
||||
case KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KEYCODE_MEDIA_STOP:
|
||||
case KEYCODE_MEDIA_NEXT:
|
||||
case KEYCODE_MEDIA_PREVIOUS:
|
||||
case KEYCODE_MEDIA_REWIND:
|
||||
case KEYCODE_MEDIA_FAST_FORWARD:
|
||||
case KEYCODE_CAMERA:
|
||||
case KEYCODE_FOCUS:
|
||||
case KEYCODE_SEARCH:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyEvent::isSystemKey() const {
|
||||
return isSystemKey(getKeyCode());
|
||||
}
|
||||
|
||||
void KeyEvent::initialize(
|
||||
int32_t deviceId,
|
||||
int32_t nature,
|
||||
|
||||
@@ -225,6 +225,15 @@ int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent) {
|
||||
|
||||
void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event,
|
||||
int handled) {
|
||||
if (!handled && ((InputEvent*)event)->getType() == INPUT_EVENT_TYPE_KEY
|
||||
&& ((KeyEvent*)event)->hasDefaultAction()) {
|
||||
// The app didn't handle this, but it may have a default action
|
||||
// associated with it. We need to hand this back to Java to be
|
||||
// executed.
|
||||
queue->doDefaultKey((KeyEvent*)event);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t res = queue->getConsumer().sendFinishedSignal();
|
||||
if (res != android::OK) {
|
||||
LOGW("Failed to send finished signal on channel '%s'. status=%d",
|
||||
|
||||
Reference in New Issue
Block a user