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 import java.lang.ClassCastException
32 
33 /**
34  * Proxy to launch in user 0
35  */
36 class ControlsRequestReceiver : BroadcastReceiver() {
37 
38     companion object {
39         private const val TAG = "ControlsRequestReceiver"
40 
41         fun isPackageInForeground(context: Context, packageName: String): Boolean {
42             val uid = try {
43                 context.packageManager.getPackageUid(packageName, 0)
44             } catch (_: PackageManager.NameNotFoundException) {
45                 Log.w(TAG, "Package $packageName not found")
46                 return false
47             }
48 
49             val am = context.getSystemService(ActivityManager::class.java)
50             if ((am?.getUidImportance(uid) ?: IMPORTANCE_GONE) != IMPORTANCE_FOREGROUND) {
51                 Log.w(TAG, "Uid $uid not in foreground")
52                 return false
53             }
54             return true
55         }
56     }
57 
58     override fun onReceive(context: Context, intent: Intent) {
59         if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_CONTROLS)) {
60             return
61         }
62 
63         val targetComponent = try {
64             intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
65         } catch (e: ClassCastException) {
66             Log.e(TAG, "Malformed intent extra ComponentName", e)
67             return
68         }
69 
70         val control = try {
71             intent.getParcelableExtra<Control>(ControlsProviderService.EXTRA_CONTROL)
72         } catch (e: ClassCastException) {
73             Log.e(TAG, "Malformed intent extra Control", e)
74             return
75         }
76 
77         val packageName = targetComponent?.packageName
78 
79         if (packageName == null || !isPackageInForeground(context, packageName)) {
80             return
81         }
82 
83         val activityIntent = Intent(context, ControlsRequestDialog::class.java).apply {
84             putExtra(Intent.EXTRA_COMPONENT_NAME, targetComponent)
85             putExtra(ControlsProviderService.EXTRA_CONTROL, control)
86             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
87         }
88         activityIntent.putExtra(Intent.EXTRA_USER_ID, context.userId)
89 
90         context.startActivityAsUser(activityIntent, UserHandle.SYSTEM)
91     }
92 }