Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
577 lines (443 sloc) 14.7 KB
#
# Collective Knowledge (APK entries)
#
# See CK LICENSE.txt for licensing details
# See CK COPYRIGHT.txt for copyright details
#
# Developer: cTuning foundation, admin@cTuning.org, http://cTuning.org
#
cfg={} # Will be updated by CK (meta description of this module)
work={} # Will be updated by CK (temporal data)
ck=None # Will be updated by CK (initialized CK kernel)
# Local settings
import os
##############################################################################
# Initialize module
def init(i):
"""
Input: {}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
return {'return':0}
##############################################################################
# detect installed APKs
def detect(i):
"""
Input: {
(data_uoa) or (name) - get params only for this APK
(target_os) - target Android OS (ck search os --tags=android) (default = android-32)
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
o=i.get('out','')
oo=''
if o=='con': oo='con'
hos=i.get('host_os','')
tos=i.get('target_os','')
tdid=i.get('device_id','')
target=i.get('target','')
if target=='' and tos=='':
tos='android-32'
ii={'action':'shell',
'module_uoa':cfg['module_deps']['os'],
'host_os':hos,
'target_os':tos,
'device_id':tdid,
'target':target,
'split_to_list':'yes',
'should_be_remote':'yes',
'cmd':'pm list packages'}
r=ck.access(ii)
if r['return']>0: return r
tosd=r['target_os_dict']
lst=r['stdout_lst']
params={}
name=i.get('name','')
if name=='':
name=i.get('data_uoa','')
iapk=0
for package in sorted(lst):
if package.startswith('package:'):
package=package[8:]
if (name!='' and package!=name) or package=='':
continue
iapk+=1
if o=='con':
ck.out(package)
params[package]={}
# Get parameters
ii={'action':'shell',
'module_uoa':cfg['module_deps']['os'],
'host_os':hos,
'target_os':tos,
'device_id':tdid,
'target':target,
'split_to_list':'yes',
'should_be_remote':'yes',
'cmd':'dumpsys package '+package}
r=ck.access(ii)
if r['return']>0: return r
ll=r['stdout_lst']
for q in ll:
j=q.find('=')
if j>0:
j1=q.rfind(' ', 0, j)
k=q[j1+1:j]
v=q[j+1:]
j2=v.find(' targetSdk=')
if j2>0:
vv=v[j2+11:]
v=v[:j2]
kk='targetSdk'
params[package][kk]=vv
params[package][k]=v
if name!='':
if iapk==0:
return {'return':16, 'error':'APK was not found on the target device', 'target_os_dict':tosd}
if o=='con':
ck.out('')
ck.out('Parameters:')
ck.out('')
for k in sorted(params[name]):
v=params[name][k]
ck.out(' '+k+' = '+v)
return {'return':0, 'params':params, 'target_os_dict':tosd}
##############################################################################
# check APK
def install(i):
"""
Input: {
(host_os)
(target_os)
(device_id)
name or data_uoa - APK name
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
import os
o=i.get('out','')
oo=''
if o=='con': oo=o
name=i.get('name','')
if name=='':
name=i.get('data_uoa','')
if name=='':
return {'return':1, 'error':'APK "name" is not defined'}
hos=i.get('host_os','')
tos=i.get('target_os','')
tdid=i.get('device_id','')
target=i.get('target','')
if target=='' and tos=='':
tos='android19-arm'
i['target_os']=tos
# return {'return':1, 'error':'"target_os" or "target" is not specified'}
xtdid=''
if tdid!='': xtdid=' -s '+tdid
rr={'return':0}
# Detect if APK is installed
r=detect(i)
if r['return']>0 and r['return']!=16: return r
if r['return']==0:
rr['params']=r['params']
if r['return']==16:
# APK is not installed
tosd=r['target_os_dict']
abi=tosd.get('abi','')
if o=='con':
ck.out('Searching APK for "'+name+'" and ABI="'+abi+'" ...')
# Check if available in the CK
r=ck.access({'action':'load',
'module_uoa':work['self_module_uid'],
'data_uoa':name})
if r['return']>0 and r['return']!=16: return r
found=False
if r['return']==0:
p=r['path']
d=r['dict']
aname=''
for apk in d.get('apks',[]):
if abi in apk.get('abis',[]):
aname=apk.get('apk_name','')
break
# If the preferred abi didn't match but is 64-bit,
# look for a 32-bit binary (worst case won't install)
alt_abi = ''
if abi in ['arm64-v8a','arm64']:
alt_abi='armeabi'
elif abi=='x86-64':
alt_abi='x86'
if alt_abi!='':
for apk in d.get('apks',[]):
if alt_abi in apk.get('abis',[]):
aname=apk.get('apk_name','')
break
if aname!='':
pp=os.path.join(p, aname)
if os.path.isfile(pp):
# Trying to install
if o=='con':
ck.out(' APK found ('+aname+') - trying to install ...')
if alt_abi!='':
ck.out(' First choice ABI "'+abi+'" not found, using "'+alt_abi+'"')
ii={'action':'shell',
'module_uoa':cfg['module_deps']['os'],
'host_os':hos,
'target_os':hos,
'cmd':'adb '+xtdid+' install -r -d '+pp,
'out':oo}
r=ck.access(ii)
if r['return']>0: return r
rc=r['return_code']
if rc>0:
return {'return':1, 'error':'command may have failed (return code='+str(rc)+')'}
# Detecting params
r=detect(i)
if r['return']>0 and r['return']!=16: return r
if r['return']==0:
rr['params']=r['params']
found=True
# If not found
if not found:
if o=='con':
ck.out('')
ck.out('APK "'+name+'" with abi "'+abi+'" was not found in CK.')
ck.out('You can download it and then register in the CK via')
ck.out(' $ ck add apk:{APK name} --path={full path to downloaded APK}')
ck.out('')
return {'return':16, 'error':'APK is not installed on target device and was not found in CK'}
return rr
##############################################################################
# add apk
def add(i):
"""
Input: {
(data_uoa) - CK entry to add APK (should be official APK name, i.e. openscience.crowdsource.experiments)
(repo_uoa) - repo where to add APK
(abi) - list of ABI separated by comma (default=armeabi,armeabi-v7a,arm64-v8a)
(version) - version
(versioncode) - versioncode
(path) - path to APK on local host (apk_name will be automatically detected)
(apk_name) - force APK name
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
import os
import shutil
o=i.get('out','')
# Check APK name
apk_name=i.get('apk_name','')
path=i.get('path','')
if path!='':
if not os.path.isfile(path):
return {'return':1, 'error':'APK is not found ('+path+')'}
if apk_name=='':
apk_name=os.path.basename(path)
# Check ABI
abi=i.get('abi','')
if abi=='':
r=ck.inp({'text':'Enter list of ABI separated by comma or Enter for "armeabi,armeabi-v7a,arm64-v8a"): '})
if r['return']>0: return r
abi=r['string'].strip()
if abi=='':
abi='armeabi,armeabi-v7a,arm64-v8a'
if abi=='':
return {'return':1, 'error':'"abi" is not specified'}
abis=abi.split(',')
# Version
version=i.get('version','')
if version=='':
r=ck.inp({'text':'Enter APK version: '})
if r['return']>0: return r
version=r['string'].strip()
if version=='':
return {'return':1, 'error':'"version" is not specified'}
# VersionCode
versioncode=i.get('versioncode','')
# Check CK entry name
duoa=i.get('data_uoa','')
ruoa=i.get('repo_uoa','')
if duoa=='':
r=ck.inp({'text':'Enter CK entry name (must be official APK name): '})
if r['return']>0: return r
duoa=r['string'].strip()
# Check if already exists
r=ck.access({'action':'load',
'module_uoa':work['self_module_uid'],
'data_uoa':duoa})
if r['return']>0 and r['return']!=16: return r
if r['return']==0:
ruoa=r['repo_uid']
pp=r['path']
dd=r['dict']
else:
r=ck.access({'action':'add',
'module_uoa':work['self_module_uid'],
'common_func':'yes',
'data_uoa':duoa,
'repo_uoa':ruoa})
if r['return']>0: return r
pp=r['path']
dd={}
# Create dirs and copy files
p2=os.path.join(pp,apk_name)
shutil.copyfile(path, p2)
# Update dict
if 'apks' not in dd: dd['apks']=[]
dd['apks'].append({'abis':abis,
'apk_name':apk_name,
'version':version,
'versioncode':versioncode})
r=ck.access({'action':'update',
'module_uoa':work['self_module_uid'],
'data_uoa':duoa,
'repo_uoa':ruoa,
'dict':dd,
'sort_keys':'yes',
'substitute':'yes',
'ignore_update':'yes'})
if r['return']>0: return r
p=r['path']
if o=='con':
ck.out('')
ck.out('APK successfully registered in the CK ('+p+')')
return r
##############################################################################
# uninstall APK
def uninstall(i):
"""
Input: {
(data_uoa) or (name) - get params only for this APK
(target_os) - target Android OS (ck search os --tags=android) (default = android-32)
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
# First check if exists
o=i.get('out','')
oo=''
if o=='con':
i['out']=''
oo=o
r=detect(i)
if r['return']>0: return r
hos=i.get('host_os','')
tos=i.get('target_os','')
tdid=i.get('device_id','')
target=i.get('target','')
xtdid=''
if tdid!='': xtdid=' -s '+tdid
if target=='' and tos=='':
tos='android-32'
name=i.get('name','')
if name=='':
name=i.get('data_uoa','')
ii={'action':'shell',
'module_uoa':cfg['module_deps']['os'],
'host_os':hos,
'target_os':hos,
'out':oo,
'cmd':'adb '+xtdid+' uninstall '+name}
r=ck.access(ii)
if r['return']>0: return r
rc=r['return_code']
if rc>0:
return {'return':1, 'error':'command may have failed (return code='+str(rc)+')'}
return r
##############################################################################
# List the apks installed on a target device
def list_installed(i):
"""
Input: {
(device_id)
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
"""
# First check if exists
o=i.get('out','')
oo=''
if o=='con':
i['out']=''
oo=o
# r=detect(i)
# if r['return']>0: return r
hos=i.get('host_os','')
tos=i.get('target_os','')
tdid=i.get('device_id','')
target=i.get('target','')
xtdid=''
if tdid!='': xtdid=' -s '+tdid
if target=='' and tos=='':
tos='android-32'
ii={'action':'shell',
'module_uoa':cfg['module_deps']['os'],
'host_os':hos,
'target_os':hos,
'out':oo,
'cmd':'adb '+xtdid+' shell pm list packages -f'}
r=ck.access(ii)
if r['return']>0: return r
rc=r['return_code']
if rc>0:
return {'return':1, 'error':'command may have failed (return code='+str(rc)+')'}
output = r['stdout']
# Output format is "package:[path]=[package]"
packages = [ a.split('=')[1] for a in output.split('\n') if '=' in a ]
if o=='con':
for p in packages:
ck.out(p)
return { 'return':0, 'lst':packages}
##############################################################################
# Uninstall all applications on a target device
def uninstall_all(i):
"""
Input: {
(device_id)
}
Output: {
return - return code = 0, if successful
> 0, if error
(error) - error text if return > 0
}
Uninstall all applications on the device specified.
"""
# First check if exists
o=i.get('out','')
oo=''
if o=='con':
i['out']=''
oo=o
hos=i.get('host_os','')
tos=i.get('target_os','')
tdid=i.get('device_id','')
target=i.get('target','')
r=list_installed({'device_id':tdid})
if r['return']>0: return r
for apk in r['lst']:
ii={'data_uoa':apk,
'device_id':tdid}
uninstall(ii)
if r['return']>0: return r
return {'return':0}