From 48607f2716408958da95ca174ae0668a314a675c Mon Sep 17 00:00:00 2001 From: Jonathan Klee Date: Mon, 13 Nov 2023 11:13:26 +0100 Subject: [PATCH] Port SplitInstallService as is --- vending-app/build.gradle | 5 +- vending-app/src/main/AndroidManifest.xml | 8 ++ .../protocol/ISplitInstallService.aidl | 29 +++++ .../ISplitInstallServiceCallback.aidl | 37 +++++++ .../e/apps/ISplitInstallService.aidl | 11 ++ .../android/vending/SplitInstallService.kt | 100 ++++++++++++++++++ .../splitinstall/SplitInstallErrorCode.kt | 13 +++ .../vending/splitinstall/SplitInstaller.kt | 30 ++++++ .../installer/AppLoungeSplitInstaller.kt | 73 +++++++++++++ 9 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 vending-app/src/main/aidl/com/google/android/play/core/splitinstall/protocol/ISplitInstallService.aidl create mode 100644 vending-app/src/main/aidl/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceCallback.aidl create mode 100644 vending-app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl create mode 100644 vending-app/src/main/java/com/android/vending/SplitInstallService.kt create mode 100644 vending-app/src/main/java/com/android/vending/splitinstall/SplitInstallErrorCode.kt create mode 100644 vending-app/src/main/java/com/android/vending/splitinstall/SplitInstaller.kt create mode 100644 vending-app/src/main/java/com/android/vending/splitinstall/installer/AppLoungeSplitInstaller.kt diff --git a/vending-app/build.gradle b/vending-app/build.gradle index 12efd905a..2ccb1cbe6 100644 --- a/vending-app/build.gradle +++ b/vending-app/build.gradle @@ -6,6 +6,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'com.squareup.wire' +apply plugin: 'org.jetbrains.kotlin.android' android { namespace "com.android.vending" @@ -64,6 +65,8 @@ dependencies { implementation "com.squareup.wire:wire-runtime:$wireVersion" implementation "com.android.volley:volley:$volleyVersion" + implementation 'androidx.core:core-ktx:1.0.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" } wire { @@ -80,4 +83,4 @@ android.applicationVariants.all { variant -> variant.outputs.each { output -> output.outputFileName = variant.applicationId + "-" + variant.versionCode + variant.versionName.substring(vendingAppVersionName.length()) + ".apk" } -} \ No newline at end of file +} diff --git a/vending-app/src/main/AndroidManifest.xml b/vending-app/src/main/AndroidManifest.xml index 4763d05df..dc7fce16e 100644 --- a/vending-app/src/main/AndroidManifest.xml +++ b/vending-app/src/main/AndroidManifest.xml @@ -53,6 +53,14 @@ + + + + + + list, in Bundle bundle, in ISplitInstallServiceCallback callback); + + // Method not identified yet + void c(String str); + + // Method not identified yet + void d(String str); + + // Method not identified yet + void e(String str); + + void getSessionStates(String str, in ISplitInstallServiceCallback callback); + +} \ No newline at end of file diff --git a/vending-app/src/main/aidl/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceCallback.aidl b/vending-app/src/main/aidl/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceCallback.aidl new file mode 100644 index 000000000..371ab555f --- /dev/null +++ b/vending-app/src/main/aidl/com/google/android/play/core/splitinstall/protocol/ISplitInstallServiceCallback.aidl @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2016 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.play.core.splitinstall.protocol; + +import android.os.Bundle; + +interface ISplitInstallServiceCallback { + + // Method not identified yet + void a(); + + void onStartInstall(int i); + + void onCompleteInstall(int i); + + void onCancelInstall(int i); + + void onGetSession(int i); + + void onError(int i); + + void onGetSessionStates(in List list); + + void onDeferredUninstall(in Bundle bundle); + + void onDeferredInstall(in Bundle bundle); + + void onGetSplitsForAppUpdate(int i, in Bundle bundle); + + void onCompleteInstallForAppUpdate(); + + void onDeferredLanguageInstall(int i); +} \ No newline at end of file diff --git a/vending-app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl b/vending-app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl new file mode 100644 index 000000000..dd57f65d2 --- /dev/null +++ b/vending-app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2016 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package foundation.e.apps; + +interface ISplitInstallService { + void installSplitModule(String packageName, String moduleName); +} diff --git a/vending-app/src/main/java/com/android/vending/SplitInstallService.kt b/vending-app/src/main/java/com/android/vending/SplitInstallService.kt new file mode 100644 index 000000000..05570e37f --- /dev/null +++ b/vending-app/src/main/java/com/android/vending/SplitInstallService.kt @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2023 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.vending + +import android.app.Service +import android.content.Intent +import android.os.Bundle +import android.os.IBinder +import android.os.Parcel +import android.util.Log +import com.android.vending.splitinstall.SplitInstaller +import com.android.vending.splitinstall.SplitInstallerFactory +import com.android.vending.splitinstall.SplitInstallerType +import com.google.android.play.core.splitinstall.protocol.ISplitInstallService +import com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback + +class SplitInstallService : Service() { + + companion object { + const val TAG = "SplitInstallService" + } + + private lateinit var mSplitInstaller: SplitInstaller + + override fun onCreate() { + super.onCreate() + + mSplitInstaller = SplitInstallerFactory.createSplitInstaller( + applicationContext, + SplitInstallerType.AppLoungeSplitInstaller + ) + + mSplitInstaller.initialize() + } + + override fun onBind(p0: Intent?): IBinder { + return mServiceInterface + } + + override fun onDestroy() { + super.onDestroy() + mSplitInstaller.destroy() + } + + private var mServiceInterface = object : ISplitInstallService.Stub() { + + override fun a() { + Log.d(TAG, "a") + } + + override fun startInstall( + packageName: String, + list: List, + bundle: Bundle, + callback: ISplitInstallServiceCallback + ) { + for (element in list) { + + val apk = element.getString("module_name") ?: element.getString("language") + apk?.let { + mSplitInstaller.install(packageName, apk) + callback.onStartInstall(0) + } ?: logBundleError(element) + } + } + + private fun logBundleError(bundle: Bundle) { + for (entry in bundle.keySet()) { + Log.e(TAG, "Unknown bundle entry: $entry. Value is ${bundle.get(entry)}") + } + } + + override fun c(str: String?) { + Log.d(TAG, "c") + } + + override fun d(str: String?) { + Log.d(TAG, "d") + } + + override fun e(str: String?) { + Log.d(TAG, "e") + } + + override fun getSessionStates(str: String, callback: ISplitInstallServiceCallback) { + Log.d(TAG, "onGetSessionStates") + callback.onGetSessionStates(arrayListOf()) + } + + override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean { + if (super.onTransact(code, data, reply, flags)) return true + Log.d(TAG, "onTransact [unknown]: $code, $data, $flags") + return false + } + } +} diff --git a/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstallErrorCode.kt b/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstallErrorCode.kt new file mode 100644 index 000000000..24edcda6b --- /dev/null +++ b/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstallErrorCode.kt @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2023 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.vending.splitinstall + +interface SplitInstallErrorCode { + companion object { + const val API_NOT_AVAILABLE = -5 + } +} diff --git a/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstaller.kt b/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstaller.kt new file mode 100644 index 000000000..91c531db2 --- /dev/null +++ b/vending-app/src/main/java/com/android/vending/splitinstall/SplitInstaller.kt @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2023 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.vending.splitinstall + +import android.content.Context +import com.android.vending.splitinstall.installer.AppLoungeSplitInstaller + +interface SplitInstaller { + fun initialize() + fun install(packageName: String, moduleName: String) + fun destroy() +} + +enum class SplitInstallerType { + AppLoungeSplitInstaller +} + +object SplitInstallerFactory { + fun createSplitInstaller(context: Context, type: SplitInstallerType): SplitInstaller { + when (type) { + SplitInstallerType.AppLoungeSplitInstaller -> + return AppLoungeSplitInstaller(context) + else -> throw IllegalArgumentException("Unknown SplitInstallerType") + } + } +} diff --git a/vending-app/src/main/java/com/android/vending/splitinstall/installer/AppLoungeSplitInstaller.kt b/vending-app/src/main/java/com/android/vending/splitinstall/installer/AppLoungeSplitInstaller.kt new file mode 100644 index 000000000..1c01af1ee --- /dev/null +++ b/vending-app/src/main/java/com/android/vending/splitinstall/installer/AppLoungeSplitInstaller.kt @@ -0,0 +1,73 @@ +/* + * SPDX-FileCopyrightText: 2023 microG Project Team + * SPDX-FileCopyrightText: 2023 E FOUNDATION + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.android.vending.splitinstall.installer + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.IBinder +import com.android.vending.splitinstall.SplitInstaller +import foundation.e.apps.ISplitInstallService + +class AppLoungeSplitInstaller( + private val context: Context +) : SplitInstaller { + + companion object { + private val ON_DEMAND_DELIVERY_SERVICE_COMPONENT = + ComponentName( + "foundation.e.apps", + "foundation.e.apps.install.splitinstall.SplitInstallService" + ) + } + + private var service: ISplitInstallService? = null + private val moduleList = ArrayList() + + private val serviceConnection = object : ServiceConnection { + override fun onServiceConnected(componentName: ComponentName, binder: IBinder) { + service = ISplitInstallService.Stub.asInterface(binder) + installWaitingModules() + } + + override fun onServiceDisconnected(componentName: ComponentName) { + service = null + } + } + + override fun initialize() { + val intent = Intent().apply { + component = ON_DEMAND_DELIVERY_SERVICE_COMPONENT + } + + context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) + } + + override fun destroy() { + context.unbindService(serviceConnection) + } + + override fun install(packageName: String, moduleName: String) { + if (service == null) { + moduleList.add(InstallModule(packageName, moduleName)) + } + + service?.installSplitModule(packageName, moduleName) + } + + private fun installWaitingModules() { + val iterator = moduleList.iterator() + while (iterator.hasNext()) { + val module = iterator.next() + service?.installSplitModule(module.packageName, module.moduleName) + iterator.remove() + } + } + + private data class InstallModule(val packageName: String, val moduleName: String) +} -- GitLab