taskman_atf/device.inc.php

162 lines
3.8 KiB
PHP
Raw Normal View History

2023-11-07 15:42:40 +03:00
<?php
namespace ATF;
use Exception;
interface IDevicePool
{
function get() : array;
}
class ApkInstaller
{
const ST_IN_PROGRESS = 1;
const ST_INSTALLED = 2;
private string $atf_host;
private ?string $apk_name;
private int $max_installs_in_progress;
private array $installs = array();
private bool $override_external_files;
private array $external_files = array();
function __construct(
string $atf_host,
int $max_installs_in_progress,
?string $apk_name,
bool $override_external_files,
array $external_files
)
{
$this->atf_host = $atf_host;
$this->max_installs_in_progress = $max_installs_in_progress;
$this->apk_name = $apk_name;
$this->override_external_files = $override_external_files;
$this->external_files = $external_files;
}
function isInstalled(string $device)
{
return isset($this->installs[$device]) && $this->installs[$device] == self::ST_INSTALLED;
}
function forgetInstall(string $device)
{
unset($this->installs[$device]);
}
function countInstallsInProgress()
{
$c = 0;
foreach($this->installs as $status)
if($status == self::ST_IN_PROGRESS)
++$c;
return $c;
}
function installAsync(string $device, bool $force = false) : Amp\Promise
{
return Amp\call(function() use($device, $force) {
while($this->countInstallsInProgress() >= $this->max_installs_in_progress)
yield Amp\delay(1000);
if($force)
unset($this->installs[$device]);
if(isset($this->installs[$device]))
return;
$this->installs[$device] = self::ST_IN_PROGRESS;
try
{
yield host_exec_async($this->atf_host, "%{adb}% -s $device shell am force-stop %{package_id}%", DEPLOY_OPT_ERR_OK);
if($this->apk_name !== null)
{
yield host_exec_async($this->atf_host, "%{adb}% -s $device uninstall %{package_id}%", DEPLOY_OPT_ERR_OK, 30);
yield host_exec_async($this->atf_host, "%{adb}% -s $device install -r %{dir}%/{$this->apk_name}", 0, 300);
//delete overrides only if there's a new apk file uploaded
yield del_external_files_async($this->atf_host, $device, $this->external_files);
}
if($this->override_external_files)
yield put_external_files_async($this->atf_host, $device, $this->external_files);
$this->installs[$device] = self::ST_INSTALLED;
}
catch(Exception $e)
{
err("Error during install *$device*: " . $e->getMessage());
unset($this->installs[$device]);
throw $e;
}
});
}
function getSize()
{
list($status, $lines) = host_exec($this->atf_host, "ls -sd -- %{dir}%/{$this->apk_name}", DEPLOY_OPT_ERR_OK|DEPLOY_OPT_SILENT);
if($status != 0)
return 0;
$items = explode(' ', $lines[0]);
//ls -s returns size in blocks where each block is 512 bytes long
return intval($items[0])*512;
}
}
class AdbDevicePool implements IDevicePool
{
private string $atf_host;
function __construct(string $atf_host)
{
$this->atf_host = $atf_host;
}
function get() : array
{
return get_devices($this->atf_host);
}
}
class FixedDevicePool implements IDevicePool
{
private array $devices;
function __construct(array $devices)
{
$this->devices = $devices;
}
function get() : array
{
return $this->devices;
}
}
class CachedDevices implements IDevicePool
{
private IDevicePool $provider;
private ?array $cached = null;
private int $last_cache_time;
private int $keep_cache_time;
function __construct(IDevicePool $provider, int $keep_cache_time)
{
$this->provider = $provider;
$this->keep_cache_time = $keep_cache_time;
}
function get() : array
{
if($this->cached === null || (time() - $this->last_cache_time) > $this->keep_cache_time)
{
$this->cached = $this->provider->get();
$this->last_cache_time = time();
}
return $this->cached;
}
}