diff --git a/lib/Android.bp b/lib/Android.bp index 5d818e293ec6580e80e68a908ecae2a82b7adbe5..3e9da4d4912dacaff18fc7cb4be5a91974179269 100644 --- a/lib/Android.bp +++ b/lib/Android.bp @@ -2,12 +2,12 @@ java_library_static { name: "splitinstall-lib", sdk_version: "current", srcs: [ - "java/**/*.java", - "aidl/**/*.aidl", + "java/**/*.java", + "aidl/**/*.aidl", ], aidl: { - local_include_dirs: [ - "aidl/", - ] + local_include_dirs: [ + "aidl/", + ] }, } diff --git a/lib/aidl/foundation/e/splitinstall/ISplitInstallService.aidl b/lib/aidl/foundation/e/splitinstall/ISplitInstallService.aidl index 2ed10cd41ccf2f799bc0128d897f38963c434133..1ad87267955a19a8749b96cf49e58b26cae7f659 100644 --- a/lib/aidl/foundation/e/splitinstall/ISplitInstallService.aidl +++ b/lib/aidl/foundation/e/splitinstall/ISplitInstallService.aidl @@ -1,5 +1,23 @@ +/* + * Copyright ECORP SAS 2022-2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package foundation.e.splitinstall; +import foundation.e.splitinstall.ISplitInstallSystemServiceCallback; + /** * Interface towards the SplitInstallService. */ @@ -12,5 +30,5 @@ interface ISplitInstallService { * for. * @param modulePath: the path of the split module apk we want to install. */ - oneway void installSplitModule(in String packageName, in String modulePath); + oneway void installSplitModule(in String packageName, in String modulePath, in ISplitInstallSystemServiceCallback callback); } diff --git a/lib/aidl/foundation/e/splitinstall/ISplitInstallSystemServiceCallback.aidl b/lib/aidl/foundation/e/splitinstall/ISplitInstallSystemServiceCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..d0c88f9aa0728c35bd9ed461ac03618db2361a3d --- /dev/null +++ b/lib/aidl/foundation/e/splitinstall/ISplitInstallSystemServiceCallback.aidl @@ -0,0 +1,26 @@ +/* + * Copyright ECORP SAS 2022-2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package foundation.e.splitinstall; + +import android.os.Bundle; + +interface ISplitInstallSystemServiceCallback { + void onStartInstall(int sessionId); + void onInstalled(int sessionId); + void onError(int errorCode); +} + diff --git a/service/Android.bp b/service/Android.bp index 309072a4f071b275fed81432f8e846f5a10eec24..22577002bba5d1198e427e06d9b1ce8cc0f2ac7b 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -4,10 +4,11 @@ android_app { srcs: [ "java/**/*.kt", + "kotlin/**/*.kt", ], - static_libs: [ - "splitinstall-lib", + static_libs: [ + "splitinstall-lib", ], privileged: true, diff --git a/service/java/foundation/e/splitinstall/service/SplitInstallBinder.kt b/service/java/foundation/e/splitinstall/service/SplitInstallBinder.kt index 9ddd91062c58673efd92797e234fd6bf93975da4..7b955769ad8f8cac4ddce09a090dc1964d23bdc8 100644 --- a/service/java/foundation/e/splitinstall/service/SplitInstallBinder.kt +++ b/service/java/foundation/e/splitinstall/service/SplitInstallBinder.kt @@ -1,5 +1,5 @@ /* - * Copyright ECORP SAS 2022 + * Copyright ECORP SAS 2022-2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,45 +22,79 @@ import android.content.Intent import android.content.pm.PackageInstaller import android.util.Log import foundation.e.splitinstall.ISplitInstallService +import foundation.e.splitinstall.ISplitInstallSystemServiceCallback import java.io.File +import android.os.Handler +import android.os.Bundle class SplitInstallBinder( - val applicationContext: Context + val applicationContext: Context, + val handler: Handler ) : ISplitInstallService.Stub() { + private var packageName: String? = null + private var modulePath: String? = null + + private val sessionCallbacks = HashMap() + companion object { const val TAG = SplitInstallService.TAG } - override fun installSplitModule(packageName: String, modulePath: String) { + override fun installSplitModule(packageName: String, modulePath: String, callback: ISplitInstallSystemServiceCallback) { - Log.i(TAG, "installing $modulePath") - val packageManager = applicationContext.packageManager - val packageInstaller = packageManager.packageInstaller - val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_INHERIT_EXISTING) - .apply { - setAppPackageName(packageName) - setDontKillApp(true) - } + this.packageName = packageName + this.modulePath = modulePath + + handler.post { + Log.i(TAG, "about to install $modulePath") + val packageManager = applicationContext.packageManager + val packageInstaller = packageManager.packageInstaller + val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_INHERIT_EXISTING) + .apply { + setAppPackageName(packageName) + setDontKillApp(true) + } + + val sessionId = packageInstaller.createSession(params) + val session = packageInstaller.openSession(sessionId) + + sessionCallbacks[modulePath] = object : PackageInstaller.SessionCallback() { + override fun onActiveChanged(sessionId: Int, active: Boolean) { + callback.onStartInstall(0) + } + + override fun onBadgingChanged(sessionId: Int) { } + + override fun onCreated(sessionId: Int) { } + + override fun onFinished(sessionId: Int, success: Boolean) { + callback.onInstalled(0) + applicationContext.packageManager.packageInstaller.unregisterSessionCallback(this) + } + + override fun onProgressChanged(sessionId: Int, progress: Float) { } + } + + packageInstaller.registerSessionCallback(sessionCallbacks[modulePath]) - val sessionId = packageInstaller.createSession(params) - val session = packageInstaller.openSession(sessionId) + try { + syncFile(session, File(modulePath)) - try { - syncFile(session, File(modulePath)) + val callbackIntent = Intent(applicationContext, SplitInstallBroadcastReceiver::class.java) + callbackIntent.action = SplitInstallBroadcastReceiver.MODULE_INSTALLED_INTENT_ACTION - val callbackIntent = Intent(applicationContext, SplitInstallBroadcastReceiver::class.java) - callbackIntent.action = SplitInstallBroadcastReceiver.MODULE_INSTALLED_INTENT_ACTION + val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + val pendingIntent = + PendingIntent.getBroadcast(applicationContext, sessionId, callbackIntent, flags) - val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE - val servicePendingIntent = - PendingIntent.getBroadcast(applicationContext, sessionId, callbackIntent, flags) - session.commit(servicePendingIntent.intentSender) - } catch (e: Exception) { - session.abandon() - throw e - } finally { - session.close() + session.commit(pendingIntent.intentSender) + } catch (e: Exception) { + session.abandon() + throw e + } finally { + session.close() + } } } @@ -72,4 +106,4 @@ class SplitInstallBinder( inputStream.close() outputStream.close() } -} \ No newline at end of file +} diff --git a/service/java/foundation/e/splitinstall/service/SplitInstallBroadcastReceiver.kt b/service/java/foundation/e/splitinstall/service/SplitInstallBroadcastReceiver.kt index 16bdacb2dcd0febaecdd43cef0f745192b5539c9..72081f5579deddece36d08193e6cc5b7afdd716f 100644 --- a/service/java/foundation/e/splitinstall/service/SplitInstallBroadcastReceiver.kt +++ b/service/java/foundation/e/splitinstall/service/SplitInstallBroadcastReceiver.kt @@ -53,4 +53,4 @@ class SplitInstallBroadcastReceiver : BroadcastReceiver() { val updatedPackage = extras.get(PM_INSTALL_EXTRA_PACKAGE_NAME_KEY) Log.i(TAG, "Package updated successfully: $updatedPackage") } -} \ No newline at end of file +} diff --git a/service/java/foundation/e/splitinstall/service/SplitInstallService.kt b/service/java/foundation/e/splitinstall/service/SplitInstallService.kt index 9b4233c7633e8f19cd8c0c598ebf470409ae0f79..6a8bde4002a61da1dd4de60646d862a54a8e26a2 100644 --- a/service/java/foundation/e/splitinstall/service/SplitInstallService.kt +++ b/service/java/foundation/e/splitinstall/service/SplitInstallService.kt @@ -1,5 +1,5 @@ /* - * Copyright ECORP SAS 2022 + * Copyright ECORP SAS 2022-2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,8 @@ import android.os.Build import android.os.IBinder import android.util.Log import foundation.e.splitinstall.service.R +import android.os.Handler; +import android.os.HandlerThread; import java.io.File @@ -38,7 +40,15 @@ class SplitInstallService : Service() { const val TAG = "SplitInstallSysService" } + override fun onCreate() { + super.onCreate() + } + override fun onBind(intent: Intent?): IBinder? { - return SplitInstallBinder(applicationContext) + val thread = HandlerThread("InstallThread") + thread.start() + val handler = Handler(thread.getLooper()) + + return SplitInstallBinder(applicationContext, handler) } }