Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ce099c2 authored by Daniel Norman's avatar Daniel Norman
Browse files

Remove usages of bugfix flag cleanup_accessibility_warning_dialog.

Flag has been in Trunkfood for over a month.

Includes one mechanical refactor to move a method from a now-removed
file into a private method in the class that uses it: createDisableDialog

(This flag guarded a preliminary cleanup and minor bug fix for
b/303511250, but the actual feature for b/303511250 is tracked in a
different flag 'skip_accessibility_warning_dialog_for_trusted_services')

Bug: 303511250
Test: existing tests in Presubmit (no change to behavior)
Change-Id: Iccf439adb2806e988310f503fb3891a6bd022054
parent 59a329ca
Loading
Loading
Loading
Loading
+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);
    }
}
+1 −22
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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}
     *
@@ -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}
+48 −76
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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. */
@@ -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) {
@@ -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);
@@ -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 {
@@ -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()) {
@@ -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 {
+5 −14
Original line number Diff line number Diff line
@@ -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 =
@@ -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 =
@@ -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);
@@ -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);
@@ -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);
@@ -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()
@@ -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);
@@ -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);
@@ -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);
@@ -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 {
@@ -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 {
@@ -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);
@@ -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);