1 /* 2 * Copyright (C) 2021 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.systemui.accessibility.floatingmenu; 18 19 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; 20 21 import android.content.Context; 22 import android.os.UserHandle; 23 import android.text.TextUtils; 24 25 import androidx.annotation.MainThread; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.keyguard.KeyguardUpdateMonitor; 29 import com.android.keyguard.KeyguardUpdateMonitorCallback; 30 import com.android.systemui.accessibility.AccessibilityButtonModeObserver; 31 import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode; 32 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver; 33 import com.android.systemui.dagger.SysUISingleton; 34 import com.android.systemui.util.settings.SecureSettings; 35 36 import javax.inject.Inject; 37 38 /** A controller to handle the lifecycle of accessibility floating menu. */ 39 @MainThread 40 @SysUISingleton 41 public class AccessibilityFloatingMenuController implements 42 AccessibilityButtonModeObserver.ModeChangedListener, 43 AccessibilityButtonTargetsObserver.TargetsChangedListener { 44 45 private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; 46 private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver; 47 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 48 private final SecureSettings mSecureSettings; 49 50 private Context mContext; 51 @VisibleForTesting 52 IAccessibilityFloatingMenu mFloatingMenu; 53 private int mBtnMode; 54 private String mBtnTargets; 55 private boolean mIsKeyguardVisible; 56 57 @VisibleForTesting 58 final KeyguardUpdateMonitorCallback mKeyguardCallback = new KeyguardUpdateMonitorCallback() { 59 60 @Override 61 public void onUserUnlocked() { 62 handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); 63 } 64 65 @Override 66 public void onKeyguardVisibilityChanged(boolean visible) { 67 mIsKeyguardVisible = visible; 68 handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); 69 } 70 71 @Override 72 public void onUserSwitching(int userId) { 73 destroyFloatingMenu(); 74 } 75 76 @Override 77 public void onUserSwitchComplete(int userId) { 78 mContext = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0); 79 mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode(); 80 mBtnTargets = 81 mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets(); 82 handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); 83 } 84 }; 85 86 @Inject AccessibilityFloatingMenuController(Context context, AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver, AccessibilityButtonModeObserver accessibilityButtonModeObserver, KeyguardUpdateMonitor keyguardUpdateMonitor, SecureSettings secureSettings)87 public AccessibilityFloatingMenuController(Context context, 88 AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver, 89 AccessibilityButtonModeObserver accessibilityButtonModeObserver, 90 KeyguardUpdateMonitor keyguardUpdateMonitor, 91 SecureSettings secureSettings) { 92 mContext = context; 93 mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver; 94 mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; 95 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 96 mSecureSettings = secureSettings; 97 98 mIsKeyguardVisible = false; 99 } 100 101 /** 102 * Handles visibility of the accessibility floating menu when accessibility button mode changes. 103 * 104 * @param mode Current accessibility button mode. 105 */ 106 @Override onAccessibilityButtonModeChanged(@ccessibilityButtonMode int mode)107 public void onAccessibilityButtonModeChanged(@AccessibilityButtonMode int mode) { 108 mBtnMode = mode; 109 handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); 110 } 111 112 /** 113 * Handles visibility of the accessibility floating menu when accessibility button targets 114 * changes. 115 * List should come from {@link android.provider.Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS}. 116 * @param targets Current accessibility button list. 117 */ 118 @Override onAccessibilityButtonTargetsChanged(String targets)119 public void onAccessibilityButtonTargetsChanged(String targets) { 120 mBtnTargets = targets; 121 handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); 122 } 123 124 /** Initializes the AccessibilityFloatingMenuController configurations. */ init()125 public void init() { 126 mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode(); 127 mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets(); 128 registerContentObservers(); 129 } 130 registerContentObservers()131 private void registerContentObservers() { 132 mAccessibilityButtonModeObserver.addListener(this); 133 mAccessibilityButtonTargetsObserver.addListener(this); 134 mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback); 135 } 136 137 /** 138 * Handles the accessibility floating menu visibility with the given values. 139 * 140 * @param keyguardVisible the keyguard visibility status. Not show the 141 * {@link AccessibilityFloatingMenu} when keyguard appears. 142 * @param mode accessibility button mode {@link AccessibilityButtonMode} 143 * @param targets accessibility button list; it should comes from 144 * {@link android.provider.Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS}. 145 */ handleFloatingMenuVisibility(boolean keyguardVisible, @AccessibilityButtonMode int mode, String targets)146 private void handleFloatingMenuVisibility(boolean keyguardVisible, 147 @AccessibilityButtonMode int mode, String targets) { 148 if (keyguardVisible) { 149 destroyFloatingMenu(); 150 return; 151 } 152 153 if (shouldShowFloatingMenu(mode, targets)) { 154 showFloatingMenu(); 155 } else { 156 destroyFloatingMenu(); 157 } 158 } 159 shouldShowFloatingMenu(@ccessibilityButtonMode int mode, String targets)160 private boolean shouldShowFloatingMenu(@AccessibilityButtonMode int mode, String targets) { 161 return mode == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU && !TextUtils.isEmpty(targets); 162 } 163 showFloatingMenu()164 private void showFloatingMenu() { 165 if (mFloatingMenu == null) { 166 mFloatingMenu = new AccessibilityFloatingMenu(mContext, mSecureSettings); 167 } 168 169 mFloatingMenu.show(); 170 } 171 destroyFloatingMenu()172 private void destroyFloatingMenu() { 173 if (mFloatingMenu == null) { 174 return; 175 } 176 177 mFloatingMenu.hide(); 178 mFloatingMenu = null; 179 } 180 } 181