Merge "Add API for IME control by Accessibility Services."
This commit is contained in:
@@ -2625,6 +2625,7 @@ package android.accessibilityservice {
|
||||
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
|
||||
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
|
||||
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
|
||||
method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
|
||||
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
|
||||
method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
@@ -2683,6 +2684,18 @@ package android.accessibilityservice {
|
||||
method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
|
||||
}
|
||||
|
||||
public static final class AccessibilityService.SoftKeyboardController {
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
|
||||
method public int getShowMode();
|
||||
method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public boolean setShowMode(int);
|
||||
}
|
||||
|
||||
public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
|
||||
method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
|
||||
}
|
||||
|
||||
public class AccessibilityServiceInfo implements android.os.Parcelable {
|
||||
ctor public AccessibilityServiceInfo();
|
||||
method public static java.lang.String capabilityToString(int);
|
||||
|
||||
@@ -2727,6 +2727,7 @@ package android.accessibilityservice {
|
||||
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
|
||||
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
|
||||
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
|
||||
method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
|
||||
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
|
||||
method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
@@ -2785,6 +2786,18 @@ package android.accessibilityservice {
|
||||
method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
|
||||
}
|
||||
|
||||
public static final class AccessibilityService.SoftKeyboardController {
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
|
||||
method public int getShowMode();
|
||||
method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public boolean setShowMode(int);
|
||||
}
|
||||
|
||||
public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
|
||||
method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
|
||||
}
|
||||
|
||||
public class AccessibilityServiceInfo implements android.os.Parcelable {
|
||||
ctor public AccessibilityServiceInfo();
|
||||
method public static java.lang.String capabilityToString(int);
|
||||
|
||||
@@ -2625,6 +2625,7 @@ package android.accessibilityservice {
|
||||
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
|
||||
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
|
||||
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
|
||||
method public final android.accessibilityservice.AccessibilityService.SoftKeyboardController getSoftKeyboardController();
|
||||
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
|
||||
method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
|
||||
method public final android.os.IBinder onBind(android.content.Intent);
|
||||
@@ -2683,6 +2684,18 @@ package android.accessibilityservice {
|
||||
method public abstract void onMagnificationChanged(android.accessibilityservice.AccessibilityService.MagnificationController, android.graphics.Region, float, float, float);
|
||||
}
|
||||
|
||||
public static final class AccessibilityService.SoftKeyboardController {
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public void addOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener, android.os.Handler);
|
||||
method public int getShowMode();
|
||||
method public boolean removeOnShowModeChangedListener(android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener);
|
||||
method public boolean setShowMode(int);
|
||||
}
|
||||
|
||||
public static abstract interface AccessibilityService.SoftKeyboardController.OnShowModeChangedListener {
|
||||
method public abstract void onShowModeChanged(android.accessibilityservice.AccessibilityService.SoftKeyboardController, int);
|
||||
}
|
||||
|
||||
public class AccessibilityServiceInfo implements android.os.Parcelable {
|
||||
ctor public AccessibilityServiceInfo();
|
||||
method public static java.lang.String capabilityToString(int);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.accessibilityservice;
|
||||
|
||||
import android.accessibilityservice.GestureDescription.MotionEventGenerator;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Service;
|
||||
@@ -29,6 +30,7 @@ import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
@@ -46,6 +48,8 @@ import android.view.accessibility.AccessibilityWindowInfo;
|
||||
import com.android.internal.os.HandlerCaller;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -363,9 +367,26 @@ public abstract class AccessibilityService extends Service {
|
||||
public boolean onKeyEvent(KeyEvent event);
|
||||
public void onMagnificationChanged(@NonNull Region region,
|
||||
float scale, float centerX, float centerY);
|
||||
public void onSoftKeyboardShowModeChanged(int showMode);
|
||||
public void onPerformGestureResult(int sequence, boolean completedSuccessfully);
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotations for Soft Keyboard show modes so tools can catch invalid show modes.
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({SHOW_MODE_AUTO, SHOW_MODE_HIDDEN})
|
||||
public @interface SoftKeyboardShowMode {};
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int SHOW_MODE_AUTO = 0;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final int SHOW_MODE_HIDDEN = 1;
|
||||
|
||||
private int mConnectionId;
|
||||
|
||||
private AccessibilityServiceInfo mInfo;
|
||||
@@ -375,6 +396,7 @@ public abstract class AccessibilityService extends Service {
|
||||
private WindowManager mWindowManager;
|
||||
|
||||
private MagnificationController mMagnificationController;
|
||||
private SoftKeyboardController mSoftKeyboardController;
|
||||
|
||||
private int mGestureStatusCallbackSequence;
|
||||
|
||||
@@ -563,10 +585,12 @@ public abstract class AccessibilityService extends Service {
|
||||
*/
|
||||
@NonNull
|
||||
public final MagnificationController getMagnificationController() {
|
||||
if (mMagnificationController == null) {
|
||||
mMagnificationController = new MagnificationController(this);
|
||||
synchronized (mLock) {
|
||||
if (mMagnificationController == null) {
|
||||
mMagnificationController = new MagnificationController(this, mLock);
|
||||
}
|
||||
return mMagnificationController;
|
||||
}
|
||||
return mMagnificationController;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,17 +694,21 @@ public abstract class AccessibilityService extends Service {
|
||||
* first magnification listener.
|
||||
*/
|
||||
private ArrayMap<OnMagnificationChangedListener, Handler> mListeners;
|
||||
private final Object mLock;
|
||||
|
||||
MagnificationController(@NonNull AccessibilityService service) {
|
||||
MagnificationController(@NonNull AccessibilityService service, @NonNull Object lock) {
|
||||
mService = service;
|
||||
mLock = lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is connected.
|
||||
*/
|
||||
void onServiceConnected() {
|
||||
if (mListeners != null && !mListeners.isEmpty()) {
|
||||
setMagnificationCallbackEnabled(true);
|
||||
synchronized (mLock) {
|
||||
if (mListeners != null && !mListeners.isEmpty()) {
|
||||
setMagnificationCallbackEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,17 +735,19 @@ public abstract class AccessibilityService extends Service {
|
||||
*/
|
||||
public void addListener(@NonNull OnMagnificationChangedListener listener,
|
||||
@Nullable Handler handler) {
|
||||
if (mListeners == null) {
|
||||
mListeners = new ArrayMap<>();
|
||||
}
|
||||
synchronized (mLock) {
|
||||
if (mListeners == null) {
|
||||
mListeners = new ArrayMap<>();
|
||||
}
|
||||
|
||||
final boolean shouldEnableCallback = mListeners.isEmpty();
|
||||
mListeners.put(listener, handler);
|
||||
final boolean shouldEnableCallback = mListeners.isEmpty();
|
||||
mListeners.put(listener, handler);
|
||||
|
||||
if (shouldEnableCallback) {
|
||||
// This may fail if the service is not connected yet, but if we
|
||||
// still have listeners when it connects then we can try again.
|
||||
setMagnificationCallbackEnabled(true);
|
||||
if (shouldEnableCallback) {
|
||||
// This may fail if the service is not connected yet, but if we
|
||||
// still have listeners when it connects then we can try again.
|
||||
setMagnificationCallbackEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,19 +764,21 @@ public abstract class AccessibilityService extends Service {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int keyIndex = mListeners.indexOfKey(listener);
|
||||
final boolean hasKey = keyIndex >= 0;
|
||||
if (hasKey) {
|
||||
mListeners.removeAt(keyIndex);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final int keyIndex = mListeners.indexOfKey(listener);
|
||||
final boolean hasKey = keyIndex >= 0;
|
||||
if (hasKey) {
|
||||
mListeners.removeAt(keyIndex);
|
||||
}
|
||||
|
||||
if (hasKey && mListeners.isEmpty()) {
|
||||
// We just removed the last listener, so we don't need
|
||||
// callbacks from the service anymore.
|
||||
setMagnificationCallbackEnabled(false);
|
||||
}
|
||||
if (hasKey && mListeners.isEmpty()) {
|
||||
// We just removed the last listener, so we don't need
|
||||
// callbacks from the service anymore.
|
||||
setMagnificationCallbackEnabled(false);
|
||||
}
|
||||
|
||||
return hasKey;
|
||||
return hasKey;
|
||||
}
|
||||
}
|
||||
|
||||
private void setMagnificationCallbackEnabled(boolean enabled) {
|
||||
@@ -768,17 +800,19 @@ public abstract class AccessibilityService extends Service {
|
||||
*/
|
||||
void dispatchMagnificationChanged(final @NonNull Region region, final float scale,
|
||||
final float centerX, final float centerY) {
|
||||
if (mListeners == null || mListeners.isEmpty()) {
|
||||
Slog.d(LOG_TAG, "Received magnification changed "
|
||||
+ "callback with no listeners registered!");
|
||||
setMagnificationCallbackEnabled(false);
|
||||
return;
|
||||
}
|
||||
final ArrayMap<OnMagnificationChangedListener, Handler> entries;
|
||||
synchronized (mLock) {
|
||||
if (mListeners == null || mListeners.isEmpty()) {
|
||||
Slog.d(LOG_TAG, "Received magnification changed "
|
||||
+ "callback with no listeners registered!");
|
||||
setMagnificationCallbackEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listeners may remove themselves. Perform a shallow copy to avoid
|
||||
// concurrent modification.
|
||||
final ArrayMap<OnMagnificationChangedListener, Handler> entries =
|
||||
new ArrayMap<>(mListeners);
|
||||
// Listeners may remove themselves. Perform a shallow copy to avoid concurrent
|
||||
// modification.
|
||||
entries = new ArrayMap<>(mListeners);
|
||||
}
|
||||
|
||||
for (int i = 0, count = entries.size(); i < count; i++) {
|
||||
final OnMagnificationChangedListener listener = entries.keyAt(i);
|
||||
@@ -1010,6 +1044,243 @@ public abstract class AccessibilityService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the soft keyboard controller, which may be used to query and modify the soft keyboard
|
||||
* show mode.
|
||||
*
|
||||
* @return the soft keyboard controller
|
||||
*/
|
||||
@NonNull
|
||||
public final SoftKeyboardController getSoftKeyboardController() {
|
||||
synchronized (mLock) {
|
||||
if (mSoftKeyboardController == null) {
|
||||
mSoftKeyboardController = new SoftKeyboardController(this, mLock);
|
||||
}
|
||||
return mSoftKeyboardController;
|
||||
}
|
||||
}
|
||||
|
||||
private void onSoftKeyboardShowModeChanged(int showMode) {
|
||||
if (mSoftKeyboardController != null) {
|
||||
mSoftKeyboardController.dispatchSoftKeyboardShowModeChanged(showMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to control and query the soft keyboard show mode.
|
||||
*/
|
||||
public static final class SoftKeyboardController {
|
||||
private final AccessibilityService mService;
|
||||
|
||||
/**
|
||||
* Map of listeners to their handlers. Lazily created when adding the first
|
||||
* soft keyboard change listener.
|
||||
*/
|
||||
private ArrayMap<OnShowModeChangedListener, Handler> mListeners;
|
||||
private final Object mLock;
|
||||
|
||||
SoftKeyboardController(@NonNull AccessibilityService service, @NonNull Object lock) {
|
||||
mService = service;
|
||||
mLock = lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is connected.
|
||||
*/
|
||||
void onServiceConnected() {
|
||||
synchronized(mLock) {
|
||||
if (mListeners != null && !mListeners.isEmpty()) {
|
||||
setSoftKeyboardCallbackEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified change listener to the list of show mode change listeners. The
|
||||
* callback will occur on the service's main thread. Listener is not called on registration.
|
||||
*/
|
||||
public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
|
||||
addOnShowModeChangedListener(listener, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified change listener to the list of soft keyboard show mode change
|
||||
* listeners. The callback will occur on the specified {@link Handler}'s thread, or on the
|
||||
* services's main thread if the handler is {@code null}.
|
||||
*
|
||||
* @param listener the listener to add, must be non-null
|
||||
* @param handler the handler on which to callback should execute, or {@code null} to
|
||||
* execute on the service's main thread
|
||||
*/
|
||||
public void addOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener,
|
||||
@Nullable Handler handler) {
|
||||
synchronized (mLock) {
|
||||
if (mListeners == null) {
|
||||
mListeners = new ArrayMap<>();
|
||||
}
|
||||
|
||||
final boolean shouldEnableCallback = mListeners.isEmpty();
|
||||
mListeners.put(listener, handler);
|
||||
|
||||
if (shouldEnableCallback) {
|
||||
// This may fail if the service is not connected yet, but if we still have
|
||||
// listeners when it connects, we can try again.
|
||||
setSoftKeyboardCallbackEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all instances of the specified change listener from teh list of magnification
|
||||
* change listeners.
|
||||
*
|
||||
* @param listener the listener to remove, must be non-null
|
||||
* @return {@code true} if at least one instance of the listener was removed
|
||||
*/
|
||||
public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
|
||||
if (mListeners == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
final int keyIndex = mListeners.indexOfKey(listener);
|
||||
final boolean hasKey = keyIndex >= 0;
|
||||
if (hasKey) {
|
||||
mListeners.removeAt(keyIndex);
|
||||
}
|
||||
|
||||
if (hasKey && mListeners.isEmpty()) {
|
||||
// We just removed the last listener, so we don't need callbacks from the
|
||||
// service anymore.
|
||||
setSoftKeyboardCallbackEnabled(false);
|
||||
}
|
||||
|
||||
return hasKey;
|
||||
}
|
||||
}
|
||||
|
||||
private void setSoftKeyboardCallbackEnabled(boolean enabled) {
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance().getConnection(
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.setSoftKeyboardCallbackEnabled(enabled);
|
||||
} catch (RemoteException re) {
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the soft keyboard show mode change to any registered listeners. This should
|
||||
* be called on the service's main thread.
|
||||
*/
|
||||
void dispatchSoftKeyboardShowModeChanged(final int showMode) {
|
||||
final ArrayMap<OnShowModeChangedListener, Handler> entries;
|
||||
synchronized (mLock) {
|
||||
if (mListeners == null || mListeners.isEmpty()) {
|
||||
Slog.d(LOG_TAG, "Received soft keyboard show mode changed callback"
|
||||
+ " with no listeners registered!");
|
||||
setSoftKeyboardCallbackEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listeners may remove themselves. Perform a shallow copy to avoid concurrent
|
||||
// modification.
|
||||
entries = new ArrayMap<>(mListeners);
|
||||
}
|
||||
|
||||
for (int i = 0, count = entries.size(); i < count; i++) {
|
||||
final OnShowModeChangedListener listener = entries.keyAt(i);
|
||||
final Handler handler = entries.valueAt(i);
|
||||
if (handler != null) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onShowModeChanged(SoftKeyboardController.this, showMode);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// We're already on the main thread, just run the listener.
|
||||
listener.onShowModeChanged(this, showMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the show mode of the soft keyboard. The default show mode is
|
||||
* {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
|
||||
* input field is focused. An AccessibilityService can also request the show mode
|
||||
* {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
|
||||
*
|
||||
* @return the current soft keyboard show mode
|
||||
*
|
||||
* @see Settings#Secure#SHOW_MODE_AUTO
|
||||
* @see Settings#Secure#SHOW_MODE_HIDDEN
|
||||
*/
|
||||
@SoftKeyboardShowMode
|
||||
public int getShowMode() {
|
||||
try {
|
||||
return Settings.Secure.getInt(mService.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
|
||||
} catch (Settings.SettingNotFoundException e) {
|
||||
Log.v(LOG_TAG, "Failed to obtain the soft keyboard mode", e);
|
||||
// The settings hasn't been changed yet, so it's value is null. Return the default.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the soft keyboard show mode. The default show mode is
|
||||
* {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
|
||||
* input field is focused. An AccessibilityService can also request the show mode
|
||||
* {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
|
||||
* The lastto this method will be honored, regardless of any previous calls (including those
|
||||
* made by other AccessibilityServices).
|
||||
* <p>
|
||||
* <strong>Note:</strong> If the service is not yet conected (e.g.
|
||||
* {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
|
||||
* service has been disconnected, this method will hav no effect and return {@code false}.
|
||||
*
|
||||
* @param showMode the new show mode for the soft keyboard
|
||||
* @return {@code true} on success
|
||||
*
|
||||
* @see Settings#Secure#SHOW_MODE_AUTO
|
||||
* @see Settings#Secure#SHOW_MODE_HIDDEN
|
||||
*/
|
||||
public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance().getConnection(
|
||||
mService.mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
return connection.setSoftKeyboardShowMode(showMode);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(LOG_TAG, "Falied to set soft keyboard behavior", re);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for changes in the soft keyboard show mode.
|
||||
*/
|
||||
public interface OnShowModeChangedListener {
|
||||
/**
|
||||
* Called when the soft keyboard behavior changes. The default show mode is
|
||||
* {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
|
||||
* input field is focused. An AccessibilityService can also request the show mode
|
||||
* {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
|
||||
*
|
||||
* @param controller the soft keyboard controller
|
||||
* @param showMode the current soft keyboard show mode
|
||||
*/
|
||||
void onShowModeChanged(@NonNull SoftKeyboardController controller,
|
||||
@SoftKeyboardShowMode int showMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a global action. Such an action can be performed
|
||||
* at any moment regardless of the current application or user
|
||||
@@ -1183,6 +1454,11 @@ public abstract class AccessibilityService extends Service {
|
||||
AccessibilityService.this.onMagnificationChanged(region, scale, centerX, centerY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSoftKeyboardShowModeChanged(int showMode) {
|
||||
AccessibilityService.this.onSoftKeyboardShowModeChanged(showMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
|
||||
AccessibilityService.this.onPerformGestureResult(sequence, completedSuccessfully);
|
||||
@@ -1205,7 +1481,8 @@ public abstract class AccessibilityService extends Service {
|
||||
private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
|
||||
private static final int DO_ON_KEY_EVENT = 6;
|
||||
private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
|
||||
private static final int DO_GESTURE_COMPLETE = 8;
|
||||
private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
|
||||
private static final int DO_GESTURE_COMPLETE = 9;
|
||||
|
||||
private final HandlerCaller mCaller;
|
||||
|
||||
@@ -1264,6 +1541,12 @@ public abstract class AccessibilityService extends Service {
|
||||
mCaller.sendMessage(message);
|
||||
}
|
||||
|
||||
public void onSoftKeyboardShowModeChanged(int showMode) {
|
||||
final Message message =
|
||||
mCaller.obtainMessageI(DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED, showMode);
|
||||
mCaller.sendMessage(message);
|
||||
}
|
||||
|
||||
public void onPerformGestureResult(int sequence, boolean successfully) {
|
||||
Message message = mCaller.obtainMessageII(DO_GESTURE_COMPLETE, sequence,
|
||||
successfully ? 1 : 0);
|
||||
@@ -1354,6 +1637,11 @@ public abstract class AccessibilityService extends Service {
|
||||
mCallback.onMagnificationChanged(region, scale, centerX, centerY);
|
||||
} return;
|
||||
|
||||
case DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED: {
|
||||
final int showMode = (int) message.arg1;
|
||||
mCallback.onSoftKeyboardShowModeChanged(showMode);
|
||||
} return;
|
||||
|
||||
case DO_GESTURE_COMPLETE: {
|
||||
final boolean successfully = message.arg2 == 1;
|
||||
mCallback.onPerformGestureResult(message.arg1, successfully);
|
||||
|
||||
@@ -43,5 +43,7 @@ import android.view.KeyEvent;
|
||||
|
||||
void onMagnificationChanged(in Region region, float scale, float centerX, float centerY);
|
||||
|
||||
void onSoftKeyboardShowModeChanged(int showMode);
|
||||
|
||||
void onPerformGestureResult(int sequence, boolean completedSuccessfully);
|
||||
}
|
||||
|
||||
@@ -84,5 +84,9 @@ interface IAccessibilityServiceConnection {
|
||||
|
||||
void setMagnificationCallbackEnabled(boolean enabled);
|
||||
|
||||
boolean setSoftKeyboardShowMode(int showMode);
|
||||
|
||||
void setSoftKeyboardCallbackEnabled(boolean enabled);
|
||||
|
||||
void sendMotionEvents(int sequence, in ParceledListSlice events);
|
||||
}
|
||||
|
||||
@@ -1087,6 +1087,11 @@ public final class UiAutomation {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSoftKeyboardShowModeChanged(int showMode) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
|
||||
/* do nothing */
|
||||
|
||||
@@ -4855,6 +4855,29 @@ public final class Settings {
|
||||
public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE =
|
||||
"accessibility_display_magnification_auto_update";
|
||||
|
||||
/**
|
||||
* Setting that specifies what mode the soft keyboard is in (default or hidden). Can be
|
||||
* modified from an AccessibilityService using the SoftKeyboardController.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String ACCESSIBILITY_SOFT_KEYBOARD_MODE =
|
||||
"accessibility_soft_keyboard_mode";
|
||||
|
||||
/**
|
||||
* Default soft keyboard behavior.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int SHOW_MODE_AUTO = 0;
|
||||
|
||||
/**
|
||||
* Soft keyboard is never shown.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int SHOW_MODE_HIDDEN = 1;
|
||||
|
||||
/**
|
||||
* Setting that specifies whether timed text (captions) should be
|
||||
* displayed in video content. Text display properties are controlled by
|
||||
|
||||
@@ -958,7 +958,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
final UserState state = getCurrentUserStateLocked();
|
||||
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
|
||||
final Service service = state.mBoundServices.get(i);
|
||||
service.notifyMagnificationChanged(region, scale, centerX, centerY);
|
||||
service.notifyMagnificationChangedLocked(region, scale, centerX, centerY);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySoftKeyboardShowModeChangedLocked(int showMode) {
|
||||
final UserState state = getCurrentUserStateLocked();
|
||||
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
|
||||
final Service service = state.mBoundServices.get(i);
|
||||
service.notifySoftKeyboardShowModeChangedLocked(showMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1407,6 +1415,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
updateEnhancedWebAccessibilityLocked(userState);
|
||||
updateDisplayColorAdjustmentSettingsLocked(userState);
|
||||
updateMagnificationLocked(userState);
|
||||
updateSoftKeyboardShowModeLocked(userState);
|
||||
scheduleUpdateInputFilter(userState);
|
||||
scheduleUpdateClientsIfNeededLocked(userState);
|
||||
}
|
||||
@@ -1623,6 +1632,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) {
|
||||
final int softKeyboardShowMode = Settings.Secure.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0,
|
||||
userState.mUserId);
|
||||
if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) {
|
||||
userState.mSoftKeyboardShowMode = softKeyboardShowMode;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateTouchExplorationLocked(UserState userState) {
|
||||
boolean enabled = false;
|
||||
final int serviceCount = userState.mBoundServices.size();
|
||||
@@ -1757,6 +1778,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateSoftKeyboardShowModeLocked(UserState userState) {
|
||||
final int userId = userState.mUserId;
|
||||
if (userId == mCurrentUserId) {
|
||||
// Check whether any Accessibility Services are still enabled and, if not, remove flag
|
||||
// requesting no soft keyboard
|
||||
final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
|
||||
if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
|
||||
// No active Accessibility Services can be requesting the soft keyboard to be hidden
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
|
||||
0,
|
||||
userState.mUserId);
|
||||
userState.mSoftKeyboardShowMode = 0;
|
||||
}
|
||||
|
||||
notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
|
||||
}
|
||||
}
|
||||
|
||||
private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
|
||||
IBinder windowToken = mGlobalWindowTokens.get(windowId);
|
||||
if (windowToken == null) {
|
||||
@@ -2102,7 +2142,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
};
|
||||
|
||||
// Handler for scheduling method invocations on the main thread.
|
||||
public InvocationHandler mInvocationHandler = new InvocationHandler(
|
||||
public final InvocationHandler mInvocationHandler = new InvocationHandler(
|
||||
mMainHandler.getLooper());
|
||||
|
||||
public Service(int userId, ComponentName componentName,
|
||||
@@ -2297,17 +2337,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCalledForCurrentUserLocked() {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT);
|
||||
return resolvedUserId == mCurrentUserId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityWindowInfo> getWindows() {
|
||||
ensureWindowsAvailableTimed();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its perent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return null;
|
||||
}
|
||||
final boolean permissionGranted =
|
||||
@@ -2335,13 +2378,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
public AccessibilityWindowInfo getWindow(int windowId) {
|
||||
ensureWindowsAvailableTimed();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return null;
|
||||
}
|
||||
final boolean permissionGranted =
|
||||
@@ -2368,13 +2405,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
Region partialInteractiveRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
|
||||
@@ -2425,13 +2456,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
Region partialInteractiveRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
|
||||
@@ -2482,13 +2507,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
Region partialInteractiveRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
|
||||
@@ -2539,13 +2558,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
Region partialInteractiveRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
|
||||
@@ -2597,13 +2610,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
Region partialInteractiveRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
|
||||
@@ -2670,13 +2677,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
final int resolvedWindowId;
|
||||
IAccessibilityInteractionConnection connection = null;
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
|
||||
@@ -2709,13 +2710,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public boolean performGlobalAction(int action) {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2750,13 +2745,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public float getMagnificationScale() {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
@@ -2771,13 +2760,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public Region getMagnifiedRegion() {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return Region.obtain();
|
||||
}
|
||||
}
|
||||
@@ -2794,13 +2777,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public float getMagnificationCenterX() {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -2815,13 +2792,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public float getMagnificationCenterY() {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -2836,13 +2807,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
@Override
|
||||
public boolean resetMagnification(boolean animate) {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
|
||||
@@ -2862,13 +2827,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
|
||||
boolean animate) {
|
||||
synchronized (mLock) {
|
||||
// We treat calls from a profile as if made by its parent as profiles
|
||||
// share the accessibility state of the parent. The call below
|
||||
// performs the current profile parent resolution.
|
||||
final int resolvedUserId = mSecurityPolicy
|
||||
.resolveCallingUserIdEnforcingPermissionsLocked(
|
||||
UserHandle.USER_CURRENT);
|
||||
if (resolvedUserId != mCurrentUserId) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
|
||||
@@ -2890,6 +2849,33 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
mInvocationHandler.setMagnificationCallbackEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setSoftKeyboardShowMode(int showMode) {
|
||||
final UserState userState;
|
||||
synchronized (mLock) {
|
||||
if (!isCalledForCurrentUserLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
userState = getCurrentUserStateLocked();
|
||||
}
|
||||
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
|
||||
userState.mUserId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSoftKeyboardCallbackEnabled(boolean enabled) {
|
||||
mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
|
||||
mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
|
||||
@@ -3080,9 +3066,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
|
||||
}
|
||||
|
||||
public void notifyMagnificationChanged(@NonNull Region region,
|
||||
public void notifyMagnificationChangedLocked(@NonNull Region region,
|
||||
float scale, float centerX, float centerY) {
|
||||
mInvocationHandler.notifyMagnificationChanged(region, scale, centerX, centerY);
|
||||
mInvocationHandler
|
||||
.notifyMagnificationChangedLocked(region, scale, centerX, centerY);
|
||||
}
|
||||
|
||||
public void notifySoftKeyboardShowModeChangedLocked(int showState) {
|
||||
mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3104,6 +3095,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the invocation handler to notify the service that the state of the soft
|
||||
* keyboard show mode has changed.
|
||||
*/
|
||||
private void notifySoftKeyboardShowModeChangedInternal(int showState) {
|
||||
final IAccessibilityServiceClient listener;
|
||||
synchronized (mLock) {
|
||||
listener = mServiceInterface;
|
||||
}
|
||||
if (listener != null) {
|
||||
try {
|
||||
listener.onSoftKeyboardShowModeChanged(showState);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
|
||||
re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyGestureInternal(int gestureId) {
|
||||
final IAccessibilityServiceClient listener;
|
||||
synchronized (mLock) {
|
||||
@@ -3239,8 +3249,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
|
||||
|
||||
private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
|
||||
private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
|
||||
|
||||
private boolean mIsMagnificationCallbackEnabled = false;
|
||||
private boolean mIsSoftKeyboardCallbackEnabled = false;
|
||||
|
||||
public InvocationHandler(Looper looper) {
|
||||
super(looper, null, true);
|
||||
@@ -3268,13 +3280,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
notifyMagnificationChangedInternal(region, scale, centerX, centerY);
|
||||
} break;
|
||||
|
||||
case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
|
||||
final int showState = (int) message.arg1;
|
||||
notifySoftKeyboardShowModeChangedInternal(showState);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unknown message: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyMagnificationChanged(@NonNull Region region, float scale,
|
||||
public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
|
||||
float centerX, float centerY) {
|
||||
if (!mIsMagnificationCallbackEnabled) {
|
||||
// Callback is disabled, don't bother packing args.
|
||||
@@ -3294,8 +3311,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
public void setMagnificationCallbackEnabled(boolean enabled) {
|
||||
mIsMagnificationCallbackEnabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void notifySoftKeyboardShowModeChangedLocked(int showState) {
|
||||
if (!mIsSoftKeyboardCallbackEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
|
||||
msg.sendToTarget();
|
||||
}
|
||||
|
||||
public void setSoftKeyboardCallbackEnabled(boolean enabled) {
|
||||
mIsSoftKeyboardCallbackEnabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class WindowsForAccessibilityCallback implements
|
||||
@@ -3976,6 +4005,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
|
||||
public int mLastSentClientState = -1;
|
||||
|
||||
public int mSoftKeyboardShowMode = 0;
|
||||
|
||||
public boolean mIsAccessibilityEnabled;
|
||||
public boolean mIsTouchExplorationEnabled;
|
||||
public boolean mIsTextHighContrastEnabled;
|
||||
@@ -4048,6 +4079,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
mIsEnhancedWebAccessibilityEnabled = false;
|
||||
mIsDisplayMagnificationEnabled = false;
|
||||
mIsAutoclickEnabled = false;
|
||||
mSoftKeyboardShowMode = 0;
|
||||
}
|
||||
|
||||
public void destroyUiAutomationService() {
|
||||
@@ -4105,6 +4137,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
|
||||
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
|
||||
|
||||
private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
|
||||
|
||||
public AccessibilityContentObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
@@ -4135,6 +4170,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
mDisplayColorMatrixUri, false, this, UserHandle.USER_ALL);
|
||||
contentResolver.registerContentObserver(
|
||||
mHighTextContrastUri, false, this, UserHandle.USER_ALL);
|
||||
contentResolver.registerContentObserver(
|
||||
mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4189,6 +4226,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
if (readHighTextContrastEnabledSettingLocked(userState)) {
|
||||
onUserStateChangedLocked(userState);
|
||||
}
|
||||
} else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
|
||||
if (readSoftKeyboardShowModeChangedLocked(userState)) {
|
||||
onUserStateChangedLocked(userState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,6 +448,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
private int[] mSubtypeIds;
|
||||
private Locale mLastSystemLocale;
|
||||
private boolean mShowImeWithHardKeyboard;
|
||||
private boolean mAccessibilityRequestingNoSoftKeyboard;
|
||||
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
|
||||
private final IPackageManager mIPackageManager;
|
||||
private final String mSlotIme;
|
||||
@@ -485,15 +486,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this, userId);
|
||||
resolver.registerContentObserver(Settings.Secure.getUriFor(
|
||||
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
|
||||
resolver.registerContentObserver(Settings.Secure.getUriFor(
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE), false, this, userId);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
@Override public void onChange(boolean selfChange, Uri uri) {
|
||||
final Uri showImeUri =
|
||||
Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
|
||||
final Uri showImeUri = Settings.Secure.getUriFor(
|
||||
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
|
||||
final Uri accessibilityRequestingNoImeUri = Settings.Secure.getUriFor(
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
|
||||
synchronized (mMethodMap) {
|
||||
if (showImeUri.equals(uri)) {
|
||||
updateKeyboardFromSettingsLocked();
|
||||
} else if (accessibilityRequestingNoImeUri.equals(uri)) {
|
||||
mAccessibilityRequestingNoSoftKeyboard = Settings.Secure.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
|
||||
0, mUserId) == 1;
|
||||
if (mAccessibilityRequestingNoSoftKeyboard) {
|
||||
final boolean showRequested = mShowRequested;
|
||||
hideCurrentInputLocked(0, null);
|
||||
mShowRequested = showRequested;
|
||||
} else if (mShowRequested) {
|
||||
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
|
||||
}
|
||||
} else {
|
||||
boolean enabledChanged = false;
|
||||
String newEnabled = mSettings.getEnabledInputMethodsStr();
|
||||
@@ -655,7 +672,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
boolean changed = false;
|
||||
|
||||
if (curIm != null) {
|
||||
int change = isPackageDisappearing(curIm.getPackageName());
|
||||
int change = isPackageDisappearing(curIm.getPackageName());
|
||||
if (change == PACKAGE_TEMPORARY_CHANGE
|
||||
|| change == PACKAGE_PERMANENT_CHANGE) {
|
||||
ServiceInfo si = null;
|
||||
@@ -2073,12 +2090,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
|
||||
mShowRequested = true;
|
||||
if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
|
||||
mShowExplicitlyRequested = true;
|
||||
if (mAccessibilityRequestingNoSoftKeyboard) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
|
||||
mShowExplicitlyRequested = true;
|
||||
mShowForced = true;
|
||||
} else if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
|
||||
mShowExplicitlyRequested = true;
|
||||
}
|
||||
|
||||
if (!mSystemReady) {
|
||||
@@ -3265,7 +3285,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
"Requires permission "
|
||||
+ android.Manifest.permission.WRITE_SECURE_SETTINGS);
|
||||
}
|
||||
|
||||
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return setInputMethodEnabledLocked(id, enabled);
|
||||
|
||||
Reference in New Issue
Block a user