• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.quickstep
18 
19 import android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS
20 import android.app.PendingIntent
21 import android.app.RemoteAction
22 import android.content.Context
23 import android.graphics.drawable.Icon
24 import android.provider.Settings
25 import android.provider.Settings.Secure.USER_SETUP_COMPLETE
26 import android.view.accessibility.AccessibilityManager
27 import com.android.launcher3.R
28 import com.android.launcher3.util.SettingsCache
29 import com.android.launcher3.util.SettingsCache.OnChangeListener
30 import java.util.concurrent.Executor
31 
32 private val USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(USER_SETUP_COMPLETE)
33 
34 /**
35  * Registers a [RemoteAction] for toggling All Apps if needed.
36  *
37  * We need this action when either [isHomeAndOverviewSame] or [isTaskbarPresent] is `true`. When
38  * home and overview are the same, we can control Launcher's or Taskbar's All Apps tray. If they are
39  * not the same, but Taskbar is present, we can only control Taskbar's tray.
40  */
41 class AllAppsActionManager(
42     private val context: Context,
43     private val bgExecutor: Executor,
44     private val createAllAppsPendingIntent: () -> PendingIntent,
45 ) {
46 
47     private val onSettingsChangeListener = OnChangeListener { v -> isUserSetupComplete = v }
48 
49     init {
50         SettingsCache.INSTANCE[context].register(USER_SETUP_COMPLETE_URI, onSettingsChangeListener)
51     }
52 
53     /** `true` if home and overview are the same Activity. */
54     var isHomeAndOverviewSame = false
55         set(value) {
56             field = value
57             updateSystemAction()
58         }
59 
60     /** `true` if Taskbar is enabled. */
61     var isTaskbarPresent = false
62         set(value) {
63             field = value
64             updateSystemAction()
65         }
66 
67     /** `true` if the setup UI is visible. */
68     var isSetupUiVisible = false
69         set(value) {
70             field = value
71             updateSystemAction()
72         }
73 
74     private var isUserSetupComplete =
75         SettingsCache.INSTANCE[context].getValue(USER_SETUP_COMPLETE_URI, 0)
76         set(value) {
77             field = value
78             updateSystemAction()
79         }
80 
81     /** `true` if the action should be registered. */
82     var isActionRegistered = false
83         private set
84 
85     private fun updateSystemAction() {
86         val isInSetupFlow = isSetupUiVisible || !isUserSetupComplete
87         val shouldRegisterAction = (isHomeAndOverviewSame || isTaskbarPresent) && !isInSetupFlow
88         if (isActionRegistered == shouldRegisterAction) return
89         isActionRegistered = shouldRegisterAction
90 
91         bgExecutor.execute {
92             val accessibilityManager =
93                 context.getSystemService(AccessibilityManager::class.java) ?: return@execute
94             if (shouldRegisterAction) {
95                 accessibilityManager.registerSystemAction(
96                     RemoteAction(
97                         Icon.createWithResource(context, R.drawable.ic_apps),
98                         context.getString(R.string.all_apps_label),
99                         context.getString(R.string.all_apps_label),
100                         createAllAppsPendingIntent(),
101                     ),
102                     GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
103                 )
104             } else {
105                 accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
106             }
107         }
108     }
109 
110     fun onDestroy() {
111         isActionRegistered = false
112         context
113             .getSystemService(AccessibilityManager::class.java)
114             ?.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
115         SettingsCache.INSTANCE[context].unregister(
116             USER_SETUP_COMPLETE_URI,
117             onSettingsChangeListener,
118         )
119     }
120 }
121