mirror of
https://github.com/waydroid/waydroid.git
synced 2026-01-22 12:58:30 -05:00
Even if we fail at getting appInfo, we will simply repeat the operation in the user_unlocked callback
337 lines
11 KiB
Python
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
|