1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.accessibility;
18 
19 import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
20 import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logAccessibilityServiceEnabled;
21 
22 import android.accessibilityservice.AccessibilityServiceInfo;
23 import android.app.AlertDialog;
24 import android.app.Dialog;
25 import android.app.settings.SettingsEnums;
26 import android.content.BroadcastReceiver;
27 import android.content.ComponentName;
28 import android.content.ContentResolver;
29 import android.content.Context;
30 import android.content.DialogInterface;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.content.pm.ApplicationInfo;
34 import android.content.pm.ResolveInfo;
35 import android.net.Uri;
36 import android.os.Bundle;
37 import android.os.SystemClock;
38 import android.text.BidiFormatter;
39 import android.text.TextUtils;
40 import android.util.Log;
41 import android.view.Menu;
42 import android.view.MenuInflater;
43 import android.view.View;
44 import android.view.accessibility.AccessibilityManager;
45 import android.widget.CompoundButton;
46 
47 import androidx.annotation.Nullable;
48 
49 import com.android.internal.accessibility.common.ShortcutConstants;
50 import com.android.settings.R;
51 import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
52 import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
53 import com.android.settingslib.accessibility.AccessibilityUtils;
54 
55 import java.util.List;
56 import java.util.Locale;
57 import java.util.concurrent.atomic.AtomicBoolean;
58 
59 /** Fragment for providing toggle bar and basic accessibility service setup. */
60 public class ToggleAccessibilityServicePreferenceFragment extends
61         ToggleFeaturePreferenceFragment {
62 
63     private static final String TAG = "ToggleAccessibilityServicePreferenceFragment";
64     private static final String KEY_HAS_LOGGED = "has_logged";
65     private final AtomicBoolean mIsDialogShown = new AtomicBoolean(/* initialValue= */ false);
66 
67     private Dialog mWarningDialog;
68     private ComponentName mTileComponentName;
69     private BroadcastReceiver mPackageRemovedReceiver;
70     private boolean mDisabledStateLogged = false;
71     private long mStartTimeMillsForLogging = 0;
72 
73     @Override
getMetricsCategory()74     public int getMetricsCategory() {
75         return getArguments().getInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY);
76     }
77 
78     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)79     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
80         // Do not call super. We don't want to see the "Help & feedback" option on this page so as
81         // not to confuse users who think they might be able to send feedback about a specific
82         // accessibility service from this page.
83     }
84 
85     @Override
onCreate(Bundle savedInstanceState)86     public void onCreate(Bundle savedInstanceState) {
87         super.onCreate(savedInstanceState);
88         if (savedInstanceState != null) {
89             if (savedInstanceState.containsKey(KEY_HAS_LOGGED)) {
90                 mDisabledStateLogged = savedInstanceState.getBoolean(KEY_HAS_LOGGED);
91             }
92         }
93     }
94 
95     @Override
registerKeysToObserverCallback( AccessibilitySettingsContentObserver contentObserver)96     protected void registerKeysToObserverCallback(
97             AccessibilitySettingsContentObserver contentObserver) {
98         super.registerKeysToObserverCallback(contentObserver);
99         contentObserver.registerObserverCallback(key -> updateSwitchBarToggleSwitch());
100     }
101 
102     @Override
onStart()103     public void onStart() {
104         super.onStart();
105         final AccessibilityServiceInfo serviceInfo = getAccessibilityServiceInfo();
106         if (serviceInfo == null) {
107             getActivity().finishAndRemoveTask();
108         } else if (!AccessibilityUtil.isSystemApp(serviceInfo)) {
109             registerPackageRemoveReceiver();
110         }
111     }
112 
113     @Override
onResume()114     public void onResume() {
115         super.onResume();
116         updateSwitchBarToggleSwitch();
117     }
118 
119     @Override
onSaveInstanceState(Bundle outState)120     public void onSaveInstanceState(Bundle outState) {
121         if (mStartTimeMillsForLogging > 0) {
122             outState.putBoolean(KEY_HAS_LOGGED, mDisabledStateLogged);
123         }
124         super.onSaveInstanceState(outState);
125     }
126 
127     @Override
onPreferenceToggled(String preferenceKey, boolean enabled)128     public void onPreferenceToggled(String preferenceKey, boolean enabled) {
129         ComponentName toggledService = ComponentName.unflattenFromString(preferenceKey);
130         logAccessibilityServiceEnabled(toggledService, enabled);
131         if (!enabled) {
132             logDisabledState(toggledService.getPackageName());
133         }
134         AccessibilityUtils.setAccessibilityServiceState(getPrefContext(), toggledService, enabled);
135     }
136 
137     // IMPORTANT: Refresh the info since there are dynamically changing capabilities. For
138     // example, before JellyBean MR2 the user was granting the explore by touch one.
139     @Nullable
getAccessibilityServiceInfo()140     AccessibilityServiceInfo getAccessibilityServiceInfo() {
141         final List<AccessibilityServiceInfo> infos = AccessibilityManager.getInstance(
142                 getPrefContext()).getInstalledAccessibilityServiceList();
143 
144         for (int i = 0, count = infos.size(); i < count; i++) {
145             AccessibilityServiceInfo serviceInfo = infos.get(i);
146             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
147             if (mComponentName.getPackageName().equals(resolveInfo.serviceInfo.packageName)
148                     && mComponentName.getClassName().equals(resolveInfo.serviceInfo.name)) {
149                 return serviceInfo;
150             }
151         }
152         return null;
153     }
154 
155     @Override
onCreateDialog(int dialogId)156     public Dialog onCreateDialog(int dialogId) {
157         final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
158         switch (dialogId) {
159             case DialogEnums.ENABLE_WARNING_FROM_TOGGLE:
160                 if (info == null) {
161                     return null;
162                 }
163                 mWarningDialog =
164                         com.android.internal.accessibility.dialog.AccessibilityServiceWarning
165                                 .createAccessibilityServiceWarningDialog(getPrefContext(), info,
166                                         v -> onAllowButtonFromEnableToggleClicked(),
167                                         v -> onDenyButtonFromEnableToggleClicked(),
168                                         v -> onDialogButtonFromUninstallClicked());
169                 return mWarningDialog;
170             case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE:
171                 if (info == null) {
172                     return null;
173                 }
174                 mWarningDialog =
175                         com.android.internal.accessibility.dialog.AccessibilityServiceWarning
176                                 .createAccessibilityServiceWarningDialog(getPrefContext(), info,
177                                         v -> onAllowButtonFromShortcutToggleClicked(),
178                                         v -> onDenyButtonFromShortcutToggleClicked(),
179                                         v -> onDialogButtonFromUninstallClicked());
180                 return mWarningDialog;
181             case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT:
182                 if (info == null) {
183                     return null;
184                 }
185                 mWarningDialog =
186                         com.android.internal.accessibility.dialog.AccessibilityServiceWarning
187                                 .createAccessibilityServiceWarningDialog(getPrefContext(), info,
188                                         v -> onAllowButtonFromShortcutClicked(),
189                                         v -> onDenyButtonFromShortcutClicked(),
190                                         v -> onDialogButtonFromUninstallClicked());
191                 return mWarningDialog;
192             case DialogEnums.DISABLE_WARNING_FROM_TOGGLE:
193                 if (info == null) {
194                     return null;
195                 }
196                 mWarningDialog = createDisableDialog(
197                         getPrefContext(), info, this::onDialogButtonFromDisableToggleClicked);
198                 return mWarningDialog;
199             default:
200                 return super.onCreateDialog(dialogId);
201         }
202     }
203 
204     /** Returns a {@link Dialog} to be shown to confirm that they want to disable a service. */
createDisableDialog(Context context, AccessibilityServiceInfo info, DialogInterface.OnClickListener listener)205     private static Dialog createDisableDialog(Context context,
206             AccessibilityServiceInfo info, DialogInterface.OnClickListener listener) {
207         final Locale locale = context.getResources().getConfiguration().getLocales().get(0);
208         final CharSequence label =
209                 info.getResolveInfo().loadLabel(context.getPackageManager());
210         CharSequence serviceName = BidiFormatter.getInstance(locale).unicodeWrap(label);
211 
212         return new AlertDialog.Builder(context)
213                 .setTitle(context.getString(R.string.disable_service_title, serviceName))
214                 .setCancelable(true)
215                 .setPositiveButton(R.string.accessibility_dialog_button_stop, listener)
216                 .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener)
217                 .create();
218     }
219 
220     @Override
getDialogMetricsCategory(int dialogId)221     public int getDialogMetricsCategory(int dialogId) {
222         switch (dialogId) {
223             case DialogEnums.ENABLE_WARNING_FROM_TOGGLE:
224             case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT:
225             case DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE:
226                 return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
227             case DialogEnums.DISABLE_WARNING_FROM_TOGGLE:
228                 return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_DISABLE;
229             case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
230                 return SettingsEnums.DIALOG_ACCESSIBILITY_TUTORIAL;
231             default:
232                 return super.getDialogMetricsCategory(dialogId);
233         }
234     }
235 
236     @Override
getUserShortcutTypes()237     int getUserShortcutTypes() {
238         return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
239                 mComponentName);
240     }
241 
242     @Override
getTileComponentName()243     ComponentName getTileComponentName() {
244         return mTileComponentName;
245     }
246 
247     @Override
getTileTooltipContent(@uickSettingsTooltipType int type)248     CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
249         final ComponentName componentName = getTileComponentName();
250         if (componentName == null) {
251             return null;
252         }
253 
254         final CharSequence tileName = loadTileLabel(getPrefContext(), componentName);
255         if (tileName == null) {
256             return null;
257         }
258 
259         final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT
260                 ? R.string.accessibility_service_qs_tooltip_content
261                 : R.string.accessibility_service_auto_added_qs_tooltip_content;
262         return getString(titleResId, tileName);
263     }
264 
265     @Override
updateSwitchBarToggleSwitch()266     protected void updateSwitchBarToggleSwitch() {
267         final boolean checked = isAccessibilityServiceEnabled();
268         if (mToggleServiceSwitchPreference.isChecked() == checked) {
269             return;
270         }
271         mToggleServiceSwitchPreference.setChecked(checked);
272     }
273 
isAccessibilityServiceEnabled()274     private boolean isAccessibilityServiceEnabled() {
275         return AccessibilityUtils.getEnabledServicesFromSettings(getPrefContext())
276                 .contains(mComponentName);
277     }
278 
279     @Override
onActivityResult(int requestCode, int resultCode, Intent data)280     public void onActivityResult(int requestCode, int resultCode, Intent data) {
281     }
282 
registerPackageRemoveReceiver()283     private void registerPackageRemoveReceiver() {
284         if (mPackageRemovedReceiver != null || getContext() == null) {
285             return;
286         }
287         mPackageRemovedReceiver = new BroadcastReceiver() {
288             @Override
289             public void onReceive(Context context, Intent intent) {
290                 final String packageName = intent.getData().getSchemeSpecificPart();
291                 if (TextUtils.equals(mComponentName.getPackageName(), packageName)) {
292                     getActivity().finishAndRemoveTask();
293                 }
294             }
295         };
296         final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
297         filter.addDataScheme("package");
298         getContext().registerReceiver(mPackageRemovedReceiver, filter);
299     }
300 
unregisterPackageRemoveReceiver()301     private void unregisterPackageRemoveReceiver() {
302         if (mPackageRemovedReceiver == null || getContext() == null) {
303             return;
304         }
305         getContext().unregisterReceiver(mPackageRemovedReceiver);
306         mPackageRemovedReceiver = null;
307     }
308 
serviceSupportsAccessibilityButton()309     boolean serviceSupportsAccessibilityButton() {
310         final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
311         return info != null
312                 && (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
313     }
314 
handleConfirmServiceEnabled(boolean confirmed)315     private void handleConfirmServiceEnabled(boolean confirmed) {
316         getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED, confirmed);
317         onPreferenceToggled(mPreferenceKey, confirmed);
318     }
319 
320     @Override
onCheckedChanged(CompoundButton buttonView, boolean isChecked)321     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
322         if (isChecked != isAccessibilityServiceEnabled()) {
323             onPreferenceClick(isChecked);
324         }
325     }
326 
327     @Override
onToggleClicked(ShortcutPreference preference)328     public void onToggleClicked(ShortcutPreference preference) {
329         final int shortcutTypes = getUserPreferredShortcutTypes();
330         if (preference.isChecked()) {
331             final boolean isWarningRequired =
332                     getPrefContext().getSystemService(AccessibilityManager.class)
333                             .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo());
334             if (isWarningRequired) {
335                 preference.setChecked(false);
336                 showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT_TOGGLE);
337             } else {
338                 onAllowButtonFromShortcutToggleClicked();
339             }
340         } else {
341             AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
342                     mComponentName);
343         }
344         mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
345     }
346 
347     @Override
onSettingsClicked(ShortcutPreference preference)348     public void onSettingsClicked(ShortcutPreference preference) {
349         final boolean isWarningRequired =
350                 getPrefContext().getSystemService(AccessibilityManager.class)
351                         .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo());
352         if (isWarningRequired) {
353             showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_SHORTCUT);
354         } else {
355             onAllowButtonFromShortcutClicked();
356         }
357     }
358 
359     @Override
onProcessArguments(Bundle arguments)360     protected void onProcessArguments(Bundle arguments) {
361         super.onProcessArguments(arguments);
362         // Settings title and intent.
363         String settingsTitle = arguments.getString(AccessibilitySettings.EXTRA_SETTINGS_TITLE);
364         String settingsComponentName = arguments.getString(
365                 AccessibilitySettings.EXTRA_SETTINGS_COMPONENT_NAME);
366         if (!TextUtils.isEmpty(settingsTitle) && !TextUtils.isEmpty(settingsComponentName)) {
367             Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent(
368                     ComponentName.unflattenFromString(settingsComponentName.toString()));
369             if (!getPackageManager().queryIntentActivities(settingsIntent, 0).isEmpty()) {
370                 mSettingsTitle = settingsTitle;
371                 mSettingsIntent = settingsIntent;
372                 setHasOptionsMenu(true);
373             }
374         }
375 
376         mComponentName = arguments.getParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME);
377 
378         // Settings animated image.
379         final int animatedImageRes = arguments.getInt(
380                 AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
381         if (animatedImageRes > 0) {
382             mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
383                     .authority(mComponentName.getPackageName())
384                     .appendPath(String.valueOf(animatedImageRes))
385                     .build();
386         }
387 
388         // Get Accessibility service name.
389         mPackageName = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
390                 getPackageManager());
391 
392         if (arguments.containsKey(AccessibilitySettings.EXTRA_TILE_SERVICE_COMPONENT_NAME)) {
393             final String tileServiceComponentName = arguments.getString(
394                     AccessibilitySettings.EXTRA_TILE_SERVICE_COMPONENT_NAME);
395             mTileComponentName = ComponentName.unflattenFromString(tileServiceComponentName);
396         }
397 
398         mStartTimeMillsForLogging = arguments.getLong(AccessibilitySettings.EXTRA_TIME_FOR_LOGGING);
399     }
400 
onDialogButtonFromDisableToggleClicked(DialogInterface dialog, int which)401     private void onDialogButtonFromDisableToggleClicked(DialogInterface dialog, int which) {
402         switch (which) {
403             case DialogInterface.BUTTON_POSITIVE:
404                 handleConfirmServiceEnabled(/* confirmed= */ false);
405                 break;
406             case DialogInterface.BUTTON_NEGATIVE:
407                 handleConfirmServiceEnabled(/* confirmed= */ true);
408                 break;
409             default:
410                 throw new IllegalArgumentException("Unexpected button identifier");
411         }
412     }
413 
onDialogButtonFromEnableToggleClicked(View view)414     private void onDialogButtonFromEnableToggleClicked(View view) {
415         final int viewId = view.getId();
416         if (viewId == R.id.permission_enable_allow_button) {
417             onAllowButtonFromEnableToggleClicked();
418         } else if (viewId == R.id.permission_enable_deny_button) {
419             onDenyButtonFromEnableToggleClicked();
420         } else {
421             throw new IllegalArgumentException("Unexpected view id");
422         }
423     }
424 
onDialogButtonFromUninstallClicked()425     private void onDialogButtonFromUninstallClicked() {
426         mWarningDialog.dismiss();
427         final Intent uninstallIntent = createUninstallPackageActivityIntent();
428         if (uninstallIntent == null) {
429             return;
430         }
431         startActivity(uninstallIntent);
432     }
433 
434     @Nullable
createUninstallPackageActivityIntent()435     private Intent createUninstallPackageActivityIntent() {
436         final AccessibilityServiceInfo a11yServiceInfo = getAccessibilityServiceInfo();
437         if (a11yServiceInfo == null) {
438             Log.w(TAG, "createUnInstallIntent -- invalid a11yServiceInfo");
439             return null;
440         }
441         final ApplicationInfo appInfo =
442                 a11yServiceInfo.getResolveInfo().serviceInfo.applicationInfo;
443         final Uri packageUri = Uri.parse("package:" + appInfo.packageName);
444         final Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
445         return uninstallIntent;
446     }
447 
448     @Override
onStop()449     public void onStop() {
450         super.onStop();
451         unregisterPackageRemoveReceiver();
452     }
453 
454     @Override
getPreferenceScreenResId()455     protected int getPreferenceScreenResId() {
456         // TODO(b/171272809): Add back when controllers move to static type
457         return 0;
458     }
459 
460     @Override
getLogTag()461     protected String getLogTag() {
462         return TAG;
463     }
464 
465     @Override
getDefaultShortcutTypes()466     protected int getDefaultShortcutTypes() {
467         if (android.view.accessibility.Flags.a11yQsShortcut()) {
468             AccessibilityServiceInfo info = getAccessibilityServiceInfo();
469             boolean isAccessibilityTool = info != null && info.isAccessibilityTool();
470             return !isAccessibilityTool || getTileComponentName() == null
471                     ? super.getDefaultShortcutTypes()
472                     : ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
473         }
474 
475         return super.getDefaultShortcutTypes();
476     }
477 
onAllowButtonFromEnableToggleClicked()478     private void onAllowButtonFromEnableToggleClicked() {
479         handleConfirmServiceEnabled(/* confirmed= */ true);
480         if (serviceSupportsAccessibilityButton()) {
481             mIsDialogShown.set(false);
482             showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
483         }
484         if (mWarningDialog != null) {
485             mWarningDialog.dismiss();
486         }
487     }
488 
onDenyButtonFromEnableToggleClicked()489     private void onDenyButtonFromEnableToggleClicked() {
490         handleConfirmServiceEnabled(/* confirmed= */ false);
491         mWarningDialog.dismiss();
492     }
493 
onDialogButtonFromShortcutToggleClicked(View view)494     void onDialogButtonFromShortcutToggleClicked(View view) {
495         final int viewId = view.getId();
496         if (viewId == R.id.permission_enable_allow_button) {
497             onAllowButtonFromShortcutToggleClicked();
498         } else if (viewId == R.id.permission_enable_deny_button) {
499             onDenyButtonFromShortcutToggleClicked();
500         } else {
501             throw new IllegalArgumentException("Unexpected view id");
502         }
503     }
504 
onAllowButtonFromShortcutToggleClicked()505     void onAllowButtonFromShortcutToggleClicked() {
506         mShortcutPreference.setChecked(true);
507 
508         final int shortcutTypes = getUserPreferredShortcutTypes();
509         AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, mComponentName);
510 
511         mIsDialogShown.set(false);
512         showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
513 
514         if (mWarningDialog != null) {
515             mWarningDialog.dismiss();
516         }
517 
518         mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
519     }
520 
onDenyButtonFromShortcutToggleClicked()521     private void onDenyButtonFromShortcutToggleClicked() {
522         mShortcutPreference.setChecked(false);
523 
524         mWarningDialog.dismiss();
525     }
526 
onAllowButtonFromShortcutClicked()527     private void onAllowButtonFromShortcutClicked() {
528         mIsDialogShown.set(false);
529         if (Flags.editShortcutsInFullScreen()) {
530             EditShortcutsPreferenceFragment.showEditShortcutScreen(
531                     getContext(),
532                     getMetricsCategory(),
533                     getShortcutTitle(),
534                     mComponentName,
535                     getIntent()
536             );
537         } else {
538             showPopupDialog(DialogEnums.EDIT_SHORTCUT);
539         }
540 
541         if (mWarningDialog != null) {
542             mWarningDialog.dismiss();
543         }
544     }
545 
onDenyButtonFromShortcutClicked()546     private void onDenyButtonFromShortcutClicked() {
547         mWarningDialog.dismiss();
548     }
549 
onPreferenceClick(boolean isChecked)550     private boolean onPreferenceClick(boolean isChecked) {
551         if (isChecked) {
552             mToggleServiceSwitchPreference.setChecked(false);
553             getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED,
554                     /* disableService */ false);
555             final boolean isWarningRequired =
556                     getPrefContext().getSystemService(AccessibilityManager.class)
557                             .isAccessibilityServiceWarningRequired(getAccessibilityServiceInfo());
558             if (isWarningRequired) {
559                 showPopupDialog(DialogEnums.ENABLE_WARNING_FROM_TOGGLE);
560             } else {
561                 onAllowButtonFromEnableToggleClicked();
562             }
563         } else {
564             mToggleServiceSwitchPreference.setChecked(true);
565             getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED,
566                     /* enableService */ true);
567             showDialog(DialogEnums.DISABLE_WARNING_FROM_TOGGLE);
568         }
569         return true;
570     }
571 
showPopupDialog(int dialogId)572     private void showPopupDialog(int dialogId) {
573         if (mIsDialogShown.compareAndSet(/* expect= */ false, /* update= */ true)) {
574             showDialog(dialogId);
575             setOnDismissListener(
576                     dialog -> mIsDialogShown.compareAndSet(/* expect= */ true, /* update= */
577                             false));
578         }
579     }
580 
logDisabledState(String packageName)581     private void logDisabledState(String packageName) {
582         if (mStartTimeMillsForLogging > 0 && !mDisabledStateLogged) {
583             AccessibilityStatsLogUtils.logDisableNonA11yCategoryService(
584                     packageName,
585                     SystemClock.elapsedRealtime() - mStartTimeMillsForLogging);
586             mDisabledStateLogged = true;
587         }
588     }
589 }
590