Skip to content

Commit cf39bdf

Browse files
author
Jeff Brown
committed
Add support for switching between multiple keyboard layouts.
Also show a notification when an external keyboard is connected and does not have a keyboard layout selected yet. Bug: 6405203 Change-Id: Id0ac6d83b3b381f8a236b2244a04c9acb203db3c
1 parent 51f2430 commit cf39bdf

File tree

14 files changed

+869
-231
lines changed

14 files changed

+869
-231
lines changed

core/java/android/hardware/input/IInputManager.aidl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ interface IInputManager {
4141
// Keyboard layouts configuration.
4242
KeyboardLayout[] getKeyboardLayouts();
4343
KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
44-
String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
45-
void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
44+
String getCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
45+
void setCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
46+
String keyboardLayoutDescriptor);
47+
String[] getKeyboardLayoutsForInputDevice(String inputDeviceDescriptor);
48+
void addKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
49+
String keyboardLayoutDescriptor);
50+
void removeKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
4651
String keyboardLayoutDescriptor);
4752

4853
// Registers an input devices changed listener.

core/java/android/hardware/input/InputManager.java

Lines changed: 128 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package android.hardware.input;
1818

19+
import com.android.internal.util.ArrayUtils;
20+
1921
import android.annotation.SdkConstant;
2022
import android.annotation.SdkConstant.SdkConstantType;
2123
import android.content.Context;
@@ -216,6 +218,41 @@ public InputDevice getInputDevice(int id) {
216218
}
217219
}
218220

221+
/**
222+
* Gets information about the input device with the specified descriptor.
223+
* @param descriptor The input device descriptor.
224+
* @return The input device or null if not found.
225+
* @hide
226+
*/
227+
public InputDevice getInputDeviceByDescriptor(String descriptor) {
228+
if (descriptor == null) {
229+
throw new IllegalArgumentException("descriptor must not be null.");
230+
}
231+
232+
synchronized (mInputDevicesLock) {
233+
populateInputDevicesLocked();
234+
235+
int numDevices = mInputDevices.size();
236+
for (int i = 0; i < numDevices; i++) {
237+
InputDevice inputDevice = mInputDevices.valueAt(i);
238+
if (inputDevice == null) {
239+
int id = mInputDevices.keyAt(i);
240+
try {
241+
inputDevice = mIm.getInputDevice(id);
242+
} catch (RemoteException ex) {
243+
// Ignore the problem for the purposes of this method.
244+
continue;
245+
}
246+
mInputDevices.setValueAt(i, inputDevice);
247+
}
248+
if (descriptor.equals(inputDevice.getDescriptor())) {
249+
return inputDevice;
250+
}
251+
}
252+
return null;
253+
}
254+
}
255+
219256
/**
220257
* Gets the ids of all input devices in the system.
221258
* @return The input device ids.
@@ -332,50 +369,129 @@ public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
332369
}
333370

334371
/**
335-
* Gets the keyboard layout descriptor for the specified input device.
372+
* Gets the current keyboard layout descriptor for the specified input device.
336373
*
337374
* @param inputDeviceDescriptor The input device descriptor.
338-
* @return The keyboard layout descriptor, or null if unknown or if the default
339-
* keyboard layout will be used.
375+
* @return The keyboard layout descriptor, or null if no keyboard layout has been set.
340376
*
341377
* @hide
342378
*/
343-
public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
379+
public String getCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
344380
if (inputDeviceDescriptor == null) {
345381
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
346382
}
347383

348384
try {
349-
return mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor);
385+
return mIm.getCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor);
350386
} catch (RemoteException ex) {
351-
Log.w(TAG, "Could not get keyboard layout for input device.", ex);
387+
Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
352388
return null;
353389
}
354390
}
355391

