diff --git a/app/src/main/java/com/aurora/store/data/installer/ServiceInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/ServiceInstaller.kt index 63b23f1c0..3666b3b91 100644 --- a/app/src/main/java/com/aurora/store/data/installer/ServiceInstaller.kt +++ b/app/src/main/java/com/aurora/store/data/installer/ServiceInstaller.kt @@ -43,11 +43,11 @@ import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean -import java.util.concurrent.atomic.AtomicInteger class ServiceInstaller(context: Context) : InstallerBase(context) { private lateinit var serviceConnection: ServiceConnection + private val executor = ThreadPoolExecutor(0, 1, 30L, TimeUnit.SECONDS, LinkedBlockingQueue()) companion object { const val ACTION_INSTALL_REPLACE_EXISTING = 2 @@ -97,227 +97,256 @@ class ServiceInstaller(context: Context) : InstallerBase(context) { } override fun uninstall(packageName: String) { - val attachedToServiceTimeout = AtomicBoolean(false) - - AuroraApplication.enqueuedInstalls.add(packageName) - - serviceConnection = object : ServiceConnection { - override fun onServiceConnected(name: ComponentName, binder: IBinder) { - attachedToServiceTimeout.set(true) - val service = IPrivilegedService.Stub.asInterface(binder) - - if (service.hasPrivilegedPermissions()) { - Log.i(context.getString(R.string.installer_service_available)) - - val callback = object : IPrivilegedCallback.Stub() { - - override fun handleResult(packageName: String, returnCode: Int) { - + executor.execute { + val readyWithAction = AtomicBoolean(false) + Handler(Looper.getMainLooper()).post { + val serviceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, binder: IBinder) { + if (isAlreadyQueued(packageName)) { + if (::serviceConnection.isInitialized) { + context.unbindService(serviceConnection) + } + readyWithAction.set(true) + return } + AuroraApplication.enqueuedInstalls.add(packageName) + val service = IPrivilegedService.Stub.asInterface(binder) - override fun handleResultX( - packageName: String, - returnCode: Int, - extra: String? - ) { + if (service.hasPrivilegedPermissions()) { + Log.i(context.getString(R.string.installer_service_available)) + + val callback = object : IPrivilegedCallback.Stub() { + + override fun handleResult(packageName: String, returnCode: Int) {} + + override fun handleResultX( + packageName: String, + returnCode: Int, + extra: String? + ) { + removeFromInstallQueue(packageName) + handleCallbackUninstall(packageName, returnCode, extra) + readyWithAction.set(true) + } + } + + try { + service.deletePackageX( + packageName, + 2, + BuildConfig.APPLICATION_ID, + callback + ) + } catch (e: RemoteException) { + Log.e("Failed to connect Aurora Services") + removeFromInstallQueue(packageName) + readyWithAction.set(true) + } + } else { removeFromInstallQueue(packageName) - handleCallbackUninstall(packageName, returnCode, extra) + postError( + packageName, + context.getString(R.string.installer_status_failure), + context.getString(R.string.installer_service_misconfigured) + ) + readyWithAction.set(true) } } - try { - service.deletePackageX( - packageName, - 2, - BuildConfig.APPLICATION_ID, - callback - ) - } catch (e: RemoteException) { - Log.e("Failed to connect Aurora Services") + override fun onServiceDisconnected(name: ComponentName) { removeFromInstallQueue(packageName) + Log.e("Disconnected from Aurora Services") + readyWithAction.set(true) } - } else { - removeFromInstallQueue(packageName) - postError( - packageName, - context.getString(R.string.installer_status_failure), - context.getString(R.string.installer_service_misconfigured) - ) } - } - override fun onServiceDisconnected(name: ComponentName) { - removeFromInstallQueue(packageName) - Log.e("Disconnected from Aurora Services") + val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT) + intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME) + + context.bindService( + intent, + serviceConnection, + Context.BIND_AUTO_CREATE + ) + } + while (!readyWithAction.get()) { + Thread.sleep(1000) } } - - val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT) - intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME) - - context.bindService( - intent, - serviceConnection, - Context.BIND_AUTO_CREATE - ) - - Handler(Looper.getMainLooper()).postDelayed({ - if (!attachedToServiceTimeout.get()) { - removeFromInstallQueue(packageName) - } - }, 25 * 1000) } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) private fun xInstall(packageName: String, uriList: List, fileList: List) { - val attachedToServiceTimeout = AtomicBoolean(false) - - AuroraApplication.enqueuedInstalls.add(packageName) - - serviceConnection = object : ServiceConnection { - override fun onServiceConnected(name: ComponentName, binder: IBinder) { - attachedToServiceTimeout.set(true) - val service = IPrivilegedService.Stub.asInterface(binder) - - if (service.hasPrivilegedPermissions()) { - Log.i(context.getString(R.string.installer_service_available)) - - val callback = object : IPrivilegedCallback.Stub() { - - override fun handleResult(packageName: String, returnCode: Int) { - + executor.execute { + val readyWithAction = AtomicBoolean(false) + Handler(Looper.getMainLooper()).post { + serviceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, binder: IBinder) { + if (isAlreadyQueued(packageName)) { + if (::serviceConnection.isInitialized) { + context.unbindService(serviceConnection) + } + readyWithAction.set(true) + return } + AuroraApplication.enqueuedInstalls.add(packageName) + val service = IPrivilegedService.Stub.asInterface(binder) - override fun handleResultX( - packageName: String, - returnCode: Int, - extra: String? - ) { - removeFromInstallQueue(packageName) - handleCallback(packageName, returnCode, extra) - } - } + if (service.hasPrivilegedPermissions()) { + Log.i(context.getString(R.string.installer_service_available)) + + val callback = object : IPrivilegedCallback.Stub() { + + override fun handleResult(packageName: String, returnCode: Int) {} + + override fun handleResultX( + packageName: String, + returnCode: Int, + extra: String? + ) { + removeFromInstallQueue(packageName) + handleCallback(packageName, returnCode, extra) + readyWithAction.set(true) + } + } - try { - if (service.isMoreMethodImplemented) { try { - service.installSplitPackageMore( - packageName, - uriList, - ACTION_INSTALL_REPLACE_EXISTING, - BuildConfig.APPLICATION_ID, - callback, - fileList - ) - } catch (e: RemoteException) { - removeFromInstallQueue(packageName) - postError(packageName, e.localizedMessage, e.stackTraceToString()) + if (service.isMoreMethodImplemented) { + try { + service.installSplitPackageMore( + packageName, + uriList, + ACTION_INSTALL_REPLACE_EXISTING, + BuildConfig.APPLICATION_ID, + callback, + fileList + ) + } catch (e: RemoteException) { + removeFromInstallQueue(packageName) + postError(packageName, e.localizedMessage, e.stackTraceToString()) + readyWithAction.set(true) + } + } else { + throw Exception("New method not implemented") + } + } catch (th: Throwable) { + th.printStackTrace() + try { + service.installSplitPackageX( + packageName, + uriList, + ACTION_INSTALL_REPLACE_EXISTING, + BuildConfig.APPLICATION_ID, + callback + ) + } catch (e: RemoteException) { + removeFromInstallQueue(packageName) + postError(packageName, e.localizedMessage, e.stackTraceToString()) + readyWithAction.set(true) + } } } else { - throw Exception("New method not implemented") - } - } catch (th: Throwable) { - th.printStackTrace() - try { - service.installSplitPackageX( - packageName, - uriList, - ACTION_INSTALL_REPLACE_EXISTING, - BuildConfig.APPLICATION_ID, - callback - ) - } catch (e: RemoteException) { removeFromInstallQueue(packageName) - postError(packageName, e.localizedMessage, e.stackTraceToString()) + postError( + packageName, + context.getString(R.string.installer_status_failure), + context.getString(R.string.installer_service_misconfigured) + ) + readyWithAction.set(true) } } - } else { - removeFromInstallQueue(packageName) - postError( - packageName, - context.getString(R.string.installer_status_failure), - context.getString(R.string.installer_service_misconfigured) - ) + + override fun onServiceDisconnected(name: ComponentName) { + removeFromInstallQueue(packageName) + readyWithAction.set(true) + Log.e("Disconnected from Aurora Services") + } } - } - override fun onServiceDisconnected(name: ComponentName) { - removeFromInstallQueue(packageName) - Log.e("Disconnected from Aurora Services") + val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT) + intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME) + + context.bindService( + intent, + serviceConnection, + Context.BIND_AUTO_CREATE + ) } + while (!readyWithAction.get()) { + Thread.sleep(1000) + } + Log.i("Services Callback : install wait done") } - - val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT) - intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME) - - context.bindService( - intent, - serviceConnection, - Context.BIND_AUTO_CREATE - ) - Handler(Looper.getMainLooper()).postDelayed({ - if (!attachedToServiceTimeout.get()) { - removeFromInstallQueue(packageName) - } - }, 25 * 1000) } private fun handleCallbackUninstall(packageName: String, returnCode: Int, extra: String?) { Log.i("Services Callback : $packageName $returnCode $extra") - when (returnCode) { - PackageInstaller.STATUS_SUCCESS -> { - EventBus.getDefault().post( - BusEvent.UninstallEvent( - packageName, - context.getString(R.string.installer_status_success) + try { + when (returnCode) { + PackageInstaller.STATUS_SUCCESS -> { + EventBus.getDefault().post( + BusEvent.UninstallEvent( + packageName, + context.getString(R.string.installer_status_success) + ) + ) + } + else -> { + val error = AppInstaller.getErrorString( + context, + returnCode ) - ) - } - else -> { - val error = AppInstaller.getErrorString( - context, - returnCode - ) - postError(packageName, error, extra) + postError(packageName, error, extra) + } } - } - if (::serviceConnection.isInitialized) { - context.unbindService(serviceConnection) + if (::serviceConnection.isInitialized) { + context.unbindService(serviceConnection) + } + } catch (th: Throwable) { + th.printStackTrace() } } private fun handleCallback(packageName: String, returnCode: Int, extra: String?) { Log.i("Services Callback : $packageName $returnCode $extra") - when (returnCode) { - PackageInstaller.STATUS_SUCCESS -> { - EventBus.getDefault().post( - InstallerEvent.Success( - packageName, - context.getString(R.string.installer_status_success) + try { + when (returnCode) { + PackageInstaller.STATUS_SUCCESS -> { + EventBus.getDefault().post( + InstallerEvent.Success( + packageName, + context.getString(R.string.installer_status_success) + ) + ) + } + else -> { + val error = AppInstaller.getErrorString( + context, + returnCode ) - ) - } - else -> { - val error = AppInstaller.getErrorString( - context, - returnCode - ) - postError(packageName, error, extra) + postError(packageName, error, extra) + } } - } - if (::serviceConnection.isInitialized) { - context.unbindService(serviceConnection) + if (::serviceConnection.isInitialized) { + context.unbindService(serviceConnection) + } + } catch (th: Throwable) { + th.printStackTrace() } } override fun postError(packageName: String, error: String?, extra: String?) { - super.postError(packageName, error, extra) - if (::serviceConnection.isInitialized) { - context.unbindService(serviceConnection) + try { + super.postError(packageName, error, extra) + if (::serviceConnection.isInitialized) { + context.unbindService(serviceConnection) + } + } catch (th: Throwable) { + th.printStackTrace() } }