diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0f9a2ac98a38c..d363bf4fbb1d5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -81,6 +81,7 @@ import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Locale;
/**
* The top of a view hierarchy, implementing the needed protocol between View
@@ -230,6 +231,8 @@ public final class ViewRootImpl implements ViewParent,
InputStage mFirstPostImeInputStage;
SyntheticInputStage mSyntheticInputStage;
+ boolean mFlipControllerFallbackKeys;
+
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -366,6 +369,8 @@ public final class ViewRootImpl implements ViewParent,
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
+ mFlipControllerFallbackKeys =
+ context.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mAttachInfo.mScreenOn = powerManager.isScreenOn();
@@ -2873,8 +2878,11 @@ public final class ViewRootImpl implements ViewParent,
mView.dispatchConfigurationChanged(config);
}
}
+
+ mFlipControllerFallbackKeys =
+ mContext.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
}
-
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -3904,6 +3912,7 @@ public final class ViewRootImpl implements ViewParent,
private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
private final SyntheticTouchNavigationHandler mTouchNavigation =
new SyntheticTouchNavigationHandler();
+ private final SyntheticKeyHandler mKeys = new SyntheticKeyHandler();
public SyntheticInputStage() {
super(null);
@@ -3926,7 +3935,12 @@ public final class ViewRootImpl implements ViewParent,
mTouchNavigation.process(event);
return FINISH_HANDLED;
}
+ } else if (q.mEvent instanceof KeyEvent) {
+ if (mKeys.process((KeyEvent) q.mEvent)) {
+ return FINISH_HANDLED;
+ }
}
+
return FORWARD;
}
@@ -4802,6 +4816,63 @@ public final class ViewRootImpl implements ViewParent,
};
}
+ final class SyntheticKeyHandler {
+
+ public boolean process(KeyEvent event) {
+ // In some locales (like Japan) controllers use B for confirm and A for back, rather
+ // than vice versa, so we need to special case this here since the input system itself
+ // is not locale-aware.
+ int keyCode;
+ switch(event.getKeyCode()) {
+ case KeyEvent.KEYCODE_BUTTON_A:
+ case KeyEvent.KEYCODE_BUTTON_C:
+ case KeyEvent.KEYCODE_BUTTON_X:
+ case KeyEvent.KEYCODE_BUTTON_Z:
+ keyCode = mFlipControllerFallbackKeys ?
+ KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_DPAD_CENTER;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_B:
+ case KeyEvent.KEYCODE_BUTTON_Y:
+ keyCode = mFlipControllerFallbackKeys ?
+ KeyEvent.KEYCODE_DPAD_CENTER : KeyEvent.KEYCODE_BACK;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_THUMBL:
+ case KeyEvent.KEYCODE_BUTTON_THUMBR:
+ case KeyEvent.KEYCODE_BUTTON_START:
+ case KeyEvent.KEYCODE_BUTTON_1:
+ case KeyEvent.KEYCODE_BUTTON_2:
+ case KeyEvent.KEYCODE_BUTTON_3:
+ case KeyEvent.KEYCODE_BUTTON_4:
+ case KeyEvent.KEYCODE_BUTTON_5:
+ case KeyEvent.KEYCODE_BUTTON_6:
+ case KeyEvent.KEYCODE_BUTTON_7:
+ case KeyEvent.KEYCODE_BUTTON_8:
+ case KeyEvent.KEYCODE_BUTTON_9:
+ case KeyEvent.KEYCODE_BUTTON_10:
+ case KeyEvent.KEYCODE_BUTTON_11:
+ case KeyEvent.KEYCODE_BUTTON_12:
+ case KeyEvent.KEYCODE_BUTTON_13:
+ case KeyEvent.KEYCODE_BUTTON_14:
+ case KeyEvent.KEYCODE_BUTTON_15:
+ case KeyEvent.KEYCODE_BUTTON_16:
+ keyCode = KeyEvent.KEYCODE_DPAD_CENTER;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_SELECT:
+ case KeyEvent.KEYCODE_BUTTON_MODE:
+ keyCode = KeyEvent.KEYCODE_MENU;
+ default:
+ return false;
+ }
+
+ enqueueInputEvent(new KeyEvent(event.getDownTime(), event.getEventTime(),
+ event.getAction(), keyCode, event.getRepeatCount(), event.getMetaState(),
+ event.getScanCode(), event.getFlags() | KeyEvent.FLAG_FALLBACK,
+ event.getSource()));
+ return true;
+ }
+
+ }
+
/**
* Returns true if the key is used for keyboard navigation.
* @param keyEvent The key event.
diff --git a/core/res/res/values-ja/bools.xml b/core/res/res/values-ja/bools.xml
new file mode 100644
index 0000000000000..59cf744532eb5
--- /dev/null
+++ b/core/res/res/values-ja/bools.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ true
+
+
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 18e4f2f9b3a82..10a5d851fac30 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -26,4 +26,5 @@
true
true
true
+ false
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7b2a1b4c5601c..39e712744f0bd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -285,6 +285,7 @@
+
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 01d22ee691780..695a74f838101 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -477,128 +477,4 @@ key ESCAPE {
ctrl: fallback MENU
}
-### Gamepad buttons ###
-
-key BUTTON_A {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_B {
- base: fallback BACK
-}
-
-key BUTTON_C {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_X {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_Y {
- base: fallback BACK
-}
-
-key BUTTON_Z {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_L1 {
- base: none
-}
-
-key BUTTON_R1 {
- base: none
-}
-
-key BUTTON_L2 {
- base: none
-}
-
-key BUTTON_R2 {
- base: none
-}
-
-key BUTTON_THUMBL {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_THUMBR {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_START {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_SELECT {
- base: fallback MENU
-}
-
-key BUTTON_MODE {
- base: fallback MENU
-}
-
-key BUTTON_1 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_2 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_3 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_4 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_5 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_6 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_7 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_8 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_9 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_10 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_11 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_12 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_13 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_14 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_15 {
- base: fallback DPAD_CENTER
-}
-
-key BUTTON_16 {
- base: fallback DPAD_CENTER
-}
+### Gamepad buttons are handled by the view root ###