356392
/**
357-
* Sets the keyboard layout descriptor for the specified input device.
393+
* Sets the current keyboard layout descriptor for the specified input device.
394+
* <p>
395+
* This method may have the side-effect of causing the input device in question
396+
* to be reconfigured.
397+
* </p>
398+
*
399+
* @param inputDeviceDescriptor The input device descriptor.
400+
* @param keyboardLayoutDescriptor The keyboard layout descriptor to use, must not be null.
401+
*
402+
* @hide
403+
*/
404+
public void setCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
405+
String keyboardLayoutDescriptor) {
406+
if (inputDeviceDescriptor == null) {
407+
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
408+
}
409+
if (keyboardLayoutDescriptor == null) {
410+
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
411+
}
412+
413+
try {
414+
mIm.setCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor,
415+
keyboardLayoutDescriptor);
416+
} catch (RemoteException ex) {
417+
Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
418+
}
419+
}
420+
421+
/**
422+
* Gets all keyboard layout descriptors that are enabled for the specified input device.
423+
*
424+
* @param inputDeviceDescriptor The input device descriptor.
425+
* @return The keyboard layout descriptors.
426+
*
427+
* @hide
428+
*/
429+
public String[] getKeyboardLayoutsForInputDevice(String inputDeviceDescriptor) {
430+
if (inputDeviceDescriptor == null) {
431+
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
432+
}
433+
434+
try {
435+
return mIm.getKeyboardLayoutsForInputDevice(inputDeviceDescriptor);
436+
} catch (RemoteException ex) {
437+
Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
438+
return ArrayUtils.emptyArray(String.class);
439+
}
440+
}
441+
442+
/**
443+
* Adds the keyboard layout descriptor for the specified input device.
358444
* <p>
359445
* This method may have the side-effect of causing the input device in question
360446
* to be reconfigured.
361447
* </p>
362448
*
363449
* @param inputDeviceDescriptor The input device descriptor.
364-
* @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove
365-
* the mapping so that the default keyboard layout will be used for the input device.
450+
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to add.
366451
*
367452
* @hide
368453
*/
369-
public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
454+
public void addKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
370455
String keyboardLayoutDescriptor) {
371456
if (inputDeviceDescriptor == null) {
372457
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
373458
}
459+
if (keyboardLayoutDescriptor == null) {
460+
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
461+
}
462+
463+
try {
464+
mIm.addKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
465+
} catch (RemoteException ex) {
466+
Log.w(TAG, "Could not add keyboard layout for input device.", ex);
467+
}
468+
}
469+
470+
/**
471+
* Removes the keyboard layout descriptor for the specified input device.
472+
* <p>
473+
* This method may have the side-effect of causing the input device in question
474+
* to be reconfigured.
475+
* </p>
476+
*
477+
* @param inputDeviceDescriptor The input device descriptor.
478+
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to remove.
479+
*
480+
* @hide
481+
*/
482+
public void removeKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
483+
String keyboardLayoutDescriptor) {
484+
if (inputDeviceDescriptor == null) {
485+
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
486+
}
487+
if (keyboardLayoutDescriptor == null) {
488+
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
489+
}
374490

375491
try {
376-
mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
492+
mIm.removeKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
377493
} catch (RemoteException ex) {
378-
Log.w(TAG, "Could not set keyboard layout for input device.", ex);
494+
Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
379495
}
380496
}
381497

core/java/android/view/WindowManagerPolicy.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@ public FakeWindow addFakeWindow(Looper looper,
386386
*/
387387
public InputChannel monitorInput(String name);
388388

389+
/**
390+
* Switch the keyboard layout for the given device.
391+
* Direction should be +1 or -1 to go to the next or previous keyboard layout.
392+
*/
393+
public void switchKeyboardLayout(int deviceId, int direction);
394+
389395
public void shutdown();
390396
public void rebootSafeMode();
391397
}
986 Bytes
Loading
756 Bytes
Loading
1.24 KB
Loading

core/res/res/values/public.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,8 @@
14891489
<java-symbol type="string" name="low_internal_storage_view_title" />
14901490
<java-symbol type="string" name="report" />
14911491
<java-symbol type="string" name="select_input_method" />
1492+
<java-symbol type="string" name="select_keyboard_layout_notification_title" />
1493+
<java-symbol type="string" name="select_keyboard_layout_notification_message" />
14921494
<java-symbol type="string" name="smv_application" />
14931495
<java-symbol type="string" name="smv_process" />
14941496
<java-symbol type="string" name="tethered_notification_message" />
@@ -1580,6 +1582,7 @@
15801582
<java-symbol type="drawable" name="expander_ic_minimized" />
15811583
<java-symbol type="drawable" name="ic_menu_archive" />
15821584
<java-symbol type="drawable" name="ic_menu_goto" />
1585+
<java-symbol type="drawable" name="ic_settings_language" />
15831586
<java-symbol type="drawable" name="title_bar_medium" />
15841587
<java-symbol type="id" name="body" />
15851588
<java-symbol type="string" name="fast_scroll_alphabet" />

core/res/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3092,6 +3092,11 @@
30923092
<!-- Title of the physical keyboard category in the input method selector [CHAR LIMIT=10] -->
30933093
<string name="hardware">Hardware</string>
30943094

3095+
<!-- Title of the notification to prompt the user to select a keyboard layout. -->
3096+
<string name="select_keyboard_layout_notification_title">Select keyboard layout</string>
3097+
<!-- Message of the notification to prompt the user to select a keyboard layout. -->
3098+
<string name="select_keyboard_layout_notification_message">Touch to select a keyboard layout.</string>
3099+
30953100
<string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
30963101
<string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
30973102

data/keyboards/Generic.kcm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ key SPACE {
252252
label: ' '
253253
base: ' '
254254
alt, meta: fallback SEARCH
255+
ctrl: fallback LANGUAGE_SWITCH
255256
}
256257

257258
key ENTER {

data/keyboards/Virtual.kcm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ key SPACE {
249249
label: ' '
250250
base: ' '
251251
alt, meta: fallback SEARCH
252+
ctrl: fallback LANGUAGE_SWITCH
252253
}
253254

254255
key ENTER {

0 commit comments

Comments
 (0)