Android-ElectricSheep-Automator
view release on metacpan or search on metacpan
lib/Android/ElectricSheep/Automator/AppProperties.pm view on Meta::CPAN
# meaning that they will be left to be enquired when someone needs them
# e.g. in an open_app() call.
sub enquire_installed_apps_factory {
my $params = $_[0] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# we need a mother object (Android::ElectricSheep::Automator)
if( (! exists $params->{'mother'})
|| (! defined $params->{'mother'})
|| (! defined $params->{'mother'}->adb())
){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, input parameter 'mother' with our parent Android::ElectricSheep::Automator object was not specified.\n"; return undef }
my $mother = $params->{'mother'};
# we now have a mother
my $log = $mother->log;
my $verbosity = $mother->verbosity;
# default is to be lazy (except for 'packages' if any)
my $lazy = (exists($params->{'lazy'}) && defined($params->{'lazy'})) ? $params->{'lazy'} : 1;
# if the user has specified packages then we will load just those non-lazily
my ($packages, @packages_arr);
if( exists($params->{'packages'}) && defined($packages=$params->{'packages'}) ){
# packages can be a single package name
my $rr = ref($packages);
if( ($rr eq '') || ($rr eq 'Regexp') ){ @packages_arr = ($packages) }
elsif( $rr eq 'ARRAY' ){ @packages_arr = @$packages }
elsif( $rr eq 'HASH' ){ @packages_arr = ( map { $_ } grep { $packages->{$_} > 0 } keys %$packages ) }
else { $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'packages' must be a scalar string (for specifying just one package) or a regexp (Regexp type for compiled (".'qr//'.") regexes or an ARRAYref or a HASHref of p...
}
my $N_packages = scalar(@packages_arr);
# by now we have packages as a HASHref or undef and they can contain regex or string package names.
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : called ...") }
# NOTE
# dumpsys package packages
# and
# dumpsys package com.example.xyz
# will yield different things for the package com.example.xyz
# we need to enquire twice, 1 for all the package names
# 2 for the full content of the package info, including activities
# we will dumpsys specifically for that package
# here we could also save to a file on device and then
# fetch it locally. We will do that if there are problems
# getting the dump from STDOUT
my @cmd = ('dumpsys', 'package', 'packages');
my $res = $mother->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nsSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
my $content = $res->[1];
my %apps;
while( $content =~ /^\s{2}Package\s+\[(.+?)\]\s+\(.+?\)\:[\r\n](.+?)(?:[\r\n]\s{2}[^ ]|[\r\n]$|\z)/smg ){
# if you want the package content:
#while( $content =~ /^(\s{2}Package\s+\[(.+?)\]\s+\(.+?\)\:[\r\n].+?)(?:[\r\n]\s{2}[^ ]|[\r\n]$|\z)/smg ){
#my $package_contents = $1; and name $2
my $package_name = $1; # full package name, e.g. com.google.android.calendar
# we will be lazy
my $is_this_lazy = $lazy;
if( $lazy == 1 ){
for my $ap (@packages_arr){
if( ref($ap) eq '' ){
if( $package_name eq $ap ){ $is_this_lazy = 0; last }
} else {
if( $package_name =~ $ap ){ $is_this_lazy = 0; last }
}
}
}
if( $is_this_lazy == 0 ){
my $app = Android::ElectricSheep::Automator::AppProperties->new({
'package' => $package_name,
'mother' => $mother,
});
if( ! defined $app ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'Android::ElectricSheep::Automator::AppProperties->new()'." has failed."); return undef }
if( $verbosity > 1 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : enquired app '".$app->get('packageName')."' successfully and instantiated its AppProperties object.") }
$apps{$package_name} = $app;
} else {
$apps{$package_name} = undef; # <<< lazy instantiate if&when needed
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : registered installed app '${package_name}' successfully (but not instantiated AppProperties).") }
}
}
# done
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : enquired ".scalar(keys %apps)." apps.") }
return \%apps;
}
# does a adb shell dumpsys and reads various things from it
# it may also do a adb shell wm density
# returns 0 on success, 1 on failure
sub enquire {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log;
my $verbosity = $self->verbosity;
# NOTE
# dumpsys package packages
# and
# dumpsys package com.example.xyz
# will yield different things for the package com.example.xyz
# we need to enquire twice, 1 for all the package names
# 2 for the full content of the package info, including activities
# we will dumpsys specifically for that package
my $package;
if( ! exists($params->{'package'}) || ! defined($package=$params->{'package'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'package' (the package name e.g. com.example.calendar) was not specified. If you want ...
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : package '${package}' : called ...") }
# here we could also save to a file on device and then
# fetch it locally. We will do that if there are problems
# getting the dump from STDOUT
my @cmd = ('dumpsys', 'package', $package);
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nsSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
my $content = $res->[1];
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}pkg=Package\{(.+?) (.+?)\}[\r\n]/sm ){
$self->set('packageId', $1);
$self->set('packageName', $2);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'packageName' and 'packageId'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}codePath=(.+?)[\r\n]/sm ){
$self->set('codePath', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'codePath'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}codePath=(.+?)[\r\n]/sm ){
$self->set('codePath', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'codePath'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}resourcePath=(.+?)[\r\n]/sm ){
$self->set('resourcePath', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'resourcePath'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}codePath=(.+?)[\r\n]/sm ){
$self->set('codePath', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'codePath'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}versionCode=(.+?)[\r\n]/sm ){
$self->set('versionCode', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'versionCode'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}versionName=(.+?)[\r\n]/sm ){
$self->set('versionName', $1);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'versionName'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}flags=\[\s*(.+?)\s*\][\r\n]/sm ){
$self->set('flags', [ split(/\s+/, $1) ]);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'flags'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}privateFlags=\[\s*(.+?)\s*\][\r\n]/sm ){
$self->set('privateFlags', [ split(/\s+/, $1) ]);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'privateFlags'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}pkgFlags=\[\s*(.+?)\s*\][\r\n]/sm ){
$self->set('pkgFlags', [ split(/\s+/, $1) ]);
} else { $log->error("${whoami} (via $parent), line ".__LINE__." : package '${package}' : error, failed to find 'pkgFlags'."); return 1 }
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}usesOptionalLibraries\:[\r\n](.+?)[\r\n]\s{4}[^ ]/sm ){
$self->set('usesOptionalLibraries', [ map { $_ =~ s/\s+//g; $_ } split(/[\r\n]+/, $1) ]);
} else { $self->set('usesOptionalLibraries', [] ); } # optional
if( $content =~ /^\s{2}Package.+?\:[\r\n].+?\s{4}usesLibraryFiles\:[\r\n](.+?)[\r\n]\s{4}[^ ]/sm ){
$self->set('usesLibraryFiles', [ map { $_ =~ s/\s+//g; $_ } split(/\[\r\n]+/, $1) ]);
} else { $self->set('usesLibraryFiles', [] ); } # optional
( run in 0.880 second using v1.01-cache-2.11-cpan-39bf76dae61 )