Files
waydroid/tools/interfaces/IPlatform.py
Alessandro Astone ebec96db06 user_manager: Do not crash when install applications during boot
Even if we fail at getting appInfo, we will simply repeat the
operation in the user_unlocked callback
2023-03-29 09:42:07 +02:00

337 lines
11 KiB
Python

import gbinder
import logging
import time
from tools import helpers
from gi.repository import GLib
import signal
INTERFACE = "lineageos.waydroid.IPlatform"
SERVICE_NAME = "waydroidplatform"
TRANSACTION_getprop = 1
TRANSACTION_setprop = 2
TRANSACTION_getAppsInfo = 3
TRANSACTION_getAppInfo = 4
TRANSACTION_installApp = 5
TRANSACTION_removeApp = 6
TRANSACTION_launchApp = 7
TRANSACTION_getAppName = 8
TRANSACTION_settingsPutString = 9
TRANSACTION_settingsGetString = 10
TRANSACTION_settingsPutInt = 11
TRANSACTION_settingsGetInt = 12
TRANSACTION_launchIntent = 13
class IPlatform:
def __init__(self, remote):
self.client = gbinder.Client(remote, INTERFACE)
def getprop(self, arg1, arg2):
request = self.client.new_request()
request.append_string16(arg1)
request.append_string16(arg2)
reply, status = self.client.transact_sync_reply(
TRANSACTION_getprop, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
rep1 = reader.read_string16()
return rep1
else:
logging.error("Failed with code: {}".format(exception))
return None
def setprop(self, arg1, arg2):
request = self.client.new_request()
request.append_string16(arg1)
request.append_string16(arg2)
reply, status = self.client.transact_sync_reply(
TRANSACTION_setprop, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
return
else:
logging.error("Failed with code: {}".format(exception))
return
def getAppsInfo(self):
request = self.client.new_request()
reply, status = self.client.transact_sync_reply(
TRANSACTION_getAppsInfo, request)
apps_list = []
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
status, apps = reader.read_int32()
for j in range(apps):
status, has_value = reader.read_int32()
if has_value == 1:
appinfo = {
"name": reader.read_string16(),
"packageName": reader.read_string16(),
"action": reader.read_string16(),
"launchIntent": reader.read_string16(),
"componentPackageName": reader.read_string16(),
"componentClassName": reader.read_string16(),
"categories": []
}
status, categories = reader.read_int32()
for i in range(categories):
appinfo["categories"].append(reader.read_string16())
apps_list.append(appinfo)
else:
logging.error("Failed with code: {}".format(exception))
return apps_list
def getAppInfo(self, arg1):
request = self.client.new_request()
request.append_string16(arg1)
reply, status = self.client.transact_sync_reply(
TRANSACTION_getAppInfo, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
status, has_value = reader.read_int32()
if has_value == 1:
appinfo = {
"name": reader.read_string16(),
"packageName": reader.read_string16(),
"action": reader.read_string16(),
"launchIntent": reader.read_string16(),
"componentPackageName": reader.read_string16(),
"componentClassName": reader.read_string16(),
"categories": []
}
status, categories = reader.read_int32()
for i in range(categories):
appinfo["categories"].append(reader.read_string16())
return appinfo
else:
logging.error("Failed with code: {}".format(exception))
return None
def installApp(self, arg1):
request = self.client.new_request()
request.append_string16(arg1)
reply, status = self.client.transact_sync_reply(
TRANSACTION_installApp, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
status, ret = reader.read_int32()
return ret
else:
logging.error("Failed with code: {}".format(exception))
return None
def removeApp(self, arg1):
request = self.client.new_request()
request.append_string16(arg1)
reply, status = self.client.transact_sync_reply(
TRANSACTION_removeApp, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
status, ret = reader.read_int32()
return ret
else:
logging.error("Failed with code: {}".format(exception))
return None
def launchApp(self, arg1):
request = self.client.new_request()
request.append_string16(arg1)
reply, status = self.client.transact_sync_reply(
TRANSACTION_launchApp, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception != 0:
logging.error("Failed with code: {}".format(exception))
def launchIntent(self, arg1, arg2):
request = self.client.new_request()
request.append_string16(arg1)
request.append_string16(arg2)
reply, status = self.client.transact_sync_reply(
TRANSACTION_launchIntent, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
rep1 = reader.read_string16()
return rep1
else:
logging.error("Failed with code: {}".format(exception))
return None
def getAppName(self, arg1):
request = self.client.new_request()
request.append_string16(arg1)
reply, status = self.client.transact_sync_reply(
TRANSACTION_getAppName, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
rep1 = reader.read_string16()
return rep1
else:
logging.error("Failed with code: {}".format(exception))
return None
def settingsPutString(self, arg1, arg2, arg3):
request = self.client.new_request()
request.append_int32(arg1)
request.append_string16(arg2)
request.append_string16(arg3)
reply, status = self.client.transact_sync_reply(
TRANSACTION_settingsPutString, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception != 0:
logging.error("Failed with code: {}".format(exception))
def settingsGetString(self, arg1, arg2):
request = self.client.new_request()
request.append_int32(arg1)
request.append_string16(arg2)
reply, status = self.client.transact_sync_reply(
TRANSACTION_settingsGetString, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
rep1 = reader.read_string16()
return rep1
else:
logging.error("Failed with code: {}".format(exception))
return None
def settingsPutInt(self, arg1, arg2, arg3):
request = self.client.new_request()
request.append_int32(arg1)
request.append_string16(arg2)
request.append_int32(arg3)
reply, status = self.client.transact_sync_reply(
TRANSACTION_settingsPutInt, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception != 0:
logging.error("Failed with code: {}".format(exception))
def settingsGetInt(self, arg1, arg2):
request = self.client.new_request()
request.append_int32(arg1)
request.append_string16(arg2)
reply, status = self.client.transact_sync_reply(
TRANSACTION_settingsGetString, request)
if status:
logging.error("Sending reply failed")
else:
reader = reply.init_reader()
status, exception = reader.read_int32()
if exception == 0:
status, rep1 = reader.read_int32()
return rep1
else:
logging.error("Failed with code: {}".format(exception))
return None
def get_service(args):
helpers.drivers.loadBinderNodes(args)
try:
serviceManager = gbinder.ServiceManager("/dev/" + args.BINDER_DRIVER, args.SERVICE_MANAGER_PROTOCOL, args.BINDER_PROTOCOL)
except TypeError:
serviceManager = gbinder.ServiceManager("/dev/" + args.BINDER_DRIVER)
if not serviceManager.is_present():
logging.info("Waiting for binder Service Manager...")
if not wait_for_manager(serviceManager):
logging.error("Service Manager never appeared")
return None
tries = 1000
remote, status = serviceManager.get_service_sync(SERVICE_NAME)
while(not remote):
if tries > 0:
logging.warning(
"Failed to get service {}, trying again...".format(SERVICE_NAME))
time.sleep(1)
remote, status = serviceManager.get_service_sync(SERVICE_NAME)
tries = tries - 1
else:
return None
return IPlatform(remote)
# Like ServiceManager.wait() but can be interrupted
def wait_for_manager(sm):
mainloop = GLib.MainLoop()
hndl = sm.add_presence_handler(lambda: mainloop.quit() if sm.is_present() else None)
GLib.timeout_add_seconds(60, lambda: mainloop.quit())
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, lambda _: mainloop.quit(), None)
mainloop.run()
sm.remove_handler(hndl)
if not sm.is_present():
return False
return True