1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.internal.accessibility.dialog; 17 18 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; 19 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; 20 import static android.view.accessibility.AccessibilityManager.ShortcutType; 21 22 import static com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode; 23 import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.createEnableDialogContentView; 24 import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getInstalledTargets; 25 import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets; 26 import static com.android.internal.accessibility.util.AccessibilityUtils.isUserSetupCompleted; 27 28 import android.annotation.Nullable; 29 import android.app.Activity; 30 import android.app.AlertDialog; 31 import android.content.DialogInterface; 32 import android.content.res.TypedArray; 33 import android.os.Bundle; 34 import android.view.View; 35 import android.view.Window; 36 import android.widget.AdapterView; 37 38 import com.android.internal.R; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 /** 44 * Activity used to display various targets related to accessibility service, accessibility 45 * activity or allowlisting feature for volume key shortcut. 46 */ 47 public class AccessibilityShortcutChooserActivity extends Activity { 48 @ShortcutType 49 private final int mShortcutType = ACCESSIBILITY_SHORTCUT_KEY; 50 private final List<AccessibilityTarget> mTargets = new ArrayList<>(); 51 private AlertDialog mMenuDialog; 52 private AlertDialog mPermissionDialog; 53 private ShortcutTargetAdapter mTargetAdapter; 54 55 @Override onCreate(@ullable Bundle savedInstanceState)56 protected void onCreate(@Nullable Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 59 final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme); 60 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, /* defValue= */ false)) { 61 requestWindowFeature(Window.FEATURE_NO_TITLE); 62 } 63 64 mTargets.addAll(getTargets(this, mShortcutType)); 65 mTargetAdapter = new ShortcutTargetAdapter(mTargets); 66 mMenuDialog = createMenuDialog(); 67 mMenuDialog.setOnShowListener(dialog -> updateDialogListeners()); 68 mMenuDialog.show(); 69 } 70 71 @Override onDestroy()72 protected void onDestroy() { 73 mMenuDialog.dismiss(); 74 super.onDestroy(); 75 } 76 onTargetSelected(AdapterView<?> parent, View view, int position, long id)77 private void onTargetSelected(AdapterView<?> parent, View view, int position, long id) { 78 final AccessibilityTarget target = mTargets.get(position); 79 target.onSelected(); 80 mMenuDialog.dismiss(); 81 } 82 onTargetChecked(AdapterView<?> parent, View view, int position, long id)83 private void onTargetChecked(AdapterView<?> parent, View view, int position, long id) { 84 final AccessibilityTarget target = mTargets.get(position); 85 86 if ((target instanceof AccessibilityServiceTarget) && !target.isShortcutEnabled()) { 87 mPermissionDialog = new AlertDialog.Builder(this) 88 .setView(createEnableDialogContentView(this, 89 (AccessibilityServiceTarget) target, 90 v -> { 91 mPermissionDialog.dismiss(); 92 mTargetAdapter.notifyDataSetChanged(); 93 }, 94 v -> mPermissionDialog.dismiss())) 95 .create(); 96 mPermissionDialog.show(); 97 return; 98 } 99 100 target.onCheckedChanged(!target.isShortcutEnabled()); 101 mTargetAdapter.notifyDataSetChanged(); 102 } 103 onDoneButtonClicked()104 private void onDoneButtonClicked() { 105 mTargets.clear(); 106 mTargets.addAll(getTargets(this, mShortcutType)); 107 if (mTargets.isEmpty()) { 108 mMenuDialog.dismiss(); 109 return; 110 } 111 112 mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.LAUNCH); 113 mTargetAdapter.notifyDataSetChanged(); 114 115 mMenuDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText( 116 getString(R.string.edit_accessibility_shortcut_menu_button)); 117 118 updateDialogListeners(); 119 } 120 onEditButtonClicked()121 private void onEditButtonClicked() { 122 mTargets.clear(); 123 mTargets.addAll(getInstalledTargets(this, mShortcutType)); 124 mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.EDIT); 125 mTargetAdapter.notifyDataSetChanged(); 126 127 mMenuDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText( 128 getString(R.string.done_accessibility_shortcut_menu_button)); 129 130 updateDialogListeners(); 131 } 132 updateDialogListeners()133 private void updateDialogListeners() { 134 final boolean isEditMenuMode = 135 mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT; 136 final int selectDialogTitleId = R.string.accessibility_select_shortcut_menu_title; 137 final int editDialogTitleId = 138 mShortcutType == ACCESSIBILITY_BUTTON 139 ? R.string.accessibility_edit_shortcut_menu_button_title 140 : R.string.accessibility_edit_shortcut_menu_volume_title; 141 142 mMenuDialog.setTitle(getString(isEditMenuMode ? editDialogTitleId : selectDialogTitleId)); 143 mMenuDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener( 144 isEditMenuMode ? view -> onDoneButtonClicked() : view -> onEditButtonClicked()); 145 mMenuDialog.getListView().setOnItemClickListener( 146 isEditMenuMode ? this::onTargetChecked : this::onTargetSelected); 147 } 148 createMenuDialog()149 private AlertDialog createMenuDialog() { 150 final String dialogTitle = 151 getString(R.string.accessibility_select_shortcut_menu_title); 152 153 final AlertDialog.Builder builder = new AlertDialog.Builder(this) 154 .setTitle(dialogTitle) 155 .setAdapter(mTargetAdapter, /* listener= */ null) 156 .setOnDismissListener(dialog -> finish()); 157 158 if (isUserSetupCompleted(this)) { 159 final String positiveButtonText = 160 getString(R.string.edit_accessibility_shortcut_menu_button); 161 builder.setPositiveButton(positiveButtonText, /* listener= */ null); 162 } 163 164 return builder.create(); 165 } 166 } 167