1 /*
2  * Copyright (C) 2020 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.controls.management
18 
19 import android.app.ActivityManager
20 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
21 import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE
22 import android.content.BroadcastReceiver
23 import android.content.ComponentName
24 import android.content.Context
25 import android.content.Intent
26 import android.content.pm.PackageManager
27 import android.os.UserHandle
28 import android.service.controls.Control
29 import android.service.controls.ControlsProviderService
30 import android.util.Log
31 
32 /**
33  * Proxy to launch in user 0
34  */
35 class ControlsRequestReceiver : BroadcastReceiver() {
36 
37     companion object {
38         private const val TAG = "ControlsRequestReceiver"
39 
isPackageInForegroundnull40         fun isPackageInForeground(context: Context, packageName: String): Boolean {
41             val uid = try {
42                 context.packageManager.getPackageUid(packageName, 0)
43             } catch (_: PackageManager.NameNotFoundException) {
44                 Log.w(TAG, "Package $packageName not found")
45                 return false
46             }
47 
48             val am = context.getSystemService(ActivityManager::class.java)
49             if ((am?.getUidImportance(uid) ?: IMPORTANCE_GONE) != IMPORTANCE_FOREGROUND) {
50                 Log.w(TAG, "Uid $uid not in foreground")
51                 return false
52             }
53             return true
54         }
55     }
56 
onReceivenull57     override fun onReceive(context: Context, intent: Intent) {
58         if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)) {
59             return
60         }
61 
62         val targetComponent = try {
63             intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName::class.java)
64         } catch (e: Exception) {
65             Log.e(TAG, "Malformed intent extra ComponentName", e)
66             return
67         } ?: run {
68             Log.e(TAG, "Null target component")
69             return
70         }
71 
72         val control = try {
73             intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL, Control::class.java)
74         } catch (e: Exception) {
75             Log.e(TAG, "Malformed intent extra Control", e)
76             return
77         } ?: run {
78             Log.e(TAG, "Null control")
79             return
80         }
81 
82         val packageName = targetComponent.packageName
83 
84         if (!isPackageInForeground(context, packageName)) {
85             return
86         }
87 
88         val activityIntent = Intent(context, ControlsRequestDialog::class.java).apply {
89             putExtra(Intent.EXTRA_COMPONENT_NAME, targetComponent)
90             putExtra(ControlsProviderService.EXTRA_CONTROL, control)
91             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
92         }
93         activityIntent.putExtra(Intent.EXTRA_USER_ID, context.userId)
94 
95         context.startActivityAsUser(activityIntent, UserHandle.SYSTEM)
96     }
97 }