1 package com.android.managedprovisioning.contracts
2 
3 import android.content.Context
4 import android.content.Intent
5 import com.android.managedprovisioning.ManagedProvisioningScreens.DOWNLOAD_ROLE_HOLDER
6 import com.android.managedprovisioning.ScreenManager
7 import com.android.managedprovisioning.annotations.LegacyApi
8 import com.android.managedprovisioning.contracts.Checksum.SignatureChecksum
9 import com.android.managedprovisioning.model.PackageDownloadInfo
10 import com.android.managedprovisioning.model.ProvisioningParams
11 import com.android.onboarding.common.MANAGED_PROVISIONING
12 import com.android.onboarding.contracts.NodeAwareIntentScope
13 import com.android.onboarding.contracts.NodeAwareIntentSerializer
14 import com.android.onboarding.contracts.NodeId
15 import com.android.onboarding.contracts.OnboardingNodeId
16 import com.android.onboarding.contracts.VoidOnboardingActivityApiContract
17 import com.android.onboarding.contracts.annotations.OnboardingNode
18 import com.android.onboarding.contracts.provisioning.EXTRAS
19 import com.android.onboarding.contracts.require
20 import com.android.onboarding.contracts.setupwizard.SuwArguments
21 import com.android.onboarding.contracts.setupwizard.SuwArgumentsSerializer
22 import com.android.onboarding.contracts.setupwizard.WithSuwArguments
23 import javax.inject.Inject
24 
25 /**
26  * @property location Url where the package (.apk) can be downloaded from. {@code null} if there is no download location specified.
27  * @property cookieHeader Cookie header for http request.
28  * @property checksum SHA-256 hash of the signature in the .apk file
29  * @property minVersion Minimum supported version code of the downloaded package.
30  */
31 interface DownloadRoleHolderArguments : WithProvisioningParams, WithSuwArguments {
32     val location: String
33     val checksum: SignatureChecksum
34     val cookieHeader: String?
35     val minVersion: Int
36 
37     companion object {
38         @JvmStatic
39         @JvmName("of")
invokenull40         operator fun invoke(
41                 suwArguments: SuwArguments,
42                 provisioningParams: ProvisioningParams,
43                 location: String,
44                 checksum: SignatureChecksum,
45                 cookieHeader: String? = null,
46                 minVersion: Int = Int.MAX_VALUE,
47         ): DownloadRoleHolderArguments = object : DownloadRoleHolderArguments {
48             override val suwArguments = suwArguments
49             override val provisioningParams = provisioningParams
50             override val location = location
51             override val checksum = checksum
52             override val cookieHeader = cookieHeader
53             override val minVersion = minVersion
54         }
55 
56         @LegacyApi
57         @JvmStatic
58         @JvmName("of")
invokenull59         operator fun invoke(
60                 suwArguments: SuwArguments,
61                 provisioningParams: ProvisioningParams,
62         ): DownloadRoleHolderArguments = invoke(
63                 suwArguments = suwArguments,
64                 provisioningParams = provisioningParams,
65                 location = provisioningParams.roleHolderDownloadInfo?.location
66                         ?.require("Download location must not be empty.", String::isNotBlank)
67                         ?: error("Missing download location."),
68                 checksum = provisioningParams.roleHolderDownloadInfo.signatureChecksum
69                         .require("Checksum is missing", ByteArray::isNotEmpty)
70                         .let(Checksum::SignatureChecksum),
71                 cookieHeader = provisioningParams.roleHolderDownloadInfo.cookieHeader,
72                 minVersion = provisioningParams.roleHolderDownloadInfo.minVersion
73         )
74     }
75 }
76 
77 @OnboardingNode(
78         component = MANAGED_PROVISIONING,
79         name = "DownloadRoleHolder",
80         uiType = OnboardingNode.UiType.LOADING)
81 class DownloadRoleHolderContract
82 @Inject
83 constructor(
84         @OnboardingNodeId override val nodeId: NodeId,
85         private val screenManager: ScreenManager,
86         val suwArgumentsSerializer: SuwArgumentsSerializer
87 ) : VoidOnboardingActivityApiContract<DownloadRoleHolderArguments>(),
88         NodeAwareIntentSerializer<DownloadRoleHolderArguments> {
89 
90     override fun performCreateIntent(context: Context, arg: DownloadRoleHolderArguments): Intent =
91             Intent(context, screenManager.getActivityClassForScreen(DOWNLOAD_ROLE_HOLDER))
92                     .also { write(it, arg) }
93 
94     override fun performExtractArgument(intent: Intent): DownloadRoleHolderArguments = read(intent)
95     override fun NodeAwareIntentScope.write(value: DownloadRoleHolderArguments) {
96         this[suwArgumentsSerializer] = value::suwArguments
97         this[EXTRAS.EXTRA_PROVISIONING_PARAMS] =
98                 value::provisioningParams.map {
99                     it.toBuilder()
100                             .setRoleHolderDownloadInfo(
101                                     PackageDownloadInfo.Builder()
102                                             .setLocation(value.location)
103                                             .setCookieHeader(value.cookieHeader)
104                                             .setMinVersion(value.minVersion)
105                                             .setSignatureChecksum(value.checksum.bytes)
106                                             .build())
107                             .build()
108                 }
109     }
110 
111     override fun NodeAwareIntentScope.read(): DownloadRoleHolderArguments {
112         val provisioningParams =
113                 parcelable<ProvisioningParams>(EXTRAS.EXTRA_PROVISIONING_PARAMS).required
114         val params = provisioningParams.map {
115             it.roleHolderDownloadInfo ?: error("Missing role holder extras")
116         }
117         return object : DownloadRoleHolderArguments {
118             override val suwArguments by read(suwArgumentsSerializer)
119             override val provisioningParams by provisioningParams
120             override val location by params.map(PackageDownloadInfo::location)
121             override val checksum by params.map(PackageDownloadInfo::signatureChecksum).map(::SignatureChecksum)
122             override val cookieHeader by params.map(PackageDownloadInfo::cookieHeader)
123             override val minVersion by params.map(PackageDownloadInfo::minVersion)
124         }
125     }
126 }