diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java new file mode 100644 index 0000000000000..dd2f0af6fbe34 --- /dev/null +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 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.internal.accessibility.dialog; + +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; +import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; + +import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets; +import static com.android.internal.util.Preconditions.checkArgument; + +import android.annotation.Nullable; +import android.app.Activity; +import android.os.Bundle; +import android.provider.Settings; +import android.text.TextUtils; +import android.view.View; +import android.view.accessibility.AccessibilityManager; +import android.widget.GridView; +import android.widget.TextView; + +import com.android.internal.R; +import com.android.internal.widget.ResolverDrawerLayout; + +import java.util.ArrayList; +import java.util.List; + +/** + * Activity used to display and persist a service or feature target for the Accessibility button. + */ +public class AccessibilityButtonChooserActivity extends Activity { + private final List mTargets = new ArrayList<>(); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.accessibility_button_chooser); + + final int shortcutType = getIntent().getIntExtra(AccessibilityManager.EXTRA_SHORTCUT_TYPE, + /* unexpectedShortcutType */ -1); + final boolean existInShortcutType = (shortcutType == ACCESSIBILITY_BUTTON) + || (shortcutType == ACCESSIBILITY_SHORTCUT_KEY); + checkArgument(existInShortcutType, "Unexpected shortcut type: " + shortcutType); + + final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel); + if (rdl != null) { + rdl.setOnDismissedListener(this::finish); + } + + final String component = Settings.Secure.getString(getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); + + final AccessibilityManager accessibilityManager = + getSystemService(AccessibilityManager.class); + final boolean isTouchExploreOn = + accessibilityManager.isTouchExplorationEnabled(); + final boolean isGestureNavigateEnabled = + NAV_BAR_MODE_GESTURAL == getResources().getInteger( + com.android.internal.R.integer.config_navBarInteractionMode); + + if (isGestureNavigateEnabled) { + final TextView promptPrologue = findViewById(R.id.accessibility_button_prompt_prologue); + promptPrologue.setText(isTouchExploreOn + ? R.string.accessibility_gesture_3finger_prompt_text + : R.string.accessibility_gesture_prompt_text); + } + + if (TextUtils.isEmpty(component)) { + final TextView prompt = findViewById(R.id.accessibility_button_prompt); + if (isGestureNavigateEnabled) { + prompt.setText(isTouchExploreOn + ? R.string.accessibility_gesture_3finger_instructional_text + : R.string.accessibility_gesture_instructional_text); + } + prompt.setVisibility(View.VISIBLE); + } + + mTargets.addAll(getTargets(this, shortcutType)); + + final GridView gridview = findViewById(R.id.accessibility_button_chooser_grid); + gridview.setAdapter(new ButtonTargetAdapter(mTargets)); + gridview.setOnItemClickListener((parent, view, position, id) -> { + final String key = Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT; + Settings.Secure.putString(getContentResolver(), key, mTargets.get(position).getId()); + finish(); + }); + } +} diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java index e8d2813fe39ed..74bbe05500f31 100644 --- a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java +++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java @@ -149,10 +149,10 @@ public class AccessibilityShortcutChooserActivity extends Activity { private void updateDialogListeners() { final boolean isEditMenuMode = - (mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT); + mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT; final int selectDialogTitleId = R.string.accessibility_select_shortcut_menu_title; final int editDialogTitleId = - (mShortcutType == ACCESSIBILITY_BUTTON) + mShortcutType == ACCESSIBILITY_BUTTON ? R.string.accessibility_edit_shortcut_menu_button_title : R.string.accessibility_edit_shortcut_menu_volume_title; diff --git a/core/java/com/android/internal/accessibility/dialog/ButtonTargetAdapter.java b/core/java/com/android/internal/accessibility/dialog/ButtonTargetAdapter.java new file mode 100644 index 0000000000000..9f472ac4dcdb8 --- /dev/null +++ b/core/java/com/android/internal/accessibility/dialog/ButtonTargetAdapter.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 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.internal.accessibility.dialog; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.internal.R; + +import java.util.List; + +/** + * Extension for {@link TargetAdapter} and used for AccessibilityButtonChooserActivity. + */ +class ButtonTargetAdapter extends TargetAdapter { + private List mTargets; + + ButtonTargetAdapter(List targets) { + mTargets = targets; + } + + @Override + public int getCount() { + return mTargets.size(); + } + + @Override + public Object getItem(int position) { + return mTargets.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final Context context = parent.getContext(); + final View root = LayoutInflater.from(context).inflate( + R.layout.accessibility_button_chooser_item, parent, /* attachToRoot= */ + false); + final AccessibilityTarget target = mTargets.get(position); + final ImageView iconView = root.findViewById(R.id.accessibility_button_target_icon); + final TextView labelView = root.findViewById(R.id.accessibility_button_target_label); + iconView.setImageDrawable(target.getIcon()); + labelView.setText(target.getLabel()); + return root; + } +} diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java index c338a292646bc..100422f5660df 100644 --- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java +++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java @@ -151,7 +151,7 @@ public final class ShortcutUtils { public static String convertToKey(@UserShortcutType int type) { switch (type) { case UserShortcutType.SOFTWARE: - return Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT; + return Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS; case UserShortcutType.HARDWARE: return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE; case UserShortcutType.TRIPLETAP: diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ee25ac27b25c7..d21376467edc1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5072,6 +5072,20 @@ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden" android:process=":ui" android:visibleToInstantApps="true"> + + + + + diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml new file mode 100644 index 0000000000000..2f97bae2a80ec --- /dev/null +++ b/core/res/res/layout/accessibility_button_chooser.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml new file mode 100644 index 0000000000000..33d6fa2862f76 --- /dev/null +++ b/core/res/res/layout/accessibility_button_chooser_item.xml @@ -0,0 +1,53 @@ + + + + + + + + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5f93506d7ba2b..431549713f44d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3241,6 +3241,18 @@ + + + + + + + + + + + +