diff options
11 files changed, 267 insertions, 143 deletions
diff --git a/api/current.txt b/api/current.txt index 774831db406f..9c851e96ffcf 100755 --- a/api/current.txt +++ b/api/current.txt @@ -769,6 +769,7 @@ package android { field public static final int insetRight = 16843192; // 0x10101b8 field public static final int insetTop = 16843193; // 0x10101b9 field public static final int installLocation = 16843447; // 0x10102b7 + field public static final int interactiveUiTimeout = 16844181; // 0x1010595 field public static final int interpolator = 16843073; // 0x1010141 field public static final int isAlwaysSyncable = 16843571; // 0x1010333 field public static final int isAsciiCapable = 16843753; // 0x10103e9 @@ -941,7 +942,6 @@ package android { field public static final int minSdkVersion = 16843276; // 0x101020c field public static final int minWidth = 16843071; // 0x101013f field public static final int minimumHorizontalAngle = 16843901; // 0x101047d - field public static final int minimumUiTimeout = 16844175; // 0x101058f field public static final int minimumVerticalAngle = 16843902; // 0x101047e field public static final int mipMap = 16843725; // 0x10103cd field public static final int mirrorForRtl = 16843726; // 0x10103ce @@ -965,6 +965,7 @@ package android { field public static final int nextFocusRight = 16842978; // 0x10100e2 field public static final int nextFocusUp = 16842979; // 0x10100e3 field public static final int noHistory = 16843309; // 0x101022d + field public static final int nonInteractiveUiTimeout = 16844175; // 0x101058f field public static final int normalScreens = 16843397; // 0x1010285 field public static final int notificationTimeout = 16843651; // 0x1010383 field public static final int numColumns = 16843032; // 0x1010118 @@ -2886,12 +2887,14 @@ package android.accessibilityservice { method public int getCapabilities(); method public deprecated java.lang.String getDescription(); method public java.lang.String getId(); - method public int getMinimumUiTimeoutMillis(); + method public int getInteractiveUiTimeoutMillis(); + method public int getNonInteractiveUiTimeoutMillis(); method public android.content.pm.ResolveInfo getResolveInfo(); method public java.lang.String getSettingsActivityName(); method public java.lang.String loadDescription(android.content.pm.PackageManager); method public java.lang.CharSequence loadSummary(android.content.pm.PackageManager); - method public void setMinimumUiTimeoutMillis(int); + method public void setInteractiveUiTimeoutMillis(int); + method public void setNonInteractiveUiTimeoutMillis(int); method public void writeToParcel(android.os.Parcel, int); field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10 field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20 @@ -50517,7 +50520,7 @@ package android.view.accessibility { method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList(); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); - method public int getMinimumUiTimeoutMillis(); + method public int getRecommendedTimeoutMillis(int, int); method public void interrupt(); method public static boolean isAccessibilityButtonSupported(); method public boolean isEnabled(); @@ -50526,6 +50529,9 @@ package android.view.accessibility { method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent); + field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4 + field public static final int FLAG_CONTENT_ICONS = 1; // 0x1 + field public static final int FLAG_CONTENT_TEXT = 2; // 0x2 } public static abstract interface AccessibilityManager.AccessibilityStateChangeListener { diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index d7cca1592740..997ed25a42c6 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -76,7 +76,8 @@ import java.util.List; * @attr ref android.R.styleable#AccessibilityService_notificationTimeout * @attr ref android.R.styleable#AccessibilityService_packageNames * @attr ref android.R.styleable#AccessibilityService_settingsActivity - * @attr ref android.R.styleable#AccessibilityService_minimumUiTimeout + * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout + * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout * @see AccessibilityService * @see android.view.accessibility.AccessibilityEvent * @see android.view.accessibility.AccessibilityManager @@ -434,11 +435,14 @@ public class AccessibilityServiceInfo implements Parcelable { public boolean crashed; /** - * The minimum timeout in milliseconds that UI controls need to remain on the screen. - * - * @see #setMinimumUiTimeoutMillis + * A recommended timeout in milliseconds for non-interactive controls. + */ + private int mNonInteractiveUiTimeout; + + /** + * A recommended timeout in milliseconds for interactive controls. */ - private int mMinimumUiTimeout; + private int mInteractiveUiTimeout; /** * The component name the accessibility service. @@ -544,8 +548,11 @@ public class AccessibilityServiceInfo implements Parcelable { notificationTimeout = asAttributes.getInt( com.android.internal.R.styleable.AccessibilityService_notificationTimeout, 0); - mMinimumUiTimeout = asAttributes.getInt( - com.android.internal.R.styleable.AccessibilityService_minimumUiTimeout, + mNonInteractiveUiTimeout = asAttributes.getInt( + com.android.internal.R.styleable.AccessibilityService_nonInteractiveUiTimeout, + 0); + mInteractiveUiTimeout = asAttributes.getInt( + com.android.internal.R.styleable.AccessibilityService_interactiveUiTimeout, 0); flags = asAttributes.getInt( com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0); @@ -616,7 +623,8 @@ public class AccessibilityServiceInfo implements Parcelable { packageNames = other.packageNames; feedbackType = other.feedbackType; notificationTimeout = other.notificationTimeout; - mMinimumUiTimeout = other.mMinimumUiTimeout; + mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout; + mInteractiveUiTimeout = other.mInteractiveUiTimeout; flags = other.flags; } @@ -775,26 +783,57 @@ public class AccessibilityServiceInfo implements Parcelable { } /** - * Set the minimum time that controls need to remain on the screen to support the user. + * Set the recommended time that non-interactive controls need to remain on the screen to + * support the user. + * <p> + * <strong>This value can be dynamically set at runtime by + * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong> + * </p> + * + * @param timeout The timeout in milliseconds. + * + * @see android.R.styleable#AccessibilityService_nonInteractiveUiTimeout + */ + public void setNonInteractiveUiTimeoutMillis(int timeout) { + mNonInteractiveUiTimeout = timeout; + } + + /** + * Get the recommended timeout for non-interactive controls. + * + * @return The timeout in milliseconds. + * + * @see #setNonInteractiveUiTimeoutMillis(int) + */ + public int getNonInteractiveUiTimeoutMillis() { + return mNonInteractiveUiTimeout; + } + + /** + * Set the recommended time that interactive controls need to remain on the screen to + * support the user. * <p> - * <strong>This value can be dynamically set at runtime by - * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong> + * <strong>This value can be dynamically set at runtime by + * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong> * </p> * * @param timeout The timeout in milliseconds. + * + * @see android.R.styleable#AccessibilityService_interactiveUiTimeout */ - public void setMinimumUiTimeoutMillis(int timeout) { - mMinimumUiTimeout = timeout; + public void setInteractiveUiTimeoutMillis(int timeout) { + mInteractiveUiTimeout = timeout; } /** - * Get the minimum ui timeout. + * Get the recommended timeout for interactive controls. * - * @see #setMinimumUiTimeoutMillis * @return The timeout in milliseconds. + * + * @see #setInteractiveUiTimeoutMillis(int) */ - public int getMinimumUiTimeoutMillis() { - return mMinimumUiTimeout; + public int getInteractiveUiTimeoutMillis() { + return mInteractiveUiTimeout; } /** {@hide} */ @@ -815,7 +854,8 @@ public class AccessibilityServiceInfo implements Parcelable { parcel.writeStringArray(packageNames); parcel.writeInt(feedbackType); parcel.writeLong(notificationTimeout); - parcel.writeInt(mMinimumUiTimeout); + parcel.writeInt(mNonInteractiveUiTimeout); + parcel.writeInt(mInteractiveUiTimeout); parcel.writeInt(flags); parcel.writeInt(crashed ? 1 : 0); parcel.writeParcelable(mComponentName, flagz); @@ -833,7 +873,8 @@ public class AccessibilityServiceInfo implements Parcelable { packageNames = parcel.readStringArray(); feedbackType = parcel.readInt(); notificationTimeout = parcel.readLong(); - mMinimumUiTimeout = parcel.readInt(); + mNonInteractiveUiTimeout = parcel.readInt(); + mInteractiveUiTimeout = parcel.readInt(); flags = parcel.readInt(); crashed = parcel.readInt() != 0; mComponentName = parcel.readParcelable(this.getClass().getClassLoader()); @@ -884,7 +925,9 @@ public class AccessibilityServiceInfo implements Parcelable { stringBuilder.append(", "); stringBuilder.append("notificationTimeout: ").append(notificationTimeout); stringBuilder.append(", "); - stringBuilder.append("minimumUiTimeout: ").append(mMinimumUiTimeout); + stringBuilder.append("nonInteractiveUiTimeout: ").append(mNonInteractiveUiTimeout); + stringBuilder.append(", "); + stringBuilder.append("interactiveUiTimeout: ").append(mInteractiveUiTimeout); stringBuilder.append(", "); appendFlags(stringBuilder, flags); stringBuilder.append(", "); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 61d08a3fa2cf..f1f4b0c89bab 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6567,23 +6567,22 @@ public final class Settings { public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout"; /** - * Whether the user specifies a minimum ui timeout to override minimum ui timeout of - * accessibility service + * Setting that specifies recommended timeout in milliseconds for controls + * which don't need user's interactions. * - * Type: int (0 for false, 1 for true) * @hide */ - public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED = - "accessibility_minimum_ui_timeout_enabled"; + public static final String ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS = + "accessibility_non_interactive_ui_timeout_ms"; /** - * Setting that specifies ui minimum timeout in milliseconds. + * Setting that specifies recommended timeout in milliseconds for controls + * which need user's interactions. * - * @see #ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED * @hide */ - public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS = - "accessibility_minimum_ui_timeout_ms"; + public static final String ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS = + "accessibility_interactive_ui_timeout_ms"; /** * List of the enabled print services. @@ -8318,8 +8317,8 @@ public final class Settings { ZEN_SETTINGS_SUGGESTION_VIEWED, CHARGING_SOUNDS_ENABLED, CHARGING_VIBRATION_ENABLED, - ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, - ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, + ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, + ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NOTIFICATION_NEW_INTERRUPTION_MODEL, }; @@ -8476,8 +8475,9 @@ public final class Settings { VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR); VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, + NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR); VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR); VALIDATORS.put(NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR); diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index a7d0cfbde1d5..6a17b646b88c 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -21,6 +21,7 @@ import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_ENABLE_ import android.Manifest; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -54,6 +55,8 @@ import android.view.accessibility.AccessibilityEvent.EventType; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -117,6 +120,39 @@ public final class AccessibilityManager { public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON = "com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON"; + /** + * Annotations for content flag of UI. + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = { "FLAG_CONTENT_" }, value = { + FLAG_CONTENT_ICONS, + FLAG_CONTENT_TEXT, + FLAG_CONTENT_CONTROLS + }) + public @interface ContentFlag {} + + /** + * Use this flag to indicate the content of a UI that times out contains icons. + * + * @see #getRecommendedTimeoutMillis(int, int) + */ + public static final int FLAG_CONTENT_ICONS = 1; + + /** + * Use this flag to indicate the content of a UI that times out contains text. + * + * @see #getRecommendedTimeoutMillis(int, int) + */ + public static final int FLAG_CONTENT_TEXT = 2; + + /** + * Use this flag to indicate the content of a UI that times out contains interactive controls. + * + * @see #getRecommendedTimeoutMillis(int, int) + */ + public static final int FLAG_CONTENT_CONTROLS = 4; + @UnsupportedAppUsage static final Object sInstanceSync = new Object(); @@ -142,7 +178,8 @@ public final class AccessibilityManager { int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK; - int mMinimumUiTimeout; + int mInteractiveUiTimeout; + int mNonInteractiveUiTimeout; boolean mIsTouchExplorationEnabled; @@ -304,7 +341,9 @@ public final class AccessibilityManager { } @Override - public void notifyServicesStateChanged() { + public void notifyServicesStateChanged(long updatedUiTimeout) { + updateUiTimeout(updatedUiTimeout); + final ArrayMap<AccessibilityServicesStateChangeListener, Handler> listeners; synchronized (mLock) { if (mServicesStateChangeListeners.isEmpty()) { @@ -326,11 +365,6 @@ public final class AccessibilityManager { public void setRelevantEventTypes(int eventTypes) { mRelevantEventTypes = eventTypes; } - - @Override - public void setMinimumUiTimeout(int uiTimeout) { - mMinimumUiTimeout = uiTimeout; - } }; /** @@ -840,16 +874,35 @@ public final class AccessibilityManager { } /** - * Get the minimum timeout for changes to the UI needed by this user. Controls should remain + * Get the recommended timeout for changes to the UI needed by this user. Controls should remain * on the screen for at least this long to give users time to react. Some users may need * extra time to review the controls, or to reach them, or to activate assistive technology * to activate the controls automatically. + * <p> + * Use the combination of content flags to indicate contents of UI. For example, use + * {@code FLAG_CONTENT_ICONS | FLAG_CONTENT_TEXT} for message notification which contains + * icons and text, or use {@code FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS} for button dialog + * which contains text and button controls. + * <p/> * - * @return The minimum ui timeout for the current user in milliseconds. - * {@link Integer#MAX_VALUE} if timeout is infinite. + * @param originalTimeout The timeout appropriate for users with no accessibility needs. + * @param uiContentFlags The combination of flags {@link #FLAG_CONTENT_ICONS}, + * {@link #FLAG_CONTENT_TEXT} or {@Link #CONTENT_CONTROLS} to + * indicate the contents of UI. + * @return The recommended UI timeout for the current user in milliseconds. */ - public int getMinimumUiTimeoutMillis() { - return mMinimumUiTimeout; + public int getRecommendedTimeoutMillis(int originalTimeout, @ContentFlag int uiContentFlags) { + boolean hasControls = (uiContentFlags & FLAG_CONTENT_CONTROLS) != 0; + boolean hasIconsOrText = (uiContentFlags & FLAG_CONTENT_ICONS) != 0 + || (uiContentFlags & FLAG_CONTENT_TEXT) != 0; + int recommendedTimeout = originalTimeout; + if (hasControls) { + recommendedTimeout = Math.max(recommendedTimeout, mInteractiveUiTimeout); + } + if (hasIconsOrText) { + recommendedTimeout = Math.max(recommendedTimeout, mNonInteractiveUiTimeout); + } + return recommendedTimeout; } /** @@ -1192,7 +1245,7 @@ public final class AccessibilityManager { final long userStateAndRelevantEvents = service.addClient(mClient, mUserId); setStateLocked(IntPair.first(userStateAndRelevantEvents)); mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents); - mMinimumUiTimeout = service.getMinimumUiTimeout(); + updateUiTimeout(service.getRecommendedTimeoutMillis()); mService = service; } catch (RemoteException re) { Log.e(LOG_TAG, "AccessibilityManagerService is dead", re); @@ -1266,6 +1319,17 @@ public final class AccessibilityManager { } /** + * Update interactive and non-interactive UI timeout. + * + * @param uiTimeout A pair of {@code int}s. First integer for interactive one, and second + * integer for non-interactive one. + */ + private void updateUiTimeout(long uiTimeout) { + mInteractiveUiTimeout = IntPair.first(uiTimeout); + mNonInteractiveUiTimeout = IntPair.second(uiTimeout); + } + + /** * Determines if the accessibility button within the system navigation area is supported. * * @return {@code true} if the accessibility button is supported on this device, diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl index 61a8a1da2b42..2767a82e5dba 100644 --- a/core/java/android/view/accessibility/IAccessibilityManager.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -76,5 +76,5 @@ interface IAccessibilityManager { // System process only boolean sendFingerprintGesture(int gestureKeyCode); - int getMinimumUiTimeout(); + long getRecommendedTimeoutMillis(); } diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl index d2ddca3acae7..94b9ad1c3279 100644 --- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl @@ -26,9 +26,7 @@ oneway interface IAccessibilityManagerClient { void setState(int stateFlags); - void notifyServicesStateChanged(); + void notifyServicesStateChanged(long updatedUiTimeout); void setRelevantEventTypes(int eventTypes); - - void setMinimumUiTimeout(int uiTimeout); } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 3ead63318a01..f8acc3368b72 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -72,8 +72,10 @@ message SecureSettingsProto { // List of the accessibility services to which the user has granted // permission to put the device into touch exploration mode. optional SettingProto touch_exploration_granted_accessibility_services = 31; - optional SettingProto minimum_ui_timeout_enabled = 32 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto minimum_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ]; + reserved 32; // minimum_ui_timeout_enabled + reserved 33; // minimum_ui_timeout_ms + optional SettingProto non_interactive_ui_timeout_ms = 34 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto interactive_ui_timeout_ms = 35 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Accessibility accessibility = 2; diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a25c9984b1c4..68ec34229d48 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3587,11 +3587,22 @@ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> <attr name="notificationTimeout" format="integer" /> - <!-- The minimum timeout in milliseconds that UI controls need to remain on the screen. + <!-- A recommended timeout in milliseconds used in + {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int) + android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)} + to return a suitable value for UIs that do not include interactive controls. This setting can be changed at runtime by calling {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> - <attr name="minimumUiTimeout" format="integer" /> + <attr name="nonInteractiveUiTimeout" format="integer" /> + <!-- A recommended timeout in milliseconds used in + {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int) + android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)} + to return a suitable value for interactive controls. + This setting can be changed at runtime by calling + {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) + android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. --> + <attr name="interactiveUiTimeout" format="integer" /> <!-- Additional flags as specified in {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting can be changed at runtime by calling diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e1c5df39676b..15f29ce8a583 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2912,12 +2912,13 @@ <public name="supportsAmbientMode" /> <!-- @hide For use by platform and tools only. Developers should not specify this value. --> <public name="usesNonSdkApi" /> - <public name="minimumUiTimeout" /> + <public name="nonInteractiveUiTimeout" /> <public name="isLightTheme" /> <public name="isSplitRequired" /> <public name="textLocale" /> <public name="settingsSliceUri" /> <public name="shell" /> + <public name="interactiveUiTimeout" /> </public-group> <public-group type="drawable" first-id="0x010800b4"> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index b46c288bdb00..ca0267ca52c6 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1643,11 +1643,11 @@ class SettingsProtoDumpUtil { Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); dumpSetting(s, p, - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, - SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_ENABLED); + Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, + SecureSettingsProto.Accessibility.NON_INTERACTIVE_UI_TIMEOUT_MS); dumpSetting(s, p, - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, - SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_MS); + Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, + SecureSettingsProto.Accessibility.INTERACTIVE_UI_TIMEOUT_MS); p.end(accessibilityToken); dumpSetting(s, p, diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index e89b9517da84..5c189ce44dc8 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1672,22 +1672,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub client -> client.setState(clientState))); } - private void scheduleNotifyClientsOfServicesStateChange(UserState userState) { + private void scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState) { + updateRecommendedUiTimeoutLocked(userState); mMainHandler.sendMessage(obtainMessage( AccessibilityManagerService::sendServicesStateChanged, - this, userState.mUserClients)); + this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState))); } private void sendServicesStateChanged( - RemoteCallbackList<IAccessibilityManagerClient> userClients) { - notifyClientsOfServicesStateChange(mGlobalClients); - notifyClientsOfServicesStateChange(userClients); + RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) { + notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout); + notifyClientsOfServicesStateChange(userClients, uiTimeout); } private void notifyClientsOfServicesStateChange( - RemoteCallbackList<IAccessibilityManagerClient> clients) { + RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) { clients.broadcast(ignoreRemoteException( - client -> client.notifyServicesStateChanged())); + client -> client.notifyServicesStateChanged(uiTimeout))); } private void scheduleUpdateInputFilter(UserState userState) { @@ -1701,24 +1702,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub this, userState)); } - private void scheduleSetAllClientsMinimumUiTimeout(UserState userState) { - mMainHandler.sendMessage(obtainMessage( - AccessibilityManagerService::sendMinimumUiTimeoutChanged, - this, userState.mUserClients, userState.mMinimumUiTimeout)); - } - - private void sendMinimumUiTimeoutChanged( - RemoteCallbackList<IAccessibilityManagerClient> userClients, int uiTimeout) { - notifyClientsOfServicesMinimumUiTimeoutChange(mGlobalClients, uiTimeout); - notifyClientsOfServicesMinimumUiTimeoutChange(userClients, uiTimeout); - } - - private void notifyClientsOfServicesMinimumUiTimeoutChange( - RemoteCallbackList<IAccessibilityManagerClient> clients, int uiTimeout) { - clients.broadcast(ignoreRemoteException( - client -> client.setMinimumUiTimeout(uiTimeout))); - } - private void updateInputFilter(UserState userState) { if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return; @@ -1852,7 +1835,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub scheduleUpdateClientsIfNeededLocked(userState); updateRelevantEventsLocked(userState); updateAccessibilityButtonTargetsLocked(userState); - updateMinimumUiTimeoutLocked(userState); } private void updateAccessibilityFocusBehaviorLocked(UserState userState) { @@ -1971,7 +1953,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub somethingChanged |= readAutoclickEnabledSettingLocked(userState); somethingChanged |= readAccessibilityShortcutSettingLocked(userState); somethingChanged |= readAccessibilityButtonSettingsLocked(userState); - somethingChanged |= readUserMinimumUiTimeoutSettingsLocked(userState); + somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); return somethingChanged; } @@ -2083,7 +2065,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } userState.mServiceToEnableWithShortcut = componentNameToEnable; - scheduleNotifyClientsOfServicesStateChange(userState); + scheduleNotifyClientsOfServicesStateChangeLocked(userState); return true; } @@ -2118,17 +2100,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; } - private boolean readUserMinimumUiTimeoutSettingsLocked(UserState userState) { - final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, 0, - userState.mUserId) == 1; - final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, 0, + private boolean readUserRecommendedUiTimeoutSettingsLocked(UserState userState) { + final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( + mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0, userState.mUserId); - if (enabled != userState.mUserMinimumUiTimeoutEnabled - || timeout != userState.mUserMinimumUiTimeout) { - userState.mUserMinimumUiTimeoutEnabled = enabled; - userState.mUserMinimumUiTimeout = timeout; + final int interactiveUiTimeout = Settings.Secure.getIntForUser( + mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0, + userState.mUserId); + if (nonInteractiveUiTimeout != userState.mUserNonInteractiveUiTimeout + || interactiveUiTimeout != userState.mUserInteractiveUiTimeout) { + userState.mUserNonInteractiveUiTimeout = nonInteractiveUiTimeout; + userState.mUserInteractiveUiTimeout = interactiveUiTimeout; + scheduleNotifyClientsOfServicesStateChangeLocked(userState); return true; } return false; @@ -2300,25 +2285,33 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private void updateMinimumUiTimeoutLocked(UserState userState) { - int newUiTimeout = 0; - if (userState.mUserMinimumUiTimeoutEnabled) { - newUiTimeout = userState.mUserMinimumUiTimeout; - } else { + private void updateRecommendedUiTimeoutLocked(UserState userState) { + int newNonInteractiveUiTimeout = userState.mUserNonInteractiveUiTimeout; + int newInteractiveUiTimeout = userState.mUserInteractiveUiTimeout; + // read from a11y services if user does not specify value + if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) { + int serviceNonInteractiveUiTimeout = 0; + int serviceInteractiveUiTimeout = 0; final List<AccessibilityServiceConnection> services = userState.mBoundServices; - final int numServices = services.size(); - for (int i = 0; i < numServices; i++) { - final int serviceUiTimeout = services.get(i).getServiceInfo() - .getMinimumUiTimeoutMillis(); - if (newUiTimeout < serviceUiTimeout) { - newUiTimeout = serviceUiTimeout; + for (int i = 0; i < services.size(); i++) { + int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis(); + if (serviceInteractiveUiTimeout < timeout) { + serviceInteractiveUiTimeout = timeout; + } + timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis(); + if (serviceNonInteractiveUiTimeout < timeout) { + serviceNonInteractiveUiTimeout = timeout; } } + if (newNonInteractiveUiTimeout == 0) { + newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout; + } + if (newInteractiveUiTimeout == 0) { + newInteractiveUiTimeout = serviceInteractiveUiTimeout; + } } - if (newUiTimeout != userState.mMinimumUiTimeout) { - userState.mMinimumUiTimeout = newUiTimeout; - scheduleSetAllClientsMinimumUiTimeout(userState); - } + userState.mNonInteractiveUiTimeout = newNonInteractiveUiTimeout; + userState.mInteractiveUiTimeout = newInteractiveUiTimeout; } @GuardedBy("mLock") @@ -2473,19 +2466,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } /** - * Get the minimum timeout for changes to the UI needed by this user. Controls should remain - * on the screen for at least this long to give users time to react. + * Get the recommended timeout of interactive controls and non-interactive controls. * - * @return The minimum timeout for the current user in milliseconds. + * @return A long for pair of {@code int}s. First integer for interactive one, and second + * integer for non-interactive one. */ @Override - public int getMinimumUiTimeout() { + public long getRecommendedTimeoutMillis() { synchronized(mLock) { final UserState userState = getCurrentUserStateLocked(); - return userState.mMinimumUiTimeout; + return getRecommendedTimeoutMillisLocked(userState); } } + private long getRecommendedTimeoutMillisLocked(UserState userState) { + return IntPair.of(userState.mInteractiveUiTimeout, + userState.mNonInteractiveUiTimeout); + } + @Override public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; @@ -2503,7 +2501,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub pw.append(", navBarMagnificationEnabled=" + userState.mIsNavBarMagnificationEnabled); pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled); - pw.append(", minimumUiTimeout=" + userState.mMinimumUiTimeout); + pw.append(", nonInteractiveUiTimeout=" + userState.mNonInteractiveUiTimeout); + pw.append(", interactiveUiTimeout=" + userState.mInteractiveUiTimeout); if (mUiAutomationManager.isUiAutomationRunningLocked()) { pw.append(", "); mUiAutomationManager.dumpUiAutomationService(fd, pw, args); @@ -2819,7 +2818,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId); onUserStateChangedLocked(userState); if (serviceInfoChanged) { - scheduleNotifyClientsOfServicesStateChange(userState); + scheduleNotifyClientsOfServicesStateChangeLocked(userState); } } @@ -3794,7 +3793,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub public ComponentName mServiceToEnableWithShortcut; public int mLastSentClientState = -1; - public int mMinimumUiTimeout = 0; + public int mNonInteractiveUiTimeout = 0; + public int mInteractiveUiTimeout = 0; private int mSoftKeyboardShowMode = 0; @@ -3809,8 +3809,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub public boolean mIsPerformGesturesEnabled; public boolean mIsFilterKeyEventsEnabled; public boolean mAccessibilityFocusOnlyInActiveWindow; - public boolean mUserMinimumUiTimeoutEnabled; - public int mUserMinimumUiTimeout; + public int mUserNonInteractiveUiTimeout; + public int mUserInteractiveUiTimeout; private boolean mBindInstantServiceAllowed; @@ -3850,8 +3850,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub // Clear event management state. mLastSentClientState = -1; - // clear minimum ui timeout - mMinimumUiTimeout = 0; + // clear UI timeout + mNonInteractiveUiTimeout = 0; + mInteractiveUiTimeout = 0; // Clear state persisted in settings. mEnabledServices.clear(); @@ -3862,8 +3863,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mServiceAssignedToAccessibilityButton = null; mIsNavBarMagnificationAssignedToAccessibilityButton = false; mIsAutoclickEnabled = false; - mUserMinimumUiTimeoutEnabled = false; - mUserMinimumUiTimeout = 0; + mUserNonInteractiveUiTimeout = 0; + mUserInteractiveUiTimeout = 0; } public void addServiceLocked(AccessibilityServiceConnection serviceConnection) { @@ -3871,7 +3872,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub serviceConnection.onAdded(); mBoundServices.add(serviceConnection); mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection); - scheduleNotifyClientsOfServicesStateChange(this); + scheduleNotifyClientsOfServicesStateChangeLocked(this); } } @@ -3897,7 +3898,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub AccessibilityServiceConnection boundClient = mBoundServices.get(i); mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient); } - scheduleNotifyClientsOfServicesStateChange(this); + scheduleNotifyClientsOfServicesStateChangeLocked(this); } /** @@ -4108,11 +4109,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); - private final Uri mUserMinimumUiTimeoutEnabledUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED); + private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); - private final Uri mUserMinimumUiTimeoutUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS); + private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS); public AccessibilityContentObserver(Handler handler) { super(handler); @@ -4149,9 +4150,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub contentResolver.registerContentObserver( mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( - mUserMinimumUiTimeoutEnabledUri, false, this, UserHandle.USER_ALL); + mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( - mUserMinimumUiTimeoutUri, false, this, UserHandle.USER_ALL); + mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); } @Override @@ -4202,11 +4203,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub if (readAccessibilityButtonSettingsLocked(userState)) { onUserStateChangedLocked(userState); } - } else if (mUserMinimumUiTimeoutEnabledUri.equals(uri) - || mUserMinimumUiTimeoutUri.equals(uri)) { - if (readUserMinimumUiTimeoutSettingsLocked(userState)) { - updateMinimumUiTimeoutLocked(userState); - } + } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) + || mUserInteractiveUiTimeoutUri.equals(uri)) { + readUserRecommendedUiTimeoutSettingsLocked(userState); } } } |