1 /*
<lambda>null2 * Copyright 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 @file:JvmName("ProcessUtils")
17
18 package androidx.work.impl.utils
19
20 import android.annotation.SuppressLint
21 import android.app.ActivityManager
22 import android.app.Application
23 import android.content.Context
24 import android.os.Build
25 import android.os.Process
26 import androidx.annotation.RequiresApi
27 import androidx.work.Configuration
28 import androidx.work.Logger
29 import androidx.work.WorkManager
30
31 private val TAG = Logger.tagWithPrefix("ProcessUtils")
32
33 /** @return `true` when `WorkManager` is running in the configured app process. */
34 fun isDefaultProcess(context: Context, configuration: Configuration): Boolean {
35 val processName = getProcessName(context)
36 return if (!configuration.defaultProcessName.isNullOrEmpty()) {
37 processName == configuration.defaultProcessName
38 } else {
39 processName == context.applicationInfo.processName
40 }
41 }
42
43 /** @return The name of the active process. */
44 @SuppressLint("PrivateApi", "DiscouragedPrivateApi")
getProcessNamenull45 private fun getProcessName(context: Context): String? {
46 if (Build.VERSION.SDK_INT >= 28) return Api28Impl.processName
47
48 // Try using ActivityThread to determine the current process name.
49 try {
50 val activityThread =
51 Class.forName("android.app.ActivityThread", false, WorkManager::class.java.classLoader)
52
53 val currentProcessName = activityThread.getDeclaredMethod("currentProcessName")
54 currentProcessName.isAccessible = true
55 val packageName = currentProcessName.invoke(null)!!
56
57 if (packageName is String) return packageName
58 } catch (exception: Throwable) {
59 Logger.get().debug(TAG, "Unable to check ActivityThread for processName", exception)
60 }
61
62 // Fallback to the most expensive way
63 val pid = Process.myPid()
64 val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
65 return am.runningAppProcesses?.find { process -> process.pid == pid }?.processName
66 }
67
68 @RequiresApi(28)
69 private object Api28Impl {
70 val processName: String
71 get() = Application.getProcessName()
72 }
73