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