summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java47
-rw-r--r--core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java49
-rw-r--r--core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java141
-rw-r--r--core/java/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTarget.java71
-rw-r--r--core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java36
-rw-r--r--core/java/com/android/internal/accessibility/dialog/OnTargetCheckedChangeListener.java30
-rw-r--r--core/java/com/android/internal/accessibility/dialog/OnTargetSelectedListener.java27
-rw-r--r--core/java/com/android/internal/accessibility/dialog/TargetAdapter.java35
-rw-r--r--core/java/com/android/internal/accessibility/dialog/TargetOperations.java33
-rw-r--r--core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java55
-rw-r--r--core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java57
-rw-r--r--core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java78
-rw-r--r--core/java/com/android/internal/accessibility/util/AccessibilityUtils.java26
-rw-r--r--core/java/com/android/internal/accessibility/util/ShortcutUtils.java17
14 files changed, 702 insertions, 0 deletions
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java
new file mode 100644
index 000000000000..4c7d93b7446a
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.android.internal.accessibility.util.ShortcutUtils.convertToKey;
+import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType;
+import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained;
+
+import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+
+/**
+ * Base class for creating accessibility activity target.
+ */
+class AccessibilityActivityTarget extends AccessibilityTarget {
+
+ AccessibilityActivityTarget(Context context, @ShortcutType int shortcutType,
+ @NonNull AccessibilityShortcutInfo shortcutInfo) {
+ super(context,
+ shortcutType,
+ AccessibilityFragmentType.LAUNCH_ACTIVITY,
+ isShortcutContained(context, shortcutType,
+ shortcutInfo.getComponentName().flattenToString()),
+ shortcutInfo.getComponentName().flattenToString(),
+ shortcutInfo.getActivityInfo().loadLabel(context.getPackageManager()),
+ shortcutInfo.getActivityInfo().loadIcon(context.getPackageManager()),
+ convertToKey(convertToUserType(shortcutType)));
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java
new file mode 100644
index 000000000000..e64f78a3f207
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.android.internal.accessibility.util.ShortcutUtils.convertToKey;
+import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType;
+import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+
+/**
+ * Base class for creating accessibility service target with various fragment types related to
+ * legacy type, invisible type and intuitive type.
+ */
+class AccessibilityServiceTarget extends AccessibilityTarget {
+
+ AccessibilityServiceTarget(Context context, @ShortcutType int shortcutType,
+ @AccessibilityFragmentType int fragmentType,
+ @NonNull AccessibilityServiceInfo serviceInfo) {
+ super(context,
+ shortcutType,
+ fragmentType,
+ isShortcutContained(context, shortcutType,
+ serviceInfo.getComponentName().flattenToString()),
+ serviceInfo.getComponentName().flattenToString(),
+ serviceInfo.getResolveInfo().loadLabel(context.getPackageManager()),
+ serviceInfo.getResolveInfo().loadIcon(context.getPackageManager()),
+ convertToKey(convertToUserType(shortcutType)));
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
new file mode 100644
index 000000000000..72ebc58380b8
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
@@ -0,0 +1,141 @@
+/*
+ * 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.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
+
+import static com.android.internal.accessibility.util.ShortcutUtils.convertToUserType;
+import static com.android.internal.accessibility.util.ShortcutUtils.optInValueToSettings;
+import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants;
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
+
+/**
+ * Abstract base class for creating various target related to accessibility service,
+ * accessibility activity, and white listing feature.
+ */
+abstract class AccessibilityTarget implements TargetOperations, OnTargetSelectedListener,
+ OnTargetCheckedChangeListener {
+ private Context mContext;
+ @ShortcutType
+ private int mShortcutType;
+ @AccessibilityFragmentType
+ private int mFragmentType;
+ private boolean mShortcutEnabled;
+ private String mId;
+ private CharSequence mLabel;
+ private Drawable mIcon;
+ private String mKey;
+
+ AccessibilityTarget(Context context, @ShortcutType int shortcutType,
+ @AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id,
+ CharSequence label, Drawable icon, String key) {
+ mContext = context;
+ mShortcutType = shortcutType;
+ mFragmentType = fragmentType;
+ mShortcutEnabled = isShortcutSwitched;
+ mId = id;
+ mLabel = label;
+ mIcon = icon;
+ mKey = key;
+ }
+
+ @Override
+ public void updateActionItem(@NonNull ViewHolder holder,
+ @ShortcutConstants.ShortcutMenuMode int shortcutMenuMode) {
+ final boolean isEditMenuMode =
+ shortcutMenuMode == ShortcutConstants.ShortcutMenuMode.EDIT;
+
+ holder.mCheckBoxView.setChecked(isEditMenuMode && isShortcutEnabled());
+ holder.mCheckBoxView.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
+ holder.mIconView.setImageDrawable(getIcon());
+ holder.mLabelView.setText(getLabel());
+ holder.mSwitchItem.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onSelected() {
+ final AccessibilityManager am =
+ getContext().getSystemService(AccessibilityManager.class);
+ switch (getShortcutType()) {
+ case ACCESSIBILITY_BUTTON:
+ am.notifyAccessibilityButtonClicked(getContext().getDisplayId(), getId());
+ return;
+ case ACCESSIBILITY_SHORTCUT_KEY:
+ am.performAccessibilityShortcut(getId());
+ return;
+ default:
+ throw new IllegalStateException("Unexpected shortcut type");
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(boolean isChecked) {
+ setShortcutEnabled(isChecked);
+ if (isChecked) {
+ optInValueToSettings(getContext(), convertToUserType(getShortcutType()), getId());
+ } else {
+ optOutValueFromSettings(getContext(), convertToUserType(getShortcutType()), getId());
+ }
+ }
+
+ public void setShortcutEnabled(boolean enabled) {
+ mShortcutEnabled = enabled;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public @ShortcutType int getShortcutType() {
+ return mShortcutType;
+ }
+
+ public @AccessibilityFragmentType int getFragmentType() {
+ return mFragmentType;
+ }
+
+ public boolean isShortcutEnabled() {
+ return mShortcutEnabled;
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTarget.java
new file mode 100644
index 000000000000..9d5c374e98f5
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAccessibilityServiceTarget.java
@@ -0,0 +1,71 @@
+/*
+ * 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.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
+
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
+import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState;
+import static com.android.internal.accessibility.util.ShortcutUtils.isComponentIdExistingInSettings;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+
+/**
+ * Extension for {@link AccessibilityServiceTarget} with
+ * {@link AccessibilityFragmentType#INVISIBLE_TOGGLE} type.
+ */
+class InvisibleToggleAccessibilityServiceTarget extends AccessibilityServiceTarget {
+
+ InvisibleToggleAccessibilityServiceTarget(Context context, @ShortcutType int shortcutType,
+ @NonNull AccessibilityServiceInfo serviceInfo) {
+ super(context,
+ shortcutType,
+ AccessibilityFragmentType.INVISIBLE_TOGGLE,
+ serviceInfo);
+ }
+
+ @Override
+ public void onCheckedChanged(boolean isChecked) {
+ final ComponentName componentName = ComponentName.unflattenFromString(getId());
+
+ if (!isComponentIdExistingInOtherShortcut()) {
+ setAccessibilityServiceState(getContext(), componentName, isChecked);
+ }
+
+ super.onCheckedChanged(isChecked);
+ }
+
+ private boolean isComponentIdExistingInOtherShortcut() {
+ switch (getShortcutType()) {
+ case ACCESSIBILITY_BUTTON:
+ return isComponentIdExistingInSettings(getContext(), UserShortcutType.HARDWARE,
+ getId());
+ case ACCESSIBILITY_SHORTCUT_KEY:
+ return isComponentIdExistingInSettings(getContext(), UserShortcutType.SOFTWARE,
+ getId());
+ default:
+ throw new IllegalStateException("Unexpected shortcut type");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java
new file mode 100644
index 000000000000..acd101bf28ba
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleWhiteListingFeatureTarget.java
@@ -0,0 +1,36 @@
+/*
+ * 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.graphics.drawable.Drawable;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+
+/**
+ * Extension for {@link AccessibilityTarget} with {@link AccessibilityFragmentType#INVISIBLE_TOGGLE}
+ * type.
+ */
+class InvisibleToggleWhiteListingFeatureTarget extends AccessibilityTarget {
+
+ InvisibleToggleWhiteListingFeatureTarget(Context context, @ShortcutType int shortcutType,
+ boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
+ super(context, shortcutType, AccessibilityFragmentType.INVISIBLE_TOGGLE,
+ isShortcutSwitched, id, label, icon, key);
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/OnTargetCheckedChangeListener.java b/core/java/com/android/internal/accessibility/dialog/OnTargetCheckedChangeListener.java
new file mode 100644
index 000000000000..dab45e45907d
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/OnTargetCheckedChangeListener.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Interface definition for a callback to be invoked when the checked state
+ * of a accessibility target changed.
+ */
+interface OnTargetCheckedChangeListener {
+ /**
+ * Called when the checked state of a accessibility target has changed.
+ *
+ * @param isChecked The new checked state of accessibility target.
+ */
+ void onCheckedChanged(boolean isChecked);
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/OnTargetSelectedListener.java b/core/java/com/android/internal/accessibility/dialog/OnTargetSelectedListener.java
new file mode 100644
index 000000000000..b3e976f296a9
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/OnTargetSelectedListener.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * Interface definition for a callback to be invoked when a accessibility target is selected.
+ */
+interface OnTargetSelectedListener {
+ /**
+ * Called when a accessibility target has been selected.
+ */
+ void onSelected();
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/TargetAdapter.java b/core/java/com/android/internal/accessibility/dialog/TargetAdapter.java
new file mode 100644
index 000000000000..1efa17e520ae
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/TargetAdapter.java
@@ -0,0 +1,35 @@
+/*
+ * 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.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+/**
+ * Abstract base class for creating target adapter for chooser activity.
+ */
+abstract class TargetAdapter extends BaseAdapter {
+ static class ViewHolder{
+ CheckBox mCheckBoxView;
+ ImageView mIconView;
+ TextView mLabelView;
+ Switch mSwitchItem;
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/TargetOperations.java b/core/java/com/android/internal/accessibility/dialog/TargetOperations.java
new file mode 100644
index 000000000000..77cc5b454ed7
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/TargetOperations.java
@@ -0,0 +1,33 @@
+/*
+ * 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.annotation.NonNull;
+
+import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
+import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
+
+/**
+ * Interface definition for operations with a accessibility target that was invoked.
+ */
+interface TargetOperations {
+ /**
+ * Called when a accessibility target has been invoked and notified to update latest status.
+ */
+ void updateActionItem(@NonNull ViewHolder holder,
+ @ShortcutMenuMode int shortcutMenuMode);
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
new file mode 100644
index 000000000000..3a42f7e0edb8
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.internal.accessibility.util.AccessibilityUtils.isAccessibilityServiceEnabled;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
+import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
+
+/**
+ * Extension for {@link AccessibilityServiceTarget} with {@link AccessibilityFragmentType#TOGGLE}
+ * type.
+ */
+class ToggleAccessibilityServiceTarget extends AccessibilityServiceTarget {
+
+ ToggleAccessibilityServiceTarget(Context context, @ShortcutType int shortcutType,
+ @NonNull AccessibilityServiceInfo serviceInfo) {
+ super(context,
+ shortcutType,
+ AccessibilityFragmentType.TOGGLE,
+ serviceInfo);
+ }
+
+ @Override
+ public void updateActionItem(@NonNull ViewHolder holder,
+ @ShortcutMenuMode int shortcutMenuMode) {
+ super.updateActionItem(holder, shortcutMenuMode);
+
+ final boolean isEditMenuMode =
+ shortcutMenuMode == ShortcutMenuMode.EDIT;
+ holder.mSwitchItem.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
+ holder.mSwitchItem.setChecked(isAccessibilityServiceEnabled(getContext(), getId()));
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java
new file mode 100644
index 000000000000..fcbf5eccbd9e
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleWhiteListingFeatureTarget.java
@@ -0,0 +1,57 @@
+/*
+ * 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.annotation.NonNull;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.provider.Settings;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
+import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
+
+/**
+ * Extension for {@link AccessibilityTarget} with {@link AccessibilityFragmentType#TOGGLE}
+ * type.
+ */
+class ToggleWhiteListingFeatureTarget extends AccessibilityTarget {
+
+ ToggleWhiteListingFeatureTarget(Context context, @ShortcutType int shortcutType,
+ boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
+ super(context, shortcutType, AccessibilityFragmentType.TOGGLE,
+ isShortcutSwitched, id, label, icon, key);
+ }
+
+ @Override
+ public void updateActionItem(@NonNull ViewHolder holder,
+ @ShortcutMenuMode int shortcutMenuMode) {
+ super.updateActionItem(holder, shortcutMenuMode);
+
+ final boolean isEditMenuMode =
+ shortcutMenuMode == ShortcutMenuMode.EDIT;
+ holder.mSwitchItem.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
+ holder.mSwitchItem.setChecked(isFeatureEnabled());
+ }
+
+ private boolean isFeatureEnabled() {
+ return Settings.Secure.getInt(getContext().getContentResolver(),
+ getKey(), /* settingsValueOff */ 0) == /* settingsValueOn */ 1;
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java
new file mode 100644
index 000000000000..04f5061fbd8e
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/dialog/VolumeShortcutToggleAccessibilityServiceTarget.java
@@ -0,0 +1,78 @@
+/*
+ * 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.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
+
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
+import static com.android.internal.accessibility.util.AccessibilityUtils.setAccessibilityServiceState;
+import static com.android.internal.accessibility.util.ShortcutUtils.optOutValueFromSettings;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager.ShortcutType;
+import android.widget.Toast;
+
+import com.android.internal.R;
+import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+
+/**
+ * Extension for {@link AccessibilityServiceTarget} with
+ * {@link AccessibilityFragmentType#VOLUME_SHORTCUT_TOGGLE} type.
+ */
+class VolumeShortcutToggleAccessibilityServiceTarget extends AccessibilityServiceTarget {
+
+ VolumeShortcutToggleAccessibilityServiceTarget(Context context, @ShortcutType int shortcutType,
+ @NonNull AccessibilityServiceInfo serviceInfo) {
+ super(context,
+ shortcutType,
+ AccessibilityFragmentType.VOLUME_SHORTCUT_TOGGLE,
+ serviceInfo);
+ }
+
+ @Override
+ public void onCheckedChanged(boolean isChecked) {
+ switch (getShortcutType()) {
+ case ACCESSIBILITY_BUTTON:
+ onCheckedFromAccessibilityButton(isChecked);
+ return;
+ case ACCESSIBILITY_SHORTCUT_KEY:
+ super.onCheckedChanged(isChecked);
+ return;
+ default:
+ throw new IllegalStateException("Unexpected shortcut type");
+ }
+ }
+
+ private void onCheckedFromAccessibilityButton(boolean isChecked) {
+ setShortcutEnabled(isChecked);
+ final ComponentName componentName = ComponentName.unflattenFromString(getId());
+ setAccessibilityServiceState(getContext(), componentName, isChecked);
+
+ if (!isChecked) {
+ optOutValueFromSettings(getContext(), UserShortcutType.HARDWARE, getId());
+
+ final String warningText =
+ getContext().getString(R.string.accessibility_uncheck_legacy_item_warning,
+ getLabel());
+ Toast.makeText(getContext(), warningText, Toast.LENGTH_SHORT).show();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index a92a50d4d832..e50b010d691a 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -15,6 +15,7 @@
*/
package com.android.internal.accessibility.util;
+
import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import static com.android.internal.accessibility.common.ShortcutConstants.SERVICES_SEPARATOR;
@@ -27,9 +28,11 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.view.accessibility.AccessibilityManager;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -129,4 +132,27 @@ public final class AccessibilityUtils {
? AccessibilityFragmentType.INVISIBLE_TOGGLE
: AccessibilityFragmentType.TOGGLE;
}
+
+ /**
+ * Returns if a {@code componentId} service is enabled.
+ *
+ * @param context The current context.
+ * @param componentId The component id that need to be checked.
+ * @return {@code true} if a {@code componentId} service is enabled.
+ */
+ public static boolean isAccessibilityServiceEnabled(Context context,
+ @NonNull String componentId) {
+ final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+ final List<AccessibilityServiceInfo> enabledServices =
+ am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+
+ for (AccessibilityServiceInfo info : enabledServices) {
+ final String id = info.getComponentName().flattenToString();
+ if (id.equals(componentId)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
index 7ec80ecdb2a9..fa90b49e85af 100644
--- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -25,8 +25,10 @@ import android.annotation.NonNull;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.ShortcutType;
+import java.util.List;
import java.util.StringJoiner;
/**
@@ -149,6 +151,21 @@ public final class ShortcutUtils {
}
/**
+ * Returns if a {@code shortcutType} shortcut contains {@code componentId}.
+ *
+ * @param context The current context.
+ * @param shortcutType The preferred shortcut type user selected.
+ * @param componentId The component id that need to be checked.
+ * @return {@code true} if a component id is contained.
+ */
+ public static boolean isShortcutContained(Context context, @ShortcutType int shortcutType,
+ @NonNull String componentId) {
+ final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+ final List<String> requiredTargets = am.getAccessibilityShortcutTargets(shortcutType);
+ return requiredTargets.contains(componentId);
+ }
+
+ /**
* Converts {@link UserShortcutType} to {@link Settings.Secure} key.
*
* @param type The shortcut type.