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 17 package com.android.internal.accessibility.dialog; 18 19 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON; 20 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY; 21 22 import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType; 23 import static com.android.internal.accessibility.util.ShortcutUtils.optInValueToSettings; 24 import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings; 25 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.graphics.drawable.Drawable; 31 import android.view.View; 32 import android.view.accessibility.AccessibilityManager; 33 import android.view.accessibility.AccessibilityManager.ShortcutType; 34 35 import com.android.internal.accessibility.common.ShortcutConstants; 36 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType; 37 import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder; 38 import com.android.internal.annotations.VisibleForTesting; 39 40 /** 41 * Abstract base class for creating various target related to accessibility service, accessibility 42 * activity, and allowlisting features. 43 * 44 * <p> Disables accessibility features that are not permitted in adding a restricted padlock icon 45 * and showing admin support message dialog. 46 */ 47 public abstract class AccessibilityTarget implements TargetOperations, OnTargetSelectedListener, 48 OnTargetCheckedChangeListener { 49 private Context mContext; 50 @ShortcutType 51 private int mShortcutType; 52 @AccessibilityFragmentType 53 private int mFragmentType; 54 private boolean mShortcutEnabled; 55 private String mId; 56 private int mUid; 57 private ComponentName mComponentName; 58 private CharSequence mLabel; 59 private Drawable mIcon; 60 private String mKey; 61 private CharSequence mStateDescription; 62 63 @VisibleForTesting AccessibilityTarget(Context context, @ShortcutType int shortcutType, @AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id, int uid, CharSequence label, Drawable icon, String key)64 public AccessibilityTarget(Context context, @ShortcutType int shortcutType, 65 @AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id, 66 int uid, CharSequence label, Drawable icon, String key) { 67 mContext = context; 68 mShortcutType = shortcutType; 69 mFragmentType = fragmentType; 70 mShortcutEnabled = isShortcutSwitched; 71 mId = id; 72 mUid = uid; 73 mComponentName = ComponentName.unflattenFromString(id); 74 mLabel = label; 75 mIcon = icon; 76 mKey = key; 77 } 78 79 @Override updateActionItem(@onNull ViewHolder holder, @ShortcutConstants.ShortcutMenuMode int shortcutMenuMode)80 public void updateActionItem(@NonNull ViewHolder holder, 81 @ShortcutConstants.ShortcutMenuMode int shortcutMenuMode) { 82 // Resetting the enable state of the item to avoid the previous wrong state of RecyclerView. 83 holder.mCheckBoxView.setEnabled(true); 84 holder.mIconView.setEnabled(true); 85 holder.mLabelView.setEnabled(true); 86 holder.mStatusView.setEnabled(true); 87 88 final boolean isEditMenuMode = 89 shortcutMenuMode == ShortcutConstants.ShortcutMenuMode.EDIT; 90 holder.mCheckBoxView.setChecked(isEditMenuMode && isShortcutEnabled()); 91 holder.mCheckBoxView.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE); 92 holder.mIconView.setImageDrawable(getIcon()); 93 holder.mLabelView.setText(getLabel()); 94 holder.mStatusView.setVisibility(View.GONE); 95 } 96 97 @Override onSelected()98 public void onSelected() { 99 final AccessibilityManager am = 100 getContext().getSystemService(AccessibilityManager.class); 101 switch (getShortcutType()) { 102 case ACCESSIBILITY_BUTTON: 103 am.notifyAccessibilityButtonClicked(getContext().getDisplayId(), getId()); 104 return; 105 case ACCESSIBILITY_SHORTCUT_KEY: 106 am.performAccessibilityShortcut(getId()); 107 return; 108 default: 109 throw new IllegalStateException("Unexpected shortcut type"); 110 } 111 } 112 113 @Override onCheckedChanged(boolean isChecked)114 public void onCheckedChanged(boolean isChecked) { 115 setShortcutEnabled(isChecked); 116 if (isChecked) { 117 optInValueToSettings(getContext(), convertToUserType(getShortcutType()), getId()); 118 } else { 119 optOutValueFromSettings(getContext(), convertToUserType(getShortcutType()), getId()); 120 } 121 } 122 setStateDescription(CharSequence stateDescription)123 public void setStateDescription(CharSequence stateDescription) { 124 mStateDescription = stateDescription; 125 } 126 127 /** 128 * Gets the state description of this feature target. 129 * 130 * @return the state description 131 */ 132 @Nullable getStateDescription()133 public CharSequence getStateDescription() { 134 return mStateDescription; 135 } 136 setShortcutEnabled(boolean enabled)137 public void setShortcutEnabled(boolean enabled) { 138 mShortcutEnabled = enabled; 139 } 140 getContext()141 public Context getContext() { 142 return mContext; 143 } 144 getShortcutType()145 public @ShortcutType int getShortcutType() { 146 return mShortcutType; 147 } 148 getFragmentType()149 public @AccessibilityFragmentType int getFragmentType() { 150 return mFragmentType; 151 } 152 isShortcutEnabled()153 public boolean isShortcutEnabled() { 154 return mShortcutEnabled; 155 } 156 getId()157 public String getId() { 158 return mId; 159 } 160 getUid()161 public int getUid() { 162 return mUid; 163 } 164 getComponentName()165 public ComponentName getComponentName() { 166 return mComponentName; 167 } 168 getLabel()169 public CharSequence getLabel() { 170 return mLabel; 171 } 172 getIcon()173 public Drawable getIcon() { 174 return mIcon; 175 } 176 getKey()177 public String getKey() { 178 return mKey; 179 } 180 } 181