1 /*
2  * Copyright (C) 2022 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 android.content.ComponentName;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.os.Handler;
23 
24 import androidx.preference.PreferenceScreen;
25 
26 import com.android.settings.R;
27 import com.android.settings.core.TogglePreferenceController;
28 import com.android.settingslib.PrimarySwitchPreference;
29 import com.android.settingslib.core.lifecycle.LifecycleObserver;
30 import com.android.settingslib.core.lifecycle.events.OnCreate;
31 import com.android.settingslib.core.lifecycle.events.OnDestroy;
32 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
33 
34 /** PrimarySwitchPreferenceController that shows quick settings tooltip on first use. */
35 public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceController
36         extends TogglePreferenceController
37         implements LifecycleObserver, OnCreate, OnDestroy, OnSaveInstanceState {
38     private static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow";
39     private final Handler mHandler;
40     private PrimarySwitchPreference mPreference;
41     private AccessibilityQuickSettingsTooltipWindow mTooltipWindow;
42     private boolean mNeedsQSTooltipReshow = false;
43 
44     /** Returns the accessibility tile component name. */
getTileComponentName()45     abstract ComponentName getTileComponentName();
46 
47     /** Returns the accessibility tile tooltip content. */
getTileTooltipContent()48     abstract CharSequence getTileTooltipContent();
49 
AccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context, String preferenceKey)50     public AccessibilityQuickSettingsPrimarySwitchPreferenceController(Context context,
51             String preferenceKey) {
52         super(context, preferenceKey);
53         mHandler = new Handler(context.getMainLooper());
54     }
55 
56     @Override
onCreate(Bundle savedInstanceState)57     public void onCreate(Bundle savedInstanceState) {
58         // Restore the tooltip.
59         if (savedInstanceState != null) {
60             if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
61                 mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW);
62             }
63         }
64     }
65 
66     @Override
onDestroy()67     public void onDestroy() {
68         mHandler.removeCallbacksAndMessages(null);
69         final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
70         if (isTooltipWindowShowing) {
71             mTooltipWindow.dismiss();
72         }
73     }
74 
75     @Override
onSaveInstanceState(Bundle outState)76     public void onSaveInstanceState(Bundle outState) {
77         final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
78         if (mNeedsQSTooltipReshow || isTooltipWindowShowing) {
79             outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
80         }
81     }
82 
83     @Override
displayPreference(PreferenceScreen screen)84     public void displayPreference(PreferenceScreen screen) {
85         super.displayPreference(screen);
86         mPreference = screen.findPreference(getPreferenceKey());
87         if (mNeedsQSTooltipReshow) {
88             mHandler.post(this::showQuickSettingsTooltipIfNeeded);
89         }
90     }
91 
92     @Override
setChecked(boolean isChecked)93     public boolean setChecked(boolean isChecked) {
94         if (isChecked) {
95             showQuickSettingsTooltipIfNeeded();
96         }
97         return isChecked;
98     }
99 
100     @Override
isChecked()101     public boolean isChecked() {
102         return false;
103     }
104 
105     @Override
getAvailabilityStatus()106     public int getAvailabilityStatus() {
107         return AVAILABLE;
108     }
109 
110     @Override
getSliceHighlightMenuRes()111     public int getSliceHighlightMenuRes() {
112         return R.string.menu_key_accessibility;
113     }
114 
showQuickSettingsTooltipIfNeeded()115     private void showQuickSettingsTooltipIfNeeded() {
116         if (mPreference == null) {
117             // Returns if no preference found by slice highlight menu.
118             return;
119         }
120 
121         final ComponentName tileComponentName = getTileComponentName();
122         if (tileComponentName == null) {
123             // Returns if no tile service assigned.
124             return;
125         }
126 
127         if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences(
128                 mContext, tileComponentName)) {
129             // Returns if quick settings tooltip only show once.
130             return;
131         }
132 
133         // TODO (287728819): Move tooltip showing to SystemUI
134         // Since the lifecycle of controller is independent of that of the preference, doing
135         // null check on switch is a temporary solution for the case that switch view
136         // is not ready when we would like to show the tooltip.  If the switch is not ready,
137         // we give up showing the tooltip and also do not reshow it in the future.
138         if (mPreference.getSwitch() != null) {
139             mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext);
140             mTooltipWindow.setup(getTileTooltipContent(),
141                     R.drawable.accessibility_auto_added_qs_tooltip_illustration);
142             mTooltipWindow.showAtTopCenter(mPreference.getSwitch());
143         }
144         AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext, tileComponentName);
145         mNeedsQSTooltipReshow = false;
146     }
147 }
148