Loading core/java/android/widget/Editor.java +12 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; Loading Loading @@ -384,6 +385,10 @@ public class Editor { private final SuggestionHelper mSuggestionHelper = new SuggestionHelper(); // Specifies whether the cursor control feature set is enabled. // This can only be true if the text view is editable. private final boolean mCursorControlEnabled; Editor(TextView textView) { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. Loading @@ -397,6 +402,13 @@ public class Editor { Magnifier.createBuilderWithOldMagnifierDefaults(mTextView).build(); mMagnifierAnimator = new MagnifierMotionAnimator(magnifier); } mCursorControlEnabled = AppGlobals.getIntCoreSetting( WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0; if (TextView.DEBUG_CURSOR) { logCursor("Editor", "Cursor control is %s.", mCursorControlEnabled ? "enabled" : "disabled"); } } ParcelableParcel saveInstanceState() { Loading core/java/android/widget/WidgetFlags.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package android.widget; /** * Keeps the flags related to the Widget namespace in {@link DeviceConfig}. * * @hide */ public final class WidgetFlags { /** * Whether the cursor control feature set is enabled. * TODO: Makes this flag key visible to webview/chrome. */ public static final String ENABLE_CURSOR_CONTROL = "CursorControlFeature__enable_cursor_control"; /** * The key name used in app core settings for enable cursor control. */ public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control"; private WidgetFlags() { } } services/core/java/com/android/server/am/CoreSettingsObserver.java +57 −0 Original line number Diff line number Diff line Loading @@ -16,15 +16,21 @@ package com.android.server.am; import android.app.ActivityThread; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.provider.DeviceConfig; import android.provider.Settings; import android.widget.WidgetFlags; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; /** Loading @@ -36,6 +42,19 @@ import java.util.Map; final class CoreSettingsObserver extends ContentObserver { private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName(); private static class DeviceConfigEntry { String namespace; String flag; String coreSettingKey; Class<?> type; DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<?> type) { this.namespace = namespace; this.flag = flag; this.coreSettingKey = coreSettingKey; this.type = type; } } // mapping form property name to its type @VisibleForTesting static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap< Loading @@ -46,6 +65,7 @@ final class CoreSettingsObserver extends ContentObserver { @VisibleForTesting static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap< String, Class<?>>(); static final List<DeviceConfigEntry> sDeviceConfigEntries = new ArrayList<DeviceConfigEntry>(); static { sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class); Loading Loading @@ -84,6 +104,11 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... sDeviceConfigEntries.add(new DeviceConfigEntry( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL, WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class)); // add other device configs here... } private final Bundle mCoreSettings = new Bundle(); Loading Loading @@ -112,6 +137,7 @@ final class CoreSettingsObserver extends ContentObserver { populateSettings(mCoreSettings, sSecureSettingToTypeMap); populateSettings(mCoreSettings, sSystemSettingToTypeMap); populateSettings(mCoreSettings, sGlobalSettingToTypeMap); populateSettingsFromDeviceConfig(); mActivityManagerService.onCoreSettingsChange(mCoreSettings); } Loading @@ -133,6 +159,16 @@ final class CoreSettingsObserver extends ContentObserver { mActivityManagerService.mContext.getContentResolver().registerContentObserver( uri, false, this); } HashSet<String> deviceConfigNamespaces = new HashSet<>(); for (DeviceConfigEntry entry : sDeviceConfigEntries) { if (!deviceConfigNamespaces.contains(entry.namespace)) { DeviceConfig.addOnPropertiesChangedListener( entry.namespace, ActivityThread.currentApplication().getMainExecutor(), (DeviceConfig.Properties prop) -> onChange(false)); deviceConfigNamespaces.add(entry.namespace); } } } @VisibleForTesting Loading Loading @@ -164,4 +200,25 @@ final class CoreSettingsObserver extends ContentObserver { } } } private void populateSettingsFromDeviceConfig() { for (DeviceConfigEntry entry : sDeviceConfigEntries) { if (entry.type == String.class) { mCoreSettings.putString(entry.coreSettingKey, DeviceConfig.getString(entry.namespace, entry.flag, "")); } else if (entry.type == int.class) { mCoreSettings.putInt(entry.coreSettingKey, DeviceConfig.getInt(entry.namespace, entry.flag, 0)); } else if (entry.type == float.class) { mCoreSettings.putFloat(entry.coreSettingKey, DeviceConfig.getFloat(entry.namespace, entry.flag, 0)); } else if (entry.type == long.class) { mCoreSettings.putLong(entry.coreSettingKey, DeviceConfig.getLong(entry.namespace, entry.flag, 0)); } else if (entry.type == boolean.class) { mCoreSettings.putInt(entry.coreSettingKey, DeviceConfig.getBoolean(entry.namespace, entry.flag, false) ? 1 : 0); } } } } Loading
core/java/android/widget/Editor.java +12 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; Loading Loading @@ -384,6 +385,10 @@ public class Editor { private final SuggestionHelper mSuggestionHelper = new SuggestionHelper(); // Specifies whether the cursor control feature set is enabled. // This can only be true if the text view is editable. private final boolean mCursorControlEnabled; Editor(TextView textView) { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. Loading @@ -397,6 +402,13 @@ public class Editor { Magnifier.createBuilderWithOldMagnifierDefaults(mTextView).build(); mMagnifierAnimator = new MagnifierMotionAnimator(magnifier); } mCursorControlEnabled = AppGlobals.getIntCoreSetting( WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0; if (TextView.DEBUG_CURSOR) { logCursor("Editor", "Cursor control is %s.", mCursorControlEnabled ? "enabled" : "disabled"); } } ParcelableParcel saveInstanceState() { Loading
core/java/android/widget/WidgetFlags.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package android.widget; /** * Keeps the flags related to the Widget namespace in {@link DeviceConfig}. * * @hide */ public final class WidgetFlags { /** * Whether the cursor control feature set is enabled. * TODO: Makes this flag key visible to webview/chrome. */ public static final String ENABLE_CURSOR_CONTROL = "CursorControlFeature__enable_cursor_control"; /** * The key name used in app core settings for enable cursor control. */ public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control"; private WidgetFlags() { } }
services/core/java/com/android/server/am/CoreSettingsObserver.java +57 −0 Original line number Diff line number Diff line Loading @@ -16,15 +16,21 @@ package com.android.server.am; import android.app.ActivityThread; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.provider.DeviceConfig; import android.provider.Settings; import android.widget.WidgetFlags; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; /** Loading @@ -36,6 +42,19 @@ import java.util.Map; final class CoreSettingsObserver extends ContentObserver { private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName(); private static class DeviceConfigEntry { String namespace; String flag; String coreSettingKey; Class<?> type; DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<?> type) { this.namespace = namespace; this.flag = flag; this.coreSettingKey = coreSettingKey; this.type = type; } } // mapping form property name to its type @VisibleForTesting static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap< Loading @@ -46,6 +65,7 @@ final class CoreSettingsObserver extends ContentObserver { @VisibleForTesting static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap< String, Class<?>>(); static final List<DeviceConfigEntry> sDeviceConfigEntries = new ArrayList<DeviceConfigEntry>(); static { sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class); Loading Loading @@ -84,6 +104,11 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... sDeviceConfigEntries.add(new DeviceConfigEntry( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL, WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class)); // add other device configs here... } private final Bundle mCoreSettings = new Bundle(); Loading Loading @@ -112,6 +137,7 @@ final class CoreSettingsObserver extends ContentObserver { populateSettings(mCoreSettings, sSecureSettingToTypeMap); populateSettings(mCoreSettings, sSystemSettingToTypeMap); populateSettings(mCoreSettings, sGlobalSettingToTypeMap); populateSettingsFromDeviceConfig(); mActivityManagerService.onCoreSettingsChange(mCoreSettings); } Loading @@ -133,6 +159,16 @@ final class CoreSettingsObserver extends ContentObserver { mActivityManagerService.mContext.getContentResolver().registerContentObserver( uri, false, this); } HashSet<String> deviceConfigNamespaces = new HashSet<>(); for (DeviceConfigEntry entry : sDeviceConfigEntries) { if (!deviceConfigNamespaces.contains(entry.namespace)) { DeviceConfig.addOnPropertiesChangedListener( entry.namespace, ActivityThread.currentApplication().getMainExecutor(), (DeviceConfig.Properties prop) -> onChange(false)); deviceConfigNamespaces.add(entry.namespace); } } } @VisibleForTesting Loading Loading @@ -164,4 +200,25 @@ final class CoreSettingsObserver extends ContentObserver { } } } private void populateSettingsFromDeviceConfig() { for (DeviceConfigEntry entry : sDeviceConfigEntries) { if (entry.type == String.class) { mCoreSettings.putString(entry.coreSettingKey, DeviceConfig.getString(entry.namespace, entry.flag, "")); } else if (entry.type == int.class) { mCoreSettings.putInt(entry.coreSettingKey, DeviceConfig.getInt(entry.namespace, entry.flag, 0)); } else if (entry.type == float.class) { mCoreSettings.putFloat(entry.coreSettingKey, DeviceConfig.getFloat(entry.namespace, entry.flag, 0)); } else if (entry.type == long.class) { mCoreSettings.putLong(entry.coreSettingKey, DeviceConfig.getLong(entry.namespace, entry.flag, 0)); } else if (entry.type == boolean.class) { mCoreSettings.putInt(entry.coreSettingKey, DeviceConfig.getBoolean(entry.namespace, entry.flag, false) ? 1 : 0); } } } }