Loading src/com/android/settings/accessibility/AccessibilityServiceWarning.javadeleted 100644 → 0 +0 −155 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.accessibility; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.text.BidiFormatter; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import com.android.settings.R; import java.util.Locale; /** * Utility class for creating the dialog that asks users for explicit permission for an * accessibility service to access user data before the service is enabled */ public class AccessibilityServiceWarning { private static final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> { // Filter obscured touches by consuming them. if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) { if (event.getAction() == MotionEvent.ACTION_UP) { Toast.makeText(v.getContext(), R.string.touch_filtered_warning, Toast.LENGTH_SHORT).show(); } return true; } return false; }; /** * The interface to execute the uninstallation action. */ interface UninstallActionPerformer { void uninstallPackage(); } /** * Returns a {@link Dialog} to be shown to confirm that they want to enable a service. * @deprecated Use {@link com.android.internal.accessibility.dialog.AccessibilityServiceWarning} */ @Deprecated public static Dialog createCapabilitiesDialog(@NonNull Context context, @NonNull AccessibilityServiceInfo info, @NonNull View.OnClickListener listener, @NonNull UninstallActionPerformer performer) { final AlertDialog ad = new AlertDialog.Builder(context) .setView(createEnableDialogContentView(context, info, listener, performer)) .create(); Window window = ad.getWindow(); WindowManager.LayoutParams params = window.getAttributes(); params.privateFlags |= SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(params); ad.create(); ad.setCanceledOnTouchOutside(true); return ad; } private static View createEnableDialogContentView(Context context, @NonNull AccessibilityServiceInfo info, View.OnClickListener listener, UninstallActionPerformer performer) { LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE); View content = inflater.inflate(R.layout.enable_accessibility_service_dialog_content, null); final Drawable icon; if (info.getResolveInfo().getIconResource() == 0) { icon = ContextCompat.getDrawable(context, R.drawable.ic_accessibility_generic); } else { icon = info.getResolveInfo().loadIcon(context.getPackageManager()); } ImageView permissionDialogIcon = content.findViewById( R.id.permissionDialog_icon); permissionDialogIcon.setImageDrawable(icon); TextView permissionDialogTitle = content.findViewById(R.id.permissionDialog_title); permissionDialogTitle.setText(context.getString(R.string.enable_service_title, getServiceName(context, info))); Button permissionAllowButton = content.findViewById( R.id.permission_enable_allow_button); Button permissionDenyButton = content.findViewById( R.id.permission_enable_deny_button); permissionAllowButton.setOnClickListener(listener); permissionAllowButton.setOnTouchListener(filterTouchListener); permissionDenyButton.setOnClickListener(listener); final Button uninstallButton = content.findViewById( R.id.permission_enable_uninstall_button); // Shows an uninstall button to help users quickly remove the non-system App due to the // required permissions. if (!AccessibilityUtil.isSystemApp(info)) { uninstallButton.setVisibility(View.VISIBLE); uninstallButton.setOnClickListener(v -> performer.uninstallPackage()); } return content; } /** Returns a {@link Dialog} to be shown to confirm that they want to disable a service. */ public static Dialog createDisableDialog(Context context, AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) { CharSequence serviceName = getServiceName(context, info); return new AlertDialog.Builder(context) .setTitle(context.getString(R.string.disable_service_title, serviceName)) .setCancelable(true) .setPositiveButton(R.string.accessibility_dialog_button_stop, listener) .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener) .create(); } // Get the service name and bidi wrap it to protect from bidi side effects. private static CharSequence getServiceName(Context context, AccessibilityServiceInfo info) { final Locale locale = context.getResources().getConfiguration().getLocales().get(0); final CharSequence label = info.getResolveInfo().loadLabel(context.getPackageManager()); return BidiFormatter.getInstance(locale).unicodeWrap(label); } } src/com/android/settings/accessibility/InvisibleToggleAccessibilityServicePreferenceFragment.java +1 −22 Original line number Diff line number Diff line Loading @@ -18,9 +18,7 @@ package com.android.settings.accessibility; import android.accessibilityservice.AccessibilityServiceInfo; import android.content.DialogInterface; import android.view.View; import com.android.settings.R; import com.android.settingslib.accessibility.AccessibilityUtils; /** Loading Loading @@ -52,26 +50,9 @@ public class InvisibleToggleAccessibilityServicePreferenceFragment extends super.onToggleClicked(preference); boolean enabled = getArguments().getBoolean(AccessibilitySettings.EXTRA_CHECKED) && preference.isChecked(); AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, enabled); } /** * {@inheritDoc} * * Enables accessibility service when user clicks permission allow button. */ @Override void onDialogButtonFromShortcutToggleClicked(View view) { super.onDialogButtonFromShortcutToggleClicked(view); if (!android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { if (view.getId() == R.id.permission_enable_allow_button) { AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, true); } } } /** * {@inheritDoc} * Loading @@ -80,10 +61,8 @@ public class InvisibleToggleAccessibilityServicePreferenceFragment extends @Override void onAllowButtonFromShortcutToggleClicked() { super.onAllowButtonFromShortcutToggleClicked(); if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, true); } } /** * {@inheritDoc} Loading src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +48 −76 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logA import static com.android.settings.accessibility.PreferredShortcuts.retrieveUserShortcutType; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.AlertDialog; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; Loading @@ -35,6 +36,7 @@ import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.text.BidiFormatter; import android.text.TextUtils; import android.util.Log; import android.view.Menu; Loading @@ -52,6 +54,7 @@ import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragm import com.android.settingslib.accessibility.AccessibilityUtils; import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; /** Fragment for providing toggle bar and basic accessibility service setup. */ Loading Loading @@ -158,69 +161,63 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromEnableToggleClicked(), v -> onDenyButtonFromEnableToggleClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromEnableToggleClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE: if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromShortcutToggleClicked(), v -> onDenyButtonFromShortcutToggleClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutToggleClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT: if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromShortcutClicked(), v -> onDenyButtonFromShortcutClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.DISABLE_WARNING_FROM_TOGGLE: if (info == null) { return null; } mWarningDialog = AccessibilityServiceWarning .createDisableDialog(getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked); mWarningDialog = createDisableDialog( getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked); return mWarningDialog; default: return super.onCreateDialog(dialogId); } } /** Returns a {@link Dialog} to be shown to confirm that they want to disable a service. */ private static Dialog createDisableDialog(Context context, AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) { final Locale locale = context.getResources().getConfiguration().getLocales().get(0); final CharSequence label = info.getResolveInfo().loadLabel(context.getPackageManager()); CharSequence serviceName = BidiFormatter.getInstance(locale).unicodeWrap(label); return new AlertDialog.Builder(context) .setTitle(context.getString(R.string.disable_service_title, serviceName)) .setCancelable(true) .setPositiveButton(R.string.accessibility_dialog_button_stop, listener) .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener) .create(); } @Override public int getDialogMetricsCategory(int dialogId) { switch (dialogId) { Loading Loading @@ -333,13 +330,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends final int shortcutTypes = retrieveUserShortcutType(getPrefContext(), mComponentName.flattenToString(), getDefaultShortcutTypes()); if (preference.isChecked()) { final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !mToggleServiceSwitchPreference.isChecked(); } if (isWarningRequired) { preference.setChecked(false); showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE); Loading @@ -355,15 +348,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends @Override public void onSettingsClicked(ShortcutPreference preference) { final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !(mShortcutPreference.isChecked() || mToggleServiceSwitchPreference.isChecked()); } if (isWarningRequired) { showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT); } else { Loading Loading @@ -537,17 +524,6 @@ public class ToggleAccessibilityServicePreferenceFragment extends mWarningDialog.dismiss(); } void onDialogButtonFromShortcutClicked(View view) { final int viewId = view.getId(); if (viewId == R.id.permission_enable_allow_button) { onAllowButtonFromShortcutClicked(); } else if (viewId == R.id.permission_enable_deny_button) { onDenyButtonFromShortcutClicked(); } else { throw new IllegalArgumentException("Unexpected view id"); } } private void onAllowButtonFromShortcutClicked() { mIsDialogShown.set(false); if (Flags.editShortcutsInFullScreen()) { Loading Loading @@ -576,13 +552,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends mToggleServiceSwitchPreference.setChecked(false); getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED, /* disableService */ false); final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !mShortcutPreference.isChecked(); } if (isWarningRequired) { showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_TOGGLE); } else { Loading tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java +5 −14 Original line number Diff line number Diff line Loading @@ -237,7 +237,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mToggleServiceSwitchPreference = Loading @@ -250,7 +249,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningNotRequired_dontShowWarning() throws Throwable { final AccessibilityServiceInfo info = setupServiceWarningRequired(false); mFragment.mToggleServiceSwitchPreference = Loading @@ -264,7 +262,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -278,7 +275,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningNotRequired_dontShowWarning() throws Throwable { setupServiceWarningRequired(false); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -292,7 +288,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void clickShortcutSettingsPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -304,7 +299,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags( com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_showDialog() Loading @@ -319,8 +313,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN}) @EnableFlags(com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_launchActivity() throws Throwable { setupServiceWarningRequired(false); Loading Loading @@ -365,7 +358,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_enableQsShortcut() throws Throwable { PreferredShortcuts.clearPreferredShortcuts(mContext); Loading @@ -383,7 +376,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_enableSoftwareShortcut() throws Throwable { PreferredShortcuts.clearPreferredShortcuts(mContext); Loading @@ -401,7 +394,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_flagOff_enableSoftwareShortcut() throws Throwable { Loading @@ -420,7 +412,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_flagOff_enableSoftwareShortcut() throws Throwable { Loading @@ -439,7 +430,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_userPreferVolumeKeysShortcut_noQsTile_enableVolumeKeysShortcut() throws Throwable { setupServiceWarningRequired(false); Loading @@ -462,7 +453,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_userPreferVolumeKeysShortcut_hasQsTile_enableVolumeKeysShortcut() throws Throwable { setupServiceWarningRequired(false); Loading Loading
src/com/android/settings/accessibility/AccessibilityServiceWarning.javadeleted 100644 → 0 +0 −155 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.accessibility; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.text.BidiFormatter; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import com.android.settings.R; import java.util.Locale; /** * Utility class for creating the dialog that asks users for explicit permission for an * accessibility service to access user data before the service is enabled */ public class AccessibilityServiceWarning { private static final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> { // Filter obscured touches by consuming them. if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) { if (event.getAction() == MotionEvent.ACTION_UP) { Toast.makeText(v.getContext(), R.string.touch_filtered_warning, Toast.LENGTH_SHORT).show(); } return true; } return false; }; /** * The interface to execute the uninstallation action. */ interface UninstallActionPerformer { void uninstallPackage(); } /** * Returns a {@link Dialog} to be shown to confirm that they want to enable a service. * @deprecated Use {@link com.android.internal.accessibility.dialog.AccessibilityServiceWarning} */ @Deprecated public static Dialog createCapabilitiesDialog(@NonNull Context context, @NonNull AccessibilityServiceInfo info, @NonNull View.OnClickListener listener, @NonNull UninstallActionPerformer performer) { final AlertDialog ad = new AlertDialog.Builder(context) .setView(createEnableDialogContentView(context, info, listener, performer)) .create(); Window window = ad.getWindow(); WindowManager.LayoutParams params = window.getAttributes(); params.privateFlags |= SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(params); ad.create(); ad.setCanceledOnTouchOutside(true); return ad; } private static View createEnableDialogContentView(Context context, @NonNull AccessibilityServiceInfo info, View.OnClickListener listener, UninstallActionPerformer performer) { LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE); View content = inflater.inflate(R.layout.enable_accessibility_service_dialog_content, null); final Drawable icon; if (info.getResolveInfo().getIconResource() == 0) { icon = ContextCompat.getDrawable(context, R.drawable.ic_accessibility_generic); } else { icon = info.getResolveInfo().loadIcon(context.getPackageManager()); } ImageView permissionDialogIcon = content.findViewById( R.id.permissionDialog_icon); permissionDialogIcon.setImageDrawable(icon); TextView permissionDialogTitle = content.findViewById(R.id.permissionDialog_title); permissionDialogTitle.setText(context.getString(R.string.enable_service_title, getServiceName(context, info))); Button permissionAllowButton = content.findViewById( R.id.permission_enable_allow_button); Button permissionDenyButton = content.findViewById( R.id.permission_enable_deny_button); permissionAllowButton.setOnClickListener(listener); permissionAllowButton.setOnTouchListener(filterTouchListener); permissionDenyButton.setOnClickListener(listener); final Button uninstallButton = content.findViewById( R.id.permission_enable_uninstall_button); // Shows an uninstall button to help users quickly remove the non-system App due to the // required permissions. if (!AccessibilityUtil.isSystemApp(info)) { uninstallButton.setVisibility(View.VISIBLE); uninstallButton.setOnClickListener(v -> performer.uninstallPackage()); } return content; } /** Returns a {@link Dialog} to be shown to confirm that they want to disable a service. */ public static Dialog createDisableDialog(Context context, AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) { CharSequence serviceName = getServiceName(context, info); return new AlertDialog.Builder(context) .setTitle(context.getString(R.string.disable_service_title, serviceName)) .setCancelable(true) .setPositiveButton(R.string.accessibility_dialog_button_stop, listener) .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener) .create(); } // Get the service name and bidi wrap it to protect from bidi side effects. private static CharSequence getServiceName(Context context, AccessibilityServiceInfo info) { final Locale locale = context.getResources().getConfiguration().getLocales().get(0); final CharSequence label = info.getResolveInfo().loadLabel(context.getPackageManager()); return BidiFormatter.getInstance(locale).unicodeWrap(label); } }
src/com/android/settings/accessibility/InvisibleToggleAccessibilityServicePreferenceFragment.java +1 −22 Original line number Diff line number Diff line Loading @@ -18,9 +18,7 @@ package com.android.settings.accessibility; import android.accessibilityservice.AccessibilityServiceInfo; import android.content.DialogInterface; import android.view.View; import com.android.settings.R; import com.android.settingslib.accessibility.AccessibilityUtils; /** Loading Loading @@ -52,26 +50,9 @@ public class InvisibleToggleAccessibilityServicePreferenceFragment extends super.onToggleClicked(preference); boolean enabled = getArguments().getBoolean(AccessibilitySettings.EXTRA_CHECKED) && preference.isChecked(); AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, enabled); } /** * {@inheritDoc} * * Enables accessibility service when user clicks permission allow button. */ @Override void onDialogButtonFromShortcutToggleClicked(View view) { super.onDialogButtonFromShortcutToggleClicked(view); if (!android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { if (view.getId() == R.id.permission_enable_allow_button) { AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, true); } } } /** * {@inheritDoc} * Loading @@ -80,10 +61,8 @@ public class InvisibleToggleAccessibilityServicePreferenceFragment extends @Override void onAllowButtonFromShortcutToggleClicked() { super.onAllowButtonFromShortcutToggleClicked(); if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { AccessibilityUtils.setAccessibilityServiceState(getContext(), mComponentName, true); } } /** * {@inheritDoc} Loading
src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +48 −76 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logA import static com.android.settings.accessibility.PreferredShortcuts.retrieveUserShortcutType; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.AlertDialog; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; Loading @@ -35,6 +36,7 @@ import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.text.BidiFormatter; import android.text.TextUtils; import android.util.Log; import android.view.Menu; Loading @@ -52,6 +54,7 @@ import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragm import com.android.settingslib.accessibility.AccessibilityUtils; import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; /** Fragment for providing toggle bar and basic accessibility service setup. */ Loading Loading @@ -158,69 +161,63 @@ public class ToggleAccessibilityServicePreferenceFragment extends if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromEnableToggleClicked(), v -> onDenyButtonFromEnableToggleClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromEnableToggleClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE: if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromShortcutToggleClicked(), v -> onDenyButtonFromShortcutToggleClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutToggleClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT: if (info == null) { return null; } if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { mWarningDialog = com.android.internal.accessibility.dialog.AccessibilityServiceWarning .createAccessibilityServiceWarningDialog(getPrefContext(), info, v -> onAllowButtonFromShortcutClicked(), v -> onDenyButtonFromShortcutClicked(), v -> onDialogButtonFromUninstallClicked()); } else { mWarningDialog = AccessibilityServiceWarning .createCapabilitiesDialog(getPrefContext(), info, this::onDialogButtonFromShortcutClicked, this::onDialogButtonFromUninstallClicked); } return mWarningDialog; case DialogEnums.DISABLE_WARNING_FROM_TOGGLE: if (info == null) { return null; } mWarningDialog = AccessibilityServiceWarning .createDisableDialog(getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked); mWarningDialog = createDisableDialog( getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked); return mWarningDialog; default: return super.onCreateDialog(dialogId); } } /** Returns a {@link Dialog} to be shown to confirm that they want to disable a service. */ private static Dialog createDisableDialog(Context context, AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) { final Locale locale = context.getResources().getConfiguration().getLocales().get(0); final CharSequence label = info.getResolveInfo().loadLabel(context.getPackageManager()); CharSequence serviceName = BidiFormatter.getInstance(locale).unicodeWrap(label); return new AlertDialog.Builder(context) .setTitle(context.getString(R.string.disable_service_title, serviceName)) .setCancelable(true) .setPositiveButton(R.string.accessibility_dialog_button_stop, listener) .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener) .create(); } @Override public int getDialogMetricsCategory(int dialogId) { switch (dialogId) { Loading Loading @@ -333,13 +330,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends final int shortcutTypes = retrieveUserShortcutType(getPrefContext(), mComponentName.flattenToString(), getDefaultShortcutTypes()); if (preference.isChecked()) { final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !mToggleServiceSwitchPreference.isChecked(); } if (isWarningRequired) { preference.setChecked(false); showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE); Loading @@ -355,15 +348,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends @Override public void onSettingsClicked(ShortcutPreference preference) { final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !(mShortcutPreference.isChecked() || mToggleServiceSwitchPreference.isChecked()); } if (isWarningRequired) { showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT); } else { Loading Loading @@ -537,17 +524,6 @@ public class ToggleAccessibilityServicePreferenceFragment extends mWarningDialog.dismiss(); } void onDialogButtonFromShortcutClicked(View view) { final int viewId = view.getId(); if (viewId == R.id.permission_enable_allow_button) { onAllowButtonFromShortcutClicked(); } else if (viewId == R.id.permission_enable_deny_button) { onDenyButtonFromShortcutClicked(); } else { throw new IllegalArgumentException("Unexpected view id"); } } private void onAllowButtonFromShortcutClicked() { mIsDialogShown.set(false); if (Flags.editShortcutsInFullScreen()) { Loading Loading @@ -576,13 +552,9 @@ public class ToggleAccessibilityServicePreferenceFragment extends mToggleServiceSwitchPreference.setChecked(false); getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED, /* disableService */ false); final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) final boolean isWarningRequired = getPrefContext().getSystemService(AccessibilityManager.class) .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo()); } else { isWarningRequired = !mShortcutPreference.isChecked(); } if (isWarningRequired) { showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_TOGGLE); } else { Loading
tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java +5 −14 Original line number Diff line number Diff line Loading @@ -237,7 +237,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mToggleServiceSwitchPreference = Loading @@ -250,7 +249,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningNotRequired_dontShowWarning() throws Throwable { final AccessibilityServiceInfo info = setupServiceWarningRequired(false); mFragment.mToggleServiceSwitchPreference = Loading @@ -264,7 +262,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -278,7 +275,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningNotRequired_dontShowWarning() throws Throwable { setupServiceWarningRequired(false); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -292,7 +288,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void clickShortcutSettingsPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); Loading @@ -304,7 +299,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags( com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_showDialog() Loading @@ -319,8 +313,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN}) @EnableFlags(com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_launchActivity() throws Throwable { setupServiceWarningRequired(false); Loading Loading @@ -365,7 +358,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_enableQsShortcut() throws Throwable { PreferredShortcuts.clearPreferredShortcuts(mContext); Loading @@ -383,7 +376,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_enableSoftwareShortcut() throws Throwable { PreferredShortcuts.clearPreferredShortcuts(mContext); Loading @@ -401,7 +394,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_flagOff_enableSoftwareShortcut() throws Throwable { Loading @@ -420,7 +412,6 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_flagOff_enableSoftwareShortcut() throws Throwable { Loading @@ -439,7 +430,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_userPreferVolumeKeysShortcut_noQsTile_enableVolumeKeysShortcut() throws Throwable { setupServiceWarningRequired(false); Loading @@ -462,7 +453,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) public void toggleShortcutPreference_userPreferVolumeKeysShortcut_hasQsTile_enableVolumeKeysShortcut() throws Throwable { setupServiceWarningRequired(false); Loading