1 package com.android.onboarding.tasks.crossApp 2 3 import android.app.Service 4 import android.content.Intent 5 import android.os.IBinder 6 import android.os.Parcelable 7 import android.os.PersistableBundle 8 import com.android.onboarding.tasks.OnboardingTaskContract 9 import com.android.onboarding.tasks.OnboardingTaskManager 10 import com.android.onboarding.tasks.OnboardingTaskToken 11 12 /** 13 * [AbstractOnboardingTaskManagerService] is a base class for services that manage onboarding tasks. 14 * Subclasses of [AbstractOnboardingTaskManagerService] must implement the [taskManager] property to 15 * provide an implementation of AbstractOnboardingTaskManager. 16 * 17 * This service allows clients to interact with the onboarding task manager by binding to it and 18 * invoking tasks. 19 */ 20 abstract class AbstractOnboardingTaskManagerService : Service() { 21 22 protected abstract val taskManager: OnboardingTaskManager 23 onBindnull24 override fun onBind(intent: Intent): IBinder { 25 return object : IOnboardingTaskManagerService.Stub() { 26 27 override fun runTask(bundle: PersistableBundle): OnboardingTaskToken { 28 val contractClass = getContractClass(bundle) ?: return OnboardingTaskToken.INVALID 29 val contractInstance = 30 OnboardingTaskContract.tryCreateContractInstance(contractClass) 31 ?: return OnboardingTaskToken.INVALID 32 val contractArgument = contractInstance.extractArgs(bundle) 33 34 return taskManager.runTask(contractInstance, contractArgument) 35 } 36 } 37 } 38 39 /** 40 * Parses the contract class name from the given [PersistableBundle]. This function extracts the 41 * contract class name from the provided bundle and attempts to find the corresponding contract 42 * class in the task manager's mapping. If found, it returns the class; otherwise, it returns 43 * null. 44 */ getContractClassnull45 private fun getContractClass( 46 bundle: PersistableBundle 47 ): Class<OnboardingTaskContract<Any?, Parcelable?>>? { 48 val contractClassName = bundle.getString(OnboardingTaskContract.EXTRA_CONTRACT_CLASS) 49 val matchingContractClass = 50 taskManager 51 .getContractAndTaskMap() 52 .filterKeys { it.name == contractClassName } 53 .keys 54 .firstOrNull() 55 if (matchingContractClass != null) { 56 @Suppress("UNCHECKED_CAST") 57 // Because we don't send the input/output types via IPC. 58 return matchingContractClass as Class<OnboardingTaskContract<Any?, Parcelable?>> 59 } else { 60 throw IllegalArgumentException("Contract class not found: $contractClassName") 61 } 62 } 63 64 companion object { 65 private const val TAG: String = "OTMService" 66 } 67 } 68