Merge "[Settings] Present EID in About phone page"
diff --git a/res/drawable/ic_modifier_keys_reset.xml b/res/drawable/ic_modifier_keys_reset.xml
new file mode 100644
index 0000000..a8cc198
--- /dev/null
+++ b/res/drawable/ic_modifier_keys_reset.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?androidprv:attr/colorAccentPrimaryVariant">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,4C13.58,0.69 7.31,1.58 4,6V4H2v6h6V8H5.09c1.44,-2.47 4.09,-3.98 6.94,-3.97c4.42,0.02 7.99,3.61 7.97,8.03s-3.61,7.99 -8.03,7.97C7.55,20.01 3.98,16.42 4,12H2c0,3.15 1.48,6.11 4,8c4.42,3.31 10.69,2.42 14,-2C23.31,13.58 22.42,7.31 18,4z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/modifier_key_bordered.xml b/res/drawable/modifier_key_bordered.xml
new file mode 100644
index 0000000..17f0090
--- /dev/null
+++ b/res/drawable/modifier_key_bordered.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="24dp" />
+ <solid android:color="@android:color/transparent"/>
+ <stroke
+ android:width="1dp"
+ android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/modifier_key_colored.xml b/res/drawable/modifier_key_colored.xml
new file mode 100644
index 0000000..2bb033b
--- /dev/null
+++ b/res/drawable/modifier_key_colored.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="24dp"/>
+ <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/modifier_key_lisetview_background.xml b/res/drawable/modifier_key_lisetview_background.xml
new file mode 100644
index 0000000..b65c61e
--- /dev/null
+++ b/res/drawable/modifier_key_lisetview_background.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="24dp"/>
+ <solid android:color="?androidprv:attr/colorSurfaceVariant"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
\ No newline at end of file
diff --git a/res/layout/modifier_key_item.xml b/res/layout/modifier_key_item.xml
new file mode 100644
index 0000000..7bd344c
--- /dev/null
+++ b/res/layout/modifier_key_item.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="8dip"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingEnd="?android:attr/scrollbarSize"
+ android:layout_weight="1">
+
+ <ImageView
+ android:id="@+id/modifier_key_check_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginStart="24dip"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:src="@drawable/ic_check_24dp"
+ android:tint="?androidprv:attr/colorAccentPrimaryVariant"/>
+
+ <TextView
+ android:id="@+id/modifier_key_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:textDirection="locale"
+ android:padding="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_toEndOf="@+id/modifier_key_check_icon"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+</RelativeLayout>
diff --git a/res/layout/modifier_key_picker_dialog.xml b/res/layout/modifier_key_picker_dialog.xml
new file mode 100644
index 0000000..8600348
--- /dev/null
+++ b/res/layout/modifier_key_picker_dialog.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:id="@+id/modifier_key_fragment_container"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:divider="?android:dividerHorizontal"
+ android:showDividers="end" >
+ <TextView
+ android:id="@+id/modifier_key_picker_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dip"
+ android:layout_marginBottom="8dip"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_picker_title"/>
+
+ <TextView
+ android:id="@+id/modifier_key_picker_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="16dip"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"/>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:divider="?android:dividerHorizontal"
+ android:showDividers="end">
+ <ListView
+ android:id="@+id/modifier_key_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:divider="@null"
+ android:dividerHeight="8dp"
+ android:padding="16dip"
+ android:listSelector="@drawable/modifier_key_lisetview_background"
+ />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dip"
+ android:layout_marginEnd="8dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1">
+
+ <Button
+ android:id="@+id/modifier_key_cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_marginStart="8dip"
+ android:layout_alignParentStart="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonCancel"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_cancel"/>
+
+ <Button
+ android:id="@+id/modifier_key_done_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_marginEnd="8dip"
+ android:layout_alignParentEnd="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonDone"
+ android:textColor="?androidprv:attr/textColorOnAccent"
+ android:text="@string/modifier_keys_done"/>
+
+ </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/modifier_key_reset_dialog.xml b/res/layout/modifier_key_reset_dialog.xml
new file mode 100644
index 0000000..fd38b11
--- /dev/null
+++ b/res/layout/modifier_key_reset_dialog.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView
+ android:id="@+id/modifier_key_reset_dialog_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dip"
+ android:layout_marginBottom="8dip"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_reset_title" />
+
+ <TextView
+ android:id="@+id/modifier_key_reset_dialog_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="16dip"
+ android:layout_marginStart="32dip"
+ android:layout_marginEnd="32dip"
+ android:gravity="center"
+ android:layout_gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/modifier_keys_reset_message" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="8dip"
+ android:layout_marginEnd="8dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1">
+
+ <Button
+ android:id="@+id/modifier_key_reset_cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_marginStart="8dip"
+ android:layout_alignParentStart="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonCancel"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_cancel"/>
+
+ <Button
+ android:id="@+id/modifier_key_reset_restore_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_marginEnd="8dip"
+ android:layout_alignParentEnd="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonCancel"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_restore"/>
+
+ </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2a2cccf..59b3f20 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3735,6 +3735,37 @@
<!-- Summary text for 'Switch apps' [CHAR LIMIT=60] -->
<string name="trackpad_switch_apps_summary">Swipe left or right with four fingers</string>
+ <!-- Title for the button to trigger the 'modifier keys settings' page. [CHAR LIMIT=35] -->
+ <string name="modifier_keys_settings">Modifier keys</string>
+ <!-- Summary text for the 'modifier_keys_settings' page. [CHAR LIMIT=100] -->
+ <string name="modifier_keys_settings_summary">Change the behavior of keys</string>
+
+ <!-- Title for the button to trigger the 'modifier keys caps lock'. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_caps_lock" translatable="false">Caps lock</string>
+ <!-- Title for the button to trigger the 'modifier keys ctrl'. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_ctrl" translatable="false">Ctrl</string>
+ <!-- Title for the button to trigger the 'modifier keys meta'. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_meta" translatable="false">Meta</string>
+ <!-- Title for the button to trigger the 'modifier keys alt'. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_alt" translatable="false">Alt</string>
+
+ <!-- Title for the button to trigger the 'modifier keys reset all'. [CHAR LIMIT=35] -->
+ <string name="modifier_keys_reset_title">Reset all</string>
+ <!-- Summary text for the buttons. [CHAR LIMIT=35] -->
+ <string name="modifier_keys_default_summary">Default</string>
+ <!-- Message for the 'Reset all' page. [CHAR LIMIT=100] -->
+ <string name="modifier_keys_reset_message">Are you sure you would like to reset all the modifier keys to their default?</string>
+ <!-- Text of the done button. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_done">Done</string>
+ <!-- Text of the cancel button. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_cancel">Cancel</string>
+ <!-- Text of the restore button. [CHAR LIMIT=15] -->
+ <string name="modifier_keys_restore">Restore</string>
+ <!-- Title for the modifier key picker dialog page [CHAR LIMIT=35] -->
+ <string name="modifier_keys_picker_title">Choose modifier key</string>
+ <!-- Summary for the modifier key picker dialog page [CHAR LIMIT=35] -->
+ <string name="modifier_keys_picker_summary">Choose a new key for <xliff:g id="modifier_key_default_name">%1$s</xliff:g>:</string>
+
<!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
<string name="default_keyboard_layout">Default</string>
@@ -8198,7 +8229,7 @@
<!-- [CHAR LIMIT=60] turn eSim deletion confirmation on/off -->
<string name="confirm_sim_deletion_title">Confirm SIM deletion</string>
<!-- [CHAR LIMIT=NONE] eSim deletion confirmation description -->
- <string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing a eSIM</string>
+ <string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing an eSIM</string>
<!-- [CHAR LIMIT=32] Name of Advanced memory protection page in "More Security Settings" and heading of page. -->
<string name="memtag_title">Advanced memory protection beta</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 20ebe255..c262264 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -378,6 +378,20 @@
<item name="android:colorControlHighlight">@color/ripple_material_inverse</item>
</style>
+ <style name="ModifierKeyButtonCancel" parent="@android:style/Widget.Material.Button">
+ <item name="android:background">@drawable/modifier_key_bordered</item>
+ <item name="android:stateListAnimator">@null</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:padding">4dp</item>
+ </style>
+
+ <style name="ModifierKeyButtonDone" parent="@android:style/Widget.Material.Button">
+ <item name="android:background">@drawable/modifier_key_colored</item>
+ <item name="android:stateListAnimator">@null</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:padding">4dp</item>
+ </style>
+
<style name="LockPatternContainerStyle">
<item name="android:gravity">center</item>
<item name="android:maxHeight">@dimen/biometric_auth_pattern_view_max_size</item>
diff --git a/res/xml/modifier_keys_settings.xml b/res/xml/modifier_keys_settings.xml
new file mode 100644
index 0000000..63e7ee1
--- /dev/null
+++ b/res/xml/modifier_keys_settings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/modifier_keys_settings"
+ android:key="modifier_keys_all"
+ settings:controller="com.android.settings.inputmethod.ModifierKeysPreferenceController">
+ <Preference
+ android:key="modifier_keys_caps_lock"
+ android:title="@string/modifier_keys_caps_lock"
+ android:summary="@string/modifier_keys_default_summary"/>
+
+ <Preference
+ android:key="modifier_keys_ctrl"
+ android:title="@string/modifier_keys_ctrl"
+ android:summary="@string/modifier_keys_default_summary"/>
+
+ <Preference
+ android:key="modifier_keys_meta"
+ android:title="@string/modifier_keys_meta"
+ android:summary="@string/modifier_keys_default_summary"/>
+
+ <Preference
+ android:key="modifier_keys_alt"
+ android:title="@string/modifier_keys_alt"
+ android:summary="@string/modifier_keys_default_summary"/>
+
+ <Preference
+ android:key="modifier_keys_restore"
+ android:icon="@drawable/ic_modifier_keys_reset"
+ settings:controller="com.android.settings.inputmethod.ModifierKeysRestorePreferenceController"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/physical_keyboard_settings.xml b/res/xml/physical_keyboard_settings.xml
index 54a5c65..40851a9 100644
--- a/res/xml/physical_keyboard_settings.xml
+++ b/res/xml/physical_keyboard_settings.xml
@@ -31,5 +31,11 @@
android:key="keyboard_shortcuts_helper"
android:title="@string/keyboard_shortcuts_helper"
android:summary="@string/keyboard_shortcuts_helper_summary" />
+
+ <Preference
+ android:key="modifier_keys_settings"
+ android:title="@string/modifier_keys_settings"
+ android:summary="@string/modifier_keys_settings_summary"
+ android:fragment="com.android.settings.inputmethod.ModifierKeysSettings" />
</PreferenceCategory>
</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
index 22bef28..7316e12 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
@@ -210,6 +210,8 @@
@Override
public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
if (mNeedResetSettings) {
outState.putBoolean(NEED_RESET_SETTINGS, true);
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index db23c43..1e66871 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -121,6 +121,7 @@
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
import com.android.settings.inputmethod.KeyboardSettings;
+import com.android.settings.inputmethod.ModifierKeysSettings;
import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import com.android.settings.inputmethod.SpellCheckersSettings;
@@ -217,6 +218,7 @@
LanguageAndInputSettings.class.getName(),
LanguageSettings.class.getName(),
KeyboardSettings.class.getName(),
+ ModifierKeysSettings.class.getName(),
NewKeyboardLayoutEnabledLocalesFragment.class.getName(),
TrackpadSettings.class.getName(),
SpellCheckersSettings.class.getName(),
diff --git a/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java
new file mode 100644
index 0000000..40c15ff
--- /dev/null
+++ b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2022 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 com.android.settings.inputmethod;
+
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settingslib.Utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ModifierKeysPickerDialogFragment extends DialogFragment {
+
+ private Preference mPreference;
+ private String mKeyDefaultName;
+ private Context mContext;
+
+ public ModifierKeysPickerDialogFragment() {
+ }
+
+ public ModifierKeysPickerDialogFragment(Preference preference) {
+ mPreference = preference;
+ mKeyDefaultName = preference.getTitle().toString();
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ super.onCreateDialog(savedInstanceState);
+ mContext = getActivity();
+ String[] modifierKeys = new String[] {
+ mContext.getString(R.string.modifier_keys_caps_lock),
+ mContext.getString(R.string.modifier_keys_ctrl),
+ mContext.getString(R.string.modifier_keys_meta),
+ mContext.getString(R.string.modifier_keys_alt)};
+
+ View dialoglayout =
+ LayoutInflater.from(mContext).inflate(R.layout.modifier_key_picker_dialog, null);
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+ dialogBuilder.setView(dialoglayout);
+
+ TextView summary = dialoglayout.findViewById(R.id.modifier_key_picker_summary);
+ CharSequence summaryText = mContext.getString(
+ R.string.modifier_keys_picker_summary, mKeyDefaultName);
+ summary.setText(summaryText);
+
+ List<String> list = new ArrayList<>();
+ for (int i = 0; i < modifierKeys.length; i++) {
+ list.add(modifierKeys[i]);
+ }
+ ModifierKeyAdapter adapter = new ModifierKeyAdapter(list);
+ ListView listView = dialoglayout.findViewById(R.id.modifier_key_picker);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
+ adapter.setCurrentItem(i);
+ adapter.setClick(true);
+ adapter.notifyDataSetChanged();
+ }
+ });
+
+ AlertDialog modifierKeyDialog = dialogBuilder.create();
+ Button doneButton = dialoglayout.findViewById(R.id.modifier_key_done_button);
+ doneButton.setOnClickListener(v -> {
+ String selectedItem = list.get(adapter.getCurrentItem());
+ Spannable itemSummary;
+ if (selectedItem.equals(mKeyDefaultName)) {
+ itemSummary = new SpannableString(
+ mContext.getString(R.string.modifier_keys_default_summary));
+ itemSummary.setSpan(
+ new ForegroundColorSpan(getColorOfTextColorSecondary()),
+ 0, itemSummary.length(), 0);
+ // TODO(b/252812993): remapModifierKey
+ } else {
+ itemSummary = new SpannableString(selectedItem);
+ itemSummary.setSpan(
+ new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
+ 0, itemSummary.length(), 0);
+ }
+ mPreference.setSummary(itemSummary);
+ modifierKeyDialog.dismiss();
+ });
+
+ Button cancelButton = dialoglayout.findViewById(R.id.modifier_key_cancel_button);
+ cancelButton.setOnClickListener(v -> {
+ modifierKeyDialog.dismiss();
+ });
+
+ final Window window = modifierKeyDialog.getWindow();
+ window.setType(TYPE_SYSTEM_DIALOG);
+
+ return modifierKeyDialog;
+ }
+
+ class ModifierKeyAdapter extends BaseAdapter {
+ private int mCurrentItem = 0;
+ private boolean mIsClick = false;
+ private List<String> mList;
+
+ ModifierKeyAdapter(List<String> list) {
+ this.mList = list;
+ }
+
+ @Override
+ public int getCount() {
+ return mList.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mList.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ if (view == null) {
+ view = LayoutInflater.from(mContext).inflate(R.layout.modifier_key_item, null);
+ }
+ TextView textView = view.findViewById(R.id.modifier_key_text);
+ ImageView checkIcon = view.findViewById(R.id.modifier_key_check_icon);
+ textView.setText(mList.get(i));
+ if (mCurrentItem == i && mIsClick) {
+ textView.setTextColor(getColorOfColorAccentPrimaryVariant());
+ checkIcon.setImageAlpha(255);
+ } else {
+ textView.setTextColor(getColorOfTextColorPrimary());
+ checkIcon.setImageAlpha(0);
+ }
+ return view;
+ }
+
+ public void setCurrentItem(int currentItem) {
+ this.mCurrentItem = currentItem;
+ }
+
+ public int getCurrentItem() {
+ return this.mCurrentItem;
+ }
+
+ public void setClick(boolean click) {
+ this.mIsClick = click;
+ }
+ }
+
+ private int getColorOfTextColorPrimary() {
+ return Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
+ }
+
+ private int getColorOfTextColorSecondary() {
+ return Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary);
+ }
+
+ private int getColorOfColorAccentPrimaryVariant() {
+ return Utils.getColorAttrDefaultColor(
+ mContext, com.android.internal.R.attr.colorAccentPrimaryVariant);
+ }
+}
diff --git a/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java b/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java
new file mode 100644
index 0000000..a7f8a37
--- /dev/null
+++ b/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 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 com.android.settings.inputmethod;
+
+import android.content.Context;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class ModifierKeysPreferenceController extends BasePreferenceController {
+
+ private static String KEY_TAG = "modifier_keys_dialog_tag";
+ private static String KEY_RESTORE_PREFERENCE = "modifier_keys_restore";
+
+ private Fragment mParent;
+ private FragmentManager mFragmentManager;
+
+ public ModifierKeysPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setFragment(Fragment parent) {
+ mParent = parent;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ // TODO: getModifierKeyRemapping()
+ // setTitle
+ // setSummary
+ if (mParent == null) {
+ return;
+ }
+ // The dialog screen depends on the previous selected key's fragment.
+ // In the rotation scenario, we should remove the previous dialog screen first.
+ clearPreviousDialog();
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (preference.getKey().equals(KEY_RESTORE_PREFERENCE)) {
+ return false;
+ }
+ showModifierKeysDialog(preference);
+ return true;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ private void showModifierKeysDialog(Preference preference) {
+ ModifierKeysPickerDialogFragment fragment =
+ new ModifierKeysPickerDialogFragment(preference);
+ fragment.setTargetFragment(mParent, 0);
+ fragment.show(mFragmentManager, KEY_TAG);
+ }
+
+ private void clearPreviousDialog() {
+ mFragmentManager = mParent.getFragmentManager();
+ DialogFragment preKeysDialogFragment =
+ (DialogFragment) mFragmentManager.findFragmentByTag(KEY_TAG);
+ if (preKeysDialogFragment != null) {
+ preKeysDialogFragment.dismiss();
+ }
+ }
+}
diff --git a/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java b/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java
new file mode 100644
index 0000000..0b605a0
--- /dev/null
+++ b/src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2022 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 com.android.settings.inputmethod;
+
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.Utils;
+
+public class ModifierKeysResetDialogFragment extends DialogFragment {
+ private static final String MODIFIER_KEYS_CAPS_LOCK = "modifier_keys_caps_lock";
+ private static final String MODIFIER_KEYS_CTRL = "modifier_keys_ctrl";
+ private static final String MODIFIER_KEYS_META = "modifier_keys_meta";
+ private static final String MODIFIER_KEYS_ALT = "modifier_keys_alt";
+
+ private PreferenceScreen mScreen;
+ private String[] mKeys = {
+ MODIFIER_KEYS_CAPS_LOCK,
+ MODIFIER_KEYS_CTRL,
+ MODIFIER_KEYS_META,
+ MODIFIER_KEYS_ALT};
+
+ public ModifierKeysResetDialogFragment() {
+ }
+
+ public ModifierKeysResetDialogFragment(PreferenceScreen screen) {
+ mScreen = screen;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ super.onCreateDialog(savedInstanceState);
+ Context mContext = getActivity();
+ View dialoglayout =
+ LayoutInflater.from(mContext).inflate(R.layout.modifier_key_reset_dialog, null);
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+ dialogBuilder.setView(dialoglayout);
+ AlertDialog modifierKeyResetDialog = dialogBuilder.create();
+
+ Button restoreButton = dialoglayout.findViewById(R.id.modifier_key_reset_restore_button);
+ restoreButton.setOnClickListener(v -> {
+ resetToDefault();
+ modifierKeyResetDialog.dismiss();
+ });
+
+ Button cancelButton = dialoglayout.findViewById(R.id.modifier_key_reset_cancel_button);
+ cancelButton.setOnClickListener(v -> {
+ modifierKeyResetDialog.dismiss();
+ });
+
+ final Window window = modifierKeyResetDialog.getWindow();
+ window.setType(TYPE_SYSTEM_DIALOG);
+
+ return modifierKeyResetDialog;
+ }
+
+ private void resetToDefault() {
+ Context mContext = getActivity();
+ for (int i = 0; i < mKeys.length; i++) {
+ Preference preference = mScreen.findPreference(mKeys[i]);
+ Spannable title = new SpannableString(
+ mContext.getString(R.string.modifier_keys_default_summary));
+ title.setSpan(
+ new ForegroundColorSpan(getColorOfTextColorSecondary()),
+ 0, title.length(), 0);
+ preference.setSummary(title);
+ }
+ // TODO(b/252812993): clearAllModifierKeyRemappings()
+ }
+
+ private int getColorOfTextColorSecondary() {
+ return Utils.getColorAttrDefaultColor(getActivity(), android.R.attr.textColorSecondary);
+ }
+}
diff --git a/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java b/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java
new file mode 100644
index 0000000..159cc11
--- /dev/null
+++ b/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 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 com.android.settings.inputmethod;
+
+import android.content.Context;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.Utils;
+
+public class ModifierKeysRestorePreferenceController extends BasePreferenceController {
+
+ private static String KEY_TAG = "modifier_keys_dialog_tag";
+
+ private Fragment mParent;
+ private FragmentManager mFragmentManager;
+ private PreferenceScreen mScreen;
+
+ public ModifierKeysRestorePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setFragment(Fragment parent) {
+ mParent = parent;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ if (mParent == null) {
+ return;
+ }
+ mScreen = screen;
+ // The dialog screen depends on the previous selected key's fragment.
+ // In the rotation scenario, we should remove the previous dialog first.
+ clearPreviousDialog();
+ setResetKeyColor();
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!preference.getKey().equals(getPreferenceKey())) {
+ return false;
+ }
+ showResetDialog();
+ return true;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ private void showResetDialog() {
+ ModifierKeysResetDialogFragment fragment =
+ new ModifierKeysResetDialogFragment(mScreen);
+ fragment.setTargetFragment(mParent, 0);
+ fragment.show(mFragmentManager, KEY_TAG);
+ }
+
+ private void setResetKeyColor() {
+ Preference preference = mScreen.findPreference(getPreferenceKey());
+ Spannable title = new SpannableString(
+ mParent.getActivity().getString(R.string.modifier_keys_reset_title));
+ title.setSpan(
+ new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
+ 0, title.length(), 0);
+ preference.setTitle(title);
+ }
+
+ private int getColorOfColorAccentPrimaryVariant() {
+ return Utils.getColorAttrDefaultColor(
+ mParent.getActivity(), com.android.internal.R.attr.colorAccentPrimaryVariant);
+ }
+
+ private void clearPreviousDialog() {
+ mFragmentManager = mParent.getFragmentManager();
+ DialogFragment preResetDialogFragment =
+ (DialogFragment) mFragmentManager.findFragmentByTag(KEY_TAG);
+ if (preResetDialogFragment != null) {
+ preResetDialogFragment.dismiss();
+ }
+ }
+}
diff --git a/src/com/android/settings/inputmethod/ModifierKeysSettings.java b/src/com/android/settings/inputmethod/ModifierKeysSettings.java
new file mode 100644
index 0000000..2353c2c
--- /dev/null
+++ b/src/com/android/settings/inputmethod/ModifierKeysSettings.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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 com.android.settings.inputmethod;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+@SearchIndexable
+public class ModifierKeysSettings extends DashboardFragment {
+
+ private static final String TAG = "ModifierKeysSettings";
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ use(ModifierKeysPreferenceController.class).setFragment(this /*parent*/);
+ use(ModifierKeysRestorePreferenceController.class).setFragment(this /*parent*/);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_KEYBOARDS_MODIFIER_KEYS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.modifier_keys_settings;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.modifier_keys_settings) {
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return FeatureFlagUtils
+ .isEnabled(
+ context, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_MODIFIER_KEY);
+ }
+ };
+}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 38ea840..7d43d7c 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -67,6 +67,7 @@
private static final String KEYBOARD_OPTIONS_CATEGORY = "keyboard_options_category";
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
+ private static final String MODIFIER_KEYS_SETTINGS = "modifier_keys_settings";
@NonNull
private final ArrayList<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
@@ -94,9 +95,14 @@
mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
(SwitchPreference) mKeyboardAssistanceCategory.findPreference(
SHOW_VIRTUAL_KEYBOARD_SWITCH));
+
mIsNewKeyboardSettings = FeatureFlagUtils.isEnabled(
getContext(), FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
- // TODO(b/247080921): Support shortcuts list & modifier keys
+ boolean isModifierKeySettingsEnabled = FeatureFlagUtils
+ .isEnabled(getContext(), FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_MODIFIER_KEY);
+ if (!isModifierKeySettingsEnabled) {
+ mKeyboardAssistanceCategory.removePreference(findPreference(MODIFIER_KEYS_SETTINGS));
+ }
}
@Override