1 /*
<lambda>null2  * Copyright (C) 2023 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.qs.tiles.base.actions
18 
19 import android.app.PendingIntent
20 import android.content.Intent
21 import android.content.pm.PackageManager
22 import android.os.UserHandle
23 import com.android.internal.jank.InteractionJankMonitor
24 import com.android.systemui.animation.ActivityTransitionAnimator
25 import com.android.systemui.animation.Expandable
26 import com.android.systemui.dagger.SysUISingleton
27 import com.android.systemui.plugins.ActivityStarter
28 import javax.inject.Inject
29 
30 /**
31  * Provides a shortcut to start an activity from [QSTileUserActionInteractor]. It supports keyguard
32  * dismissing and tile from-view animations, as well as the option to show over lockscreen.
33  */
34 interface QSTileIntentUserInputHandler {
35 
36     fun handle(
37         expandable: Expandable?,
38         intent: Intent,
39         dismissShadeShowOverLockScreenWhenLocked: Boolean = false
40     )
41 
42     /** @param requestLaunchingDefaultActivity used in case !pendingIndent.isActivity */
43     fun handle(
44         expandable: Expandable?,
45         pendingIntent: PendingIntent,
46         requestLaunchingDefaultActivity: Boolean = false
47     )
48 }
49 
50 @SysUISingleton
51 class QSTileIntentUserInputHandlerImpl
52 @Inject
53 constructor(
54     private val activityStarter: ActivityStarter,
55     private val packageManager: PackageManager,
56     private val userHandle: UserHandle,
57 ) : QSTileIntentUserInputHandler {
58 
handlenull59     override fun handle(
60         expandable: Expandable?,
61         intent: Intent,
62         dismissShadeShowOverLockScreenWhenLocked: Boolean
63     ) {
64         val animationController: ActivityTransitionAnimator.Controller? =
65             expandable?.activityTransitionController(
66                 InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
67             )
68         if (dismissShadeShowOverLockScreenWhenLocked) {
69             activityStarter.startActivity(
70                 intent,
71                 true /* dismissShade */,
72                 animationController,
73                 true /* showOverLockscreenWhenLocked */
74             )
75         } else {
76             activityStarter.postStartActivityDismissingKeyguard(intent, 0, animationController)
77         }
78     }
79 
80     // TODO(b/249804373): make sure to allow showing activities over the lockscreen. See b/292112939
handlenull81     override fun handle(
82         expandable: Expandable?,
83         pendingIntent: PendingIntent,
84         requestLaunchingDefaultActivity: Boolean
85     ) {
86         if (pendingIntent.isActivity) {
87             val animationController: ActivityTransitionAnimator.Controller? =
88                 expandable?.activityTransitionController(
89                     InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
90                 )
91             activityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController)
92         } else if (requestLaunchingDefaultActivity) {
93             val intent =
94                 Intent(Intent.ACTION_MAIN)
95                     .addCategory(Intent.CATEGORY_LAUNCHER)
96                     .setPackage(pendingIntent.creatorPackage)
97                     .addFlags(
98                         Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
99                     )
100             val intents =
101                 packageManager.queryIntentActivitiesAsUser(
102                     intent,
103                     PackageManager.ResolveInfoFlags.of(0L),
104                     userHandle.identifier
105                 )
106             intents
107                 .firstOrNull { it.activityInfo.exported }
108                 ?.let { resolved ->
109                     intent.setPackage(null)
110                     intent.setComponent(resolved.activityInfo.componentName)
111                     handle(expandable, intent)
112                 }
113         }
114     }
115 }
116