1 /*
2  * 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.view.accessibility.AccessibilityManager
25 import com.android.launcher3.R
26 import java.util.concurrent.Executor
27 
28 /**
29  * Registers a [RemoteAction] for toggling All Apps if needed.
30  *
31  * We need this action when either [isHomeAndOverviewSame] or [isTaskbarPresent] is `true`. When
32  * home and overview are the same, we can control Launcher's or Taskbar's All Apps tray. If they are
33  * not the same, but Taskbar is present, we can only control Taskbar's tray.
34  */
35 class AllAppsActionManager(
36     private val context: Context,
37     private val bgExecutor: Executor,
38     private val createAllAppsPendingIntent: () -> PendingIntent,
39 ) {
40 
41     /** `true` if home and overview are the same Activity. */
42     var isHomeAndOverviewSame = false
43         set(value) {
44             field = value
45             updateSystemAction()
46         }
47 
48     /** `true` if Taskbar is enabled. */
49     var isTaskbarPresent = false
50         set(value) {
51             field = value
52             updateSystemAction()
53         }
54 
55     /** `true` if the action should be registered. */
56     var isActionRegistered = false
57         private set
58 
updateSystemActionnull59     private fun updateSystemAction() {
60         val shouldRegisterAction = isHomeAndOverviewSame || isTaskbarPresent
61         if (isActionRegistered == shouldRegisterAction) return
62         isActionRegistered = shouldRegisterAction
63 
64         bgExecutor.execute {
65             val accessibilityManager =
66                 context.getSystemService(AccessibilityManager::class.java) ?: return@execute
67             if (shouldRegisterAction) {
68                 accessibilityManager.registerSystemAction(
69                     RemoteAction(
70                         Icon.createWithResource(context, R.drawable.ic_apps),
71                         context.getString(R.string.all_apps_label),
72                         context.getString(R.string.all_apps_label),
73                         createAllAppsPendingIntent(),
74                     ),
75                     GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
76                 )
77             } else {
78                 accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
79             }
80         }
81     }
82 
onDestroynull83     fun onDestroy() {
84         isActionRegistered = false
85         context
86             .getSystemService(AccessibilityManager::class.java)
87             ?.unregisterSystemAction(
88                 GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
89             )
90     }
91 }
92