[Mag] Keyboard shortcut info shown when physical keyboard present
Shows keyboard shortcut info in magnification settings when a physical keyboard is present. See bug for screenshots. Hides touchscreen info in magnification settings when a touchscreen is not present. Adds ShadowInputDevice support for physical full keyboards. Bug: b/388847050 Test: Manual, atest ToggleScreenMagnificationPreferenceFragmentTest Flag: com.android.server.accessibility.enable_magnification_keyboard_control Change-Id: Ib53fbd8f929d1cc8e294f6f04bab405c9bb576a9
This commit is contained in:
@@ -5330,6 +5330,16 @@
|
||||
{4,number,integer}. Lift finger to stop magnification
|
||||
]]>
|
||||
</string>
|
||||
<!-- Instructions on the accessibility preference screen teaching the user how to control magnification with a keyboard. [CHAR LIMIT=none] -->
|
||||
<string name="accessibility_screen_magnification_keyboard_summary">
|
||||
<![CDATA[
|
||||
<b>To zoom with the keyboard:</b><br/>
|
||||
{0,number,integer}. Use the shortcut to start magnification<br/>
|
||||
{1,number,integer}. Hold down <xliff:g id="meta1">%1$s</xliff:g> and <xliff:g id="alt1">%2$s</xliff:g> and press + or - to zoom in or out<br/>
|
||||
{2,number,integer}. Hold down <xliff:g id="meta2">%3$s</xliff:g> and <xliff:g id="alt2">%4$s</xliff:g> and press the arrow keys to move around the screen<br/>
|
||||
{3,number,integer}. Use the shortcut to stop magnification
|
||||
]]>
|
||||
</string>
|
||||
<!-- Instructions on the accessibility preference screen teaching the user how to interact with screen magnification when one finger panning feature is turned off. [CHAR LIMIT=none] -->
|
||||
<string name="accessibility_screen_magnification_summary_one_finger_panning_off">
|
||||
<![CDATA[
|
||||
|
@@ -35,6 +35,7 @@ import android.os.Bundle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.view.InputDevice;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -231,9 +232,32 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
|
||||
if (!arguments.containsKey(AccessibilitySettings.EXTRA_HTML_DESCRIPTION)
|
||||
&& !Flags.enableMagnificationOneFingerPanningGesture()) {
|
||||
String summary = MessageFormat.format(
|
||||
context.getString(R.string.accessibility_screen_magnification_summary),
|
||||
new Object[]{1, 2, 3, 4, 5});
|
||||
String summary = "";
|
||||
boolean hasTouchscreen = hasTouchscreen();
|
||||
if (Flags.enableMagnificationKeyboardControl() && hasHardKeyboard()) {
|
||||
// Include the keyboard summary when a keyboard is plugged in.
|
||||
final String meta = context.getString(R.string.modifier_keys_meta);
|
||||
final String alt = context.getString(R.string.modifier_keys_alt);
|
||||
summary += MessageFormat.format(
|
||||
context.getString(
|
||||
R.string.accessibility_screen_magnification_keyboard_summary,
|
||||
meta, alt, meta, alt),
|
||||
new Object[]{1, 2, 3, 4});
|
||||
if (hasTouchscreen) {
|
||||
// Add a newline before the touchscreen text.
|
||||
summary += "<br/><br/>";
|
||||
}
|
||||
|
||||
}
|
||||
if (hasTouchscreen || TextUtils.isEmpty(summary)) {
|
||||
// Always show the touchscreen summary if there is no summary yet, even if the
|
||||
// touchscreen is missing.
|
||||
// If the keyboard summary is present and there is no touchscreen, then we can
|
||||
// ignore the touchscreen summary.
|
||||
summary += MessageFormat.format(
|
||||
context.getString(R.string.accessibility_screen_magnification_summary),
|
||||
new Object[]{1, 2, 3, 4, 5});
|
||||
}
|
||||
arguments.putCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, summary);
|
||||
}
|
||||
|
||||
@@ -610,6 +634,25 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
getPrefContext(), MAGNIFICATION_CONTROLLER_NAME);
|
||||
}
|
||||
|
||||
private boolean hasHardKeyboard() {
|
||||
final int[] devices = InputDevice.getDeviceIds();
|
||||
for (int i = 0; i < devices.length; i++) {
|
||||
InputDevice device = InputDevice.getDevice(devices[i]);
|
||||
if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasTouchscreen() {
|
||||
return getPackageManager()
|
||||
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
|
||||
|| getPackageManager().hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);
|
||||
}
|
||||
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
// LINT.IfChange(search_data)
|
||||
|
@@ -51,6 +51,7 @@ import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.view.InputDevice;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
@@ -68,6 +69,7 @@ import com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
|
||||
import com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
|
||||
import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
|
||||
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
|
||||
import com.android.settings.testutils.shadow.ShadowInputDevice;
|
||||
import com.android.settings.testutils.shadow.ShadowStorageManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
@@ -169,6 +171,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowDeviceConfig.reset();
|
||||
ShadowInputDevice.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -671,6 +674,36 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
assertThat(fragment.getCurrentHtmlDescription().toString()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_KEYBOARD_CONTROL)
|
||||
public void getCurrentHtmlDescription_doesNotIncludeKeyboardInfoIfNoKeyboardAttached() {
|
||||
ToggleScreenMagnificationPreferenceFragment fragment =
|
||||
mFragController.create(
|
||||
R.id.main_content, /* bundle= */ null).start().resume().get();
|
||||
|
||||
String htmlDescription = fragment.getCurrentHtmlDescription().toString();
|
||||
assertThat(htmlDescription).isNotEmpty();
|
||||
assertThat(htmlDescription).doesNotContain("keyboard");
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_KEYBOARD_CONTROL)
|
||||
@Config(shadows = ShadowInputDevice.class)
|
||||
public void getCurrentHtmlDescription_includesKeyboardInfoIfKeyboardAttached() {
|
||||
int deviceId = 1;
|
||||
ShadowInputDevice.sDeviceIds = new int[]{deviceId};
|
||||
InputDevice device = ShadowInputDevice.makeFullKeyboardInputDevicebyId(deviceId);
|
||||
ShadowInputDevice.addDevice(deviceId, device);
|
||||
|
||||
ToggleScreenMagnificationPreferenceFragment fragment =
|
||||
mFragController.create(
|
||||
R.id.main_content, /* bundle= */ null).start().resume().get();
|
||||
|
||||
String htmlDescription = fragment.getCurrentHtmlDescription().toString();
|
||||
assertThat(htmlDescription).isNotEmpty();
|
||||
assertThat(htmlDescription).contains("keyboard");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_magnificationEnabled_returnShortcutOnWithSummary() {
|
||||
mShadowAccessibilityManager.setAccessibilityShortcutTargets(
|
||||
|
@@ -37,6 +37,8 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
|
||||
|
||||
private int mSources;
|
||||
|
||||
private boolean mIsFullKeyboard;
|
||||
|
||||
@Implementation
|
||||
protected static int[] getDeviceIds() {
|
||||
return sDeviceIds;
|
||||
@@ -62,25 +64,10 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
|
||||
return mDeviceId;
|
||||
}
|
||||
|
||||
public static InputDevice makeInputDevicebyId(int id) {
|
||||
final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
|
||||
final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
|
||||
shadowInputDevice.setId(id);
|
||||
return inputDevice;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
mDeviceId = id;
|
||||
}
|
||||
|
||||
public static InputDevice makeInputDevicebyIdWithSources(int id, int sources) {
|
||||
final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
|
||||
final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
|
||||
shadowInputDevice.setId(id);
|
||||
shadowInputDevice.setSources(sources);
|
||||
return inputDevice;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public int getSources() {
|
||||
return mSources;
|
||||
@@ -89,4 +76,42 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
|
||||
public void setSources(int sources) {
|
||||
mSources = sources;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isFullKeyboard() {
|
||||
return mIsFullKeyboard;
|
||||
}
|
||||
|
||||
public void setFullKeyboard(boolean isFullKeyboard) {
|
||||
mIsFullKeyboard = isFullKeyboard;
|
||||
}
|
||||
|
||||
public static InputDevice makeInputDevicebyId(int id) {
|
||||
final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
|
||||
final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
|
||||
shadowInputDevice.setId(id);
|
||||
return inputDevice;
|
||||
}
|
||||
|
||||
public static InputDevice makeInputDevicebyIdWithSources(int id, int sources) {
|
||||
final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
|
||||
final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
|
||||
shadowInputDevice.setId(id);
|
||||
shadowInputDevice.setSources(sources);
|
||||
return inputDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full keyboard input device shadow.
|
||||
* @param id The ID to use. If the ID is < 1, the device is considered virtual.
|
||||
* @return The shadow InputDevice
|
||||
*/
|
||||
public static InputDevice makeFullKeyboardInputDevicebyId(int id) {
|
||||
final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
|
||||
final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
|
||||
shadowInputDevice.setId(id);
|
||||
shadowInputDevice.setFullKeyboard(true);
|
||||
shadowInputDevice.setSources(InputDevice.SOURCE_KEYBOARD);
|
||||
return inputDevice;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user