<lambda>null1package 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