1 /*
<lambda>null2 * 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.permissioncontroller.permission.utils
18
19 import android.app.Activity
20 import android.app.Application
21 import android.app.Service
22 import android.content.Context
23 import android.content.ContextWrapper
24 import android.content.pm.ComponentInfo
25 import android.content.pm.PackageManager
26 import android.content.pm.ResolveInfo
27 import android.os.Looper
28 import android.os.UserHandle
29 import kotlinx.coroutines.asCoroutineDispatcher
30 import java.util.concurrent.Executors
31
32 /**
33 * Gets an [Application] instance from a regular [Context]
34 */
35 val Context.application: Application get() = when (this) {
36 is Application -> this
37 is Activity -> application
38 is Service -> application
39 is ContextWrapper -> baseContext.application
40 else -> applicationContext as Application
41 }
42
43 /**
44 * The number of threads in the IPC thread pool. Set to the maximum number of binder threads allowed
45 * to an app by the Android System.
46 */
47 const val IPC_THREAD_POOL_COUNT = 8
48
49 /**
50 * A coroutine dispatcher with a fixed thread pool size, to be used for background tasks
51 */
52 val IPC = Executors.newFixedThreadPool(IPC_THREAD_POOL_COUNT).asCoroutineDispatcher()
53
54 /**
55 * Assert that an operation is running on main thread
56 */
ensureMainThreadnull57 fun ensureMainThread() = check(Looper.myLooper() == Looper.getMainLooper()) {
58 "Only meant to be used on the main thread"
59 }
60
61 /**
62 * A more readable version of [PackageManager.updatePermissionFlags]
63 */
PackageManagernull64 fun PackageManager.updatePermissionFlags(
65 permissionName: String,
66 packageName: String,
67 user: UserHandle,
68 vararg flags: Pair<Int, Boolean>
69 ) {
70 val mask = flags.fold(0, { mask, (flag, _) -> mask or flag })
71 val value = flags.fold(0, { mask, (flag, flagValue) -> if (flagValue) mask or flag else mask })
72 updatePermissionFlags(permissionName, packageName, mask, value, user)
73 }
74
75 /**
76 * @see UserHandle.getUid
77 */
getUidnull78 fun UserHandle.getUid(appId: Int): Int {
79 return identifier * 100000 + (appId % 100000)
80 }
81
82 /**
83 * Gets a [ComponentInfo] from a [ResolveInfo]
84 */
85 val ResolveInfo.componentInfo: ComponentInfo
86 get() {
87 return (activityInfo as ComponentInfo?)
88 ?: serviceInfo
89 ?: providerInfo
90 ?: throw IllegalStateException("Missing ComponentInfo!")
91 }