<lambda>null1 package android.platform.helpers
2 
3 import android.platform.uiautomator_helpers.DeviceHelpers.shell
4 import android.platform.uiautomator_helpers.WaitUtils.ensureThat
5 import android.util.Log
6 import java.time.Duration
7 
8 /** Allows to execute operations such as restart on a process identififed by [packageName]. */
9 class ProcessUtil(private val packageName: String) {
10 
11     /** Restart [packageName] running `am crash <package-name>`. */
12     fun restart() {
13         val initialPids = getPids("initial")
14         initialPids
15             .map { pid -> "kill $pid" }
16             .forEach { killCmd ->
17                 val result = shell(killCmd)
18                 Log.d(TAG, "Result of \"$killCmd\": \"$result\"")
19             }
20         ensureThat("All sysui process stopped", Duration.ofSeconds(30L)) {
21            allProcessesStopped(initialPids)
22         }
23         ensureThat("All sysui process restarted", Duration.ofSeconds(30L)) {
24            hasProcessRestarted(initialPids)
25        }
26     }
27 
28     private fun getPids(logTag: String): List<String> {
29         val pidofResult = shell("pidof $packageName").trim()
30         Log.d(TAG, "pidofResult($logTag) = \"$pidofResult\"")
31         return if (pidofResult.isEmpty()) {
32             emptyList()
33         } else pidofResult.split("\\s".toRegex())
34     }
35 
36     private fun allProcessesStopped(initialPidsList: List<String>): Boolean =
37         (getPids("stopped") intersect initialPidsList).isEmpty()
38 
39     /**
40      * We can only test if one process has restarted. If we match against the number of killed
41      * processes, one may have spawned another process later, and this check would fail.
42      *
43      * @param initialPidsList list of pidof $packageName
44      * @return true if there is a new process with name $packageName
45      */
46     private fun hasProcessRestarted(initialPidsList: List<String>): Boolean =
47         (getPids("restarted") subtract initialPidsList).isNotEmpty()
48 
49     private companion object {
50         const val TAG = "ProcessUtils"
51     }
52 }
53