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 java.util.concurrent.Executors
30 import kotlinx.coroutines.asCoroutineDispatcher
31
32 /** Gets an [Application] instance from a regular [Context] */
33 val Context.application: Application
34 get() =
35 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 /** A coroutine dispatcher with a fixed thread pool size, to be used for background tasks */
50 val IPC = Executors.newFixedThreadPool(IPC_THREAD_POOL_COUNT).asCoroutineDispatcher()
51
52 /** Assert that an operation is running on main thread */
ensureMainThreadnull53 fun ensureMainThread() =
54 check(Looper.myLooper() == Looper.getMainLooper()) {
55 "Only meant to be used on the main thread"
56 }
57
58 /** A more readable version of [PackageManager.updatePermissionFlags] */
PackageManagernull59 fun PackageManager.updatePermissionFlags(
60 permissionName: String,
61 packageName: String,
62 user: UserHandle,
63 vararg flags: Pair<Int, Boolean>
64 ) {
65 val mask = flags.fold(0, { mask, (flag, _) -> mask or flag })
66 val value =
67 flags.fold(0, { mask2, (flag, flagValue) -> if (flagValue) mask2 or flag else mask2 })
68 updatePermissionFlags(permissionName, packageName, mask, value, user)
69 }
70
71 /** Gets a [ComponentInfo] from a [ResolveInfo] */
72 val ResolveInfo.componentInfo: ComponentInfo
73 get() {
74 return (activityInfo as ComponentInfo?)
75 ?: serviceInfo ?: providerInfo ?: throw IllegalStateException("Missing ComponentInfo!")
76 }
77