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.car.carlauncher.repositories.appactions
18 
19 import android.car.media.CarMediaManager
20 import android.content.ComponentName
21 import android.content.Context
22 import android.os.Process
23 import android.os.UserHandle
24 import android.view.Display.INVALID_DISPLAY
25 import android.view.View
26 import com.android.car.carlaunchercommon.shortcuts.AppInfoShortcutItem
27 import com.android.car.carlaunchercommon.shortcuts.ForceStopShortcutItem
28 import com.android.car.carlaunchercommon.shortcuts.PinShortcutItem
29 import com.android.car.dockutil.Flags
30 import com.android.car.dockutil.events.DockCompatUtils.isDockSupportedOnDisplay
31 import com.android.car.dockutil.events.DockEventSenderHelper
32 import com.android.car.ui.shortcutspopup.CarUiShortcutsPopup
33 
34 /**
35  * This class is responsible for creating and displaying app shortcuts popups within the
36  * car UI. It generates shortcuts for actions like "Stop App," "App Info," and potentially
37  * "Pin to Dock." The class interacts with CarMediaManager and relies on a ShortcutsListener
38  * to track interactions with the shortcuts popup.
39  *
40  * @param carMediaManager For controlling car media settings.
41  * @param mediaServiceComponents A set of ComponentNames identifying installed media services.
42  * @param shortcutsListener Listener for handling events triggered by the shortcuts popup.
43  */
44 class AppShortcutsFactory(
45     private val carMediaManager: CarMediaManager,
46     private val mediaServiceComponents: Set<ComponentName>,
47     private val shortcutsListener: ShortcutsListener
48 ) {
49 
50     /**
51      * Displays a car UI shortcuts popup anchored to the provided view.  The popup includes
52      * shortcuts for "Force Stop," "App Info," and potentially "Pin to Dock" (if the feature
53      * is enabled).
54      *
55      * @param componentName The ComponentName of the app for which shortcuts are generated.
56      * @param displayName The display name of the app.
57      * @param context Application context.
58      * @param anchorView The UI view to anchor the shortcuts popup.
59      */
showShortcutsnull60     fun showShortcuts(
61         componentName: ComponentName,
62         displayName: CharSequence,
63         context: Context,
64         anchorView: View
65     ) {
66         val carUiShortcutsPopupBuilder =
67             CarUiShortcutsPopup.Builder()
68                 .addShortcut(
69                     ForceStopShortcutItem(
70                         context,
71                         componentName.packageName,
72                         displayName,
73                         carMediaManager,
74                         mediaServiceComponents
75                     )
76                 )
77                 .addShortcut(
78                     AppInfoShortcutItem(
79                         context,
80                         componentName.packageName,
81                         UserHandle.getUserHandleForUid(Process.myUid())
82                     )
83                 )
84         if (Flags.dockFeature() &&
85             isDockSupportedOnDisplay(context, context.display?.displayId ?: INVALID_DISPLAY)
86         ) {
87             carUiShortcutsPopupBuilder
88                 .addShortcut(buildPinToDockShortcut(componentName, context))
89         }
90         val carUiShortcutsPopup =
91             carUiShortcutsPopupBuilder
92                 .build(context, anchorView)
93         carUiShortcutsPopup.show()
94         shortcutsListener.onShortcutsShow(carUiShortcutsPopup)
95     }
96 
97     /**
98      * Helper function to construct a shortcut item for the "Pin to Dock" action
99      * within the shortcuts popup.
100      *
101      * @param componentName ComponentName of the app to be pinned.
102      * @param context Application context.
103      * @return A CarUiShortcutsPopup.ShortcutItem for the "Pin to Dock" action, or null
104      *         if the feature is not enabled.
105      */
buildPinToDockShortcutnull106     private fun buildPinToDockShortcut(
107         componentName: ComponentName,
108         context: Context
109     ): CarUiShortcutsPopup.ShortcutItem? {
110         val helper = DockEventSenderHelper(context)
111         return PinShortcutItem(
112             context.resources,
113             false,
114             { helper.sendPinEvent(componentName) }
115         )
116         { helper.sendUnpinEvent(componentName) }
117     }
118 
119     /**
120      *  Simple callback interface for notifying clients when a car UI shortcuts
121      *  popup is displayed.
122      */
123     interface ShortcutsListener {
124         /**
125          *  Called when a CarUiShortcutsPopup view becomes visible.
126          *
127          *  @param carUiShortcutsPopup The displayed popup view.
128          */
onShortcutsShownull129         fun onShortcutsShow(carUiShortcutsPopup: CarUiShortcutsPopup)
130     }
131 }
132