aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartynas Petuška <petuska@google.com>2023-11-20 14:53:43 +0000
committerMartynas Petuška <petuska@google.com>2023-11-27 12:06:47 +0000
commitf57b2d22a21ed193636e6bb79a40245fa4b5e146 (patch)
tree10a35e341ce0547acdea97cf9486dcbae7b75da4
parent671b25093236f1b8853fc0c502974e4d5e015407 (diff)
downloadManagedProvisioning-f57b2d22a21ed193636e6bb79a40245fa4b5e146.tar.gz
DI Setup
Bug: 301578742 Topic: cl/584012825 Test: m ManagedProvisioning Change-Id: If44f8403af79681a47d09cbdc66b360e1f033d74
-rw-r--r--Android.bp36
-rw-r--r--aconfig/root.aconfig2
-rw-r--r--proguard.flags2
-rw-r--r--src/com/android/managedprovisioning/ManagedProvisioningBaseApplication.java16
-rw-r--r--src/com/android/managedprovisioning/Module.kt15
-rw-r--r--src/com/android/managedprovisioning/annotations/LegacyApi.kt9
-rw-r--r--src/com/android/managedprovisioning/common/CommonModule.kt13
-rw-r--r--src/com/android/managedprovisioning/common/Flags.kt33
-rw-r--r--src/com/android/managedprovisioning/common/SetupLayoutActivity.java12
-rw-r--r--src/com/android/managedprovisioning/contracts/Checksum.kt17
-rw-r--r--src/com/android/managedprovisioning/contracts/DownloadRoleHolderContract.kt100
-rw-r--r--src/com/android/managedprovisioning/contracts/ProvisioningArgumentsSerializer.kt84
-rw-r--r--src/com/android/managedprovisioning/preprovisioning/DownloadRoleHolderActivity.java20
-rw-r--r--src/com/android/managedprovisioning/preprovisioning/PreProvisioningActivity.java57
-rw-r--r--tests/robotests/Android.bp2
-rw-r--r--tests/robotests/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContractTest.kt45
-rw-r--r--tests/robotests/src/com/android/managedprovisioning/contracts/data.kt89
17 files changed, 509 insertions, 43 deletions
diff --git a/Android.bp b/Android.bp
index 976704098..38db1433e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,6 +26,19 @@ java_library {
},
}
+aconfig_declarations {
+ name: "aconfig_managed_provisioning_flags",
+ package: "com.android.managedprovisioning.flags",
+ srcs: [
+ "aconfig/*.aconfig"
+ ],
+}
+
+java_aconfig_library {
+ name: "aconfig_managed_provisioning_flags_lib",
+ aconfig_declarations: "aconfig_managed_provisioning_flags",
+}
+
android_library {
name: "ManagedProvisioningLib",
manifest: "AndroidManifest.xml",
@@ -36,14 +49,20 @@ android_library {
static_libs: [
"androidx.legacy_legacy-support-v4",
- "setupcompat",
+ "androidx.annotation_annotation",
"setupdesign",
"managedprovisioning_protoslite",
"androidx.webkit_webkit-nodeps",
"setupdesign-lottie-loading-layout",
"lottie",
"guava",
- "aconfig_managed_provisioning_flags_lib"
+ "aconfig_managed_provisioning_flags_lib",
+ "hilt_android",
+ "android_onboarding.contracts.provisioning",
+ "android_onboarding.contracts.annotations",
+ "android_onboarding.contracts.setupwizard",
+ "android_onboarding.flags_hilt",
+ "jsr330",
],
plugins: ["auto_value_plugin"],
@@ -83,16 +102,3 @@ android_app {
include_filter: ["com.android.managedprovisioning.*"],
},
}
-
-aconfig_declarations {
- name: "aconfig_managed_provisioning_flags",
- package: "com.android.managedprovisioning.flags",
- srcs: [
- "aconfig/*.aconfig"
- ],
-}
-
-java_aconfig_library {
- name: "aconfig_managed_provisioning_flags_lib",
- aconfig_declarations: "aconfig_managed_provisioning_flags",
-}
diff --git a/aconfig/root.aconfig b/aconfig/root.aconfig
index 858dd5a7e..defd6594d 100644
--- a/aconfig/root.aconfig
+++ b/aconfig/root.aconfig
@@ -1,7 +1,7 @@
package: "com.android.managedprovisioning.flags"
flag {
- name: "cosmic_ray"
+ name: "is_cosmic_ray_enabled"
namespace: "enterprise"
description: "Enables Cosmic Ray features"
bug: "288413994"
diff --git a/proguard.flags b/proguard.flags
index 2f45d5450..af83ce119 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,6 +1,6 @@
# Ensure exception attributes are kept to allow mocking of methods with
# checked exceptions.
--keepattributes Exceptions
+-keepattributes Exception
# It is not an error that these classes are referenced in
# AndriodManifest.xml, but not present in Android master. They are
diff --git a/src/com/android/managedprovisioning/ManagedProvisioningBaseApplication.java b/src/com/android/managedprovisioning/ManagedProvisioningBaseApplication.java
index 54aae9f8c..e20e21050 100644
--- a/src/com/android/managedprovisioning/ManagedProvisioningBaseApplication.java
+++ b/src/com/android/managedprovisioning/ManagedProvisioningBaseApplication.java
@@ -23,6 +23,10 @@ import android.view.WindowManager;
import com.android.managedprovisioning.preprovisioning.EncryptionController;
+import dagger.hilt.android.HiltAndroidApp;
+
+import javax.inject.Inject;
+
/**
* A base {@link Application} that is meant to be extended.
*
@@ -32,9 +36,11 @@ import com.android.managedprovisioning.preprovisioning.EncryptionController;
*
* <p>By default, the existing {@code ManagedProvisioning} {@link Activity} classes are used.
*/
-public abstract class ManagedProvisioningBaseApplication extends Application {
- private final ScreenManager mScreenManager =
- new ScreenManager(ScreenManager.DEFAULT_SCREEN_TO_ACTIVITY_MAP);
+@HiltAndroidApp(Application.class)
+public abstract class ManagedProvisioningBaseApplication extends
+ Hilt_ManagedProvisioningBaseApplication {
+ @Inject
+ protected ScreenManager mScreenManager;
private EncryptionController mEncryptionController;
private boolean mKeepScreenOn;
@@ -70,8 +76,8 @@ public abstract class ManagedProvisioningBaseApplication extends Application {
* <p>If no screens were set via {@link #setOverrideActivity(ManagedProvisioningScreens,
* Class)}, the base ManagedProvisioning {@link Activity} implementation will be returned.
*/
- public final Class<? extends Activity>
- getActivityClassForScreen(ManagedProvisioningScreens screen) {
+ public final Class<? extends Activity> getActivityClassForScreen(
+ ManagedProvisioningScreens screen) {
return mScreenManager.getActivityClassForScreen(screen);
}
diff --git a/src/com/android/managedprovisioning/Module.kt b/src/com/android/managedprovisioning/Module.kt
new file mode 100644
index 000000000..86625063f
--- /dev/null
+++ b/src/com/android/managedprovisioning/Module.kt
@@ -0,0 +1,15 @@
+package com.android.managedprovisioning
+
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.components.SingletonComponent
+
+@Module
+@InstallIn(ActivityComponent::class, SingletonComponent::class)
+class Module {
+ @Provides
+ fun defaultScreenManager(): ScreenManager =
+ ScreenManager(ScreenManager.DEFAULT_SCREEN_TO_ACTIVITY_MAP)
+} \ No newline at end of file
diff --git a/src/com/android/managedprovisioning/annotations/LegacyApi.kt b/src/com/android/managedprovisioning/annotations/LegacyApi.kt
new file mode 100644
index 000000000..671ad2360
--- /dev/null
+++ b/src/com/android/managedprovisioning/annotations/LegacyApi.kt
@@ -0,0 +1,9 @@
+package com.android.managedprovisioning.annotations
+
+@RequiresOptIn(
+ message =
+ "Marks API meant only to facilitate legacy code integration. " +
+ "Should be avoided whenever possible.",
+ level = RequiresOptIn.Level.ERROR,
+)
+annotation class LegacyApi \ No newline at end of file
diff --git a/src/com/android/managedprovisioning/common/CommonModule.kt b/src/com/android/managedprovisioning/common/CommonModule.kt
new file mode 100644
index 000000000..76a30bfc2
--- /dev/null
+++ b/src/com/android/managedprovisioning/common/CommonModule.kt
@@ -0,0 +1,13 @@
+package com.android.managedprovisioning.common
+
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+
+@Module
+@InstallIn(ActivityComponent::class)
+interface CommonModule {
+ @Binds
+ fun bind(impl: DefaultFlags): Flags
+}
diff --git a/src/com/android/managedprovisioning/common/Flags.kt b/src/com/android/managedprovisioning/common/Flags.kt
new file mode 100644
index 000000000..270f5065d
--- /dev/null
+++ b/src/com/android/managedprovisioning/common/Flags.kt
@@ -0,0 +1,33 @@
+package com.android.managedprovisioning.common
+
+import com.android.managedprovisioning.annotations.LegacyApi
+import com.android.onboarding.flags.DefaultOnboardingFlagsProvider
+import com.android.onboarding.flags.OnboardingFlagsProvider
+import javax.inject.Inject
+import com.android.managedprovisioning.flags.FeatureFlags as AconfigFlags
+import com.android.managedprovisioning.flags.FeatureFlagsImpl as DefaultAconfigFlags
+
+
+interface Flags : AconfigFlags {
+ @Deprecated(
+ "Static version is reserved for edge-cases where DI could not be " +
+ "easily achieved and as such should be avoided. " +
+ "Consider using injected version whenever possible."
+ )
+ @LegacyApi
+ companion object : Flags by DefaultFlags(DefaultOnboardingFlagsProvider())
+}
+
+class DefaultFlags(
+ private val onboardingFlags: OnboardingFlagsProvider,
+ private val aconfigFlags: AconfigFlags,
+) : Flags, AconfigFlags by aconfigFlags {
+ @Inject
+ constructor(
+ onboardingFlags: OnboardingFlagsProvider,
+ ) : this(onboardingFlags, DefaultAconfigFlags())
+
+ override fun isCosmicRayEnabled(): Boolean =
+ onboardingFlags.isDebug ||
+ (onboardingFlags.isContractEnabled && aconfigFlags.isCosmicRayEnabled)
+}
diff --git a/src/com/android/managedprovisioning/common/SetupLayoutActivity.java b/src/com/android/managedprovisioning/common/SetupLayoutActivity.java
index ea8e9320a..dd228fbcc 100644
--- a/src/com/android/managedprovisioning/common/SetupLayoutActivity.java
+++ b/src/com/android/managedprovisioning/common/SetupLayoutActivity.java
@@ -45,10 +45,13 @@ import com.android.managedprovisioning.common.ThemeHelper.DefaultNightModeChecke
import com.android.managedprovisioning.common.ThemeHelper.DefaultSetupWizardBridge;
import com.android.managedprovisioning.preprovisioning.EncryptionController;
+import dagger.hilt.android.AndroidEntryPoint;
+
/**
* Base class for setting up the layout.
*/
-public abstract class SetupLayoutActivity extends AppCompatActivity {
+@AndroidEntryPoint(AppCompatActivity.class)
+public abstract class SetupLayoutActivity extends Hilt_SetupLayoutActivity {
protected final Utils mUtils;
protected final SettingsFacade mSettingsFacade;
private final ThemeHelper mThemeHelper;
@@ -176,9 +179,11 @@ public abstract class SetupLayoutActivity extends AppCompatActivity {
/**
* Constructs and shows a {@link DialogFragment} unless it is already displayed.
+ *
* @param dialogBuilder Lightweight builder, that it is inexpensive to discard it if dialog
- * already shown.
- * @param tag The tag for this dialog, as per {@link FragmentTransaction#add(Fragment, String)}.
+ * already shown.
+ * @param tag The tag for this dialog, as per
+ * {@link FragmentTransaction#add(Fragment, String)}.
*/
protected void showDialog(DialogBuilder dialogBuilder, String tag) {
FragmentManager fragmentManager = getFragmentManager();
@@ -189,6 +194,7 @@ public abstract class SetupLayoutActivity extends AppCompatActivity {
/**
* Checks whether the {@link DialogFragment} associated with the given tag is currently showing.
+ *
* @param tag The tag for this dialog.
*/
protected boolean isDialogAdded(String tag) {
diff --git a/src/com/android/managedprovisioning/contracts/Checksum.kt b/src/com/android/managedprovisioning/contracts/Checksum.kt
new file mode 100644
index 000000000..5ef4927f7
--- /dev/null
+++ b/src/com/android/managedprovisioning/contracts/Checksum.kt
@@ -0,0 +1,17 @@
+package com.android.managedprovisioning.contracts
+
+sealed interface Checksum {
+ val bytes: ByteArray
+
+ /**
+ * SHA-256 hash of the .apk file
+ */
+ @JvmInline
+ value class PackageChecksum(override val bytes: ByteArray) : Checksum
+
+ /**
+ * SHA-256 hash of the signature in the .apk file
+ */
+ @JvmInline
+ value class SignatureChecksum(override val bytes: ByteArray) : Checksum
+} \ No newline at end of file
diff --git a/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContract.kt b/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContract.kt
new file mode 100644
index 000000000..53e26de0f
--- /dev/null
+++ b/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContract.kt
@@ -0,0 +1,100 @@
+package com.android.managedprovisioning.contracts
+
+import android.content.Context
+import android.content.Intent
+import com.android.managedprovisioning.ManagedProvisioningScreens.DOWNLOAD_ROLE_HOLDER
+import com.android.managedprovisioning.ScreenManager
+import com.android.managedprovisioning.annotations.LegacyApi
+import com.android.managedprovisioning.contracts.Checksum.SignatureChecksum
+import com.android.managedprovisioning.model.PackageDownloadInfo
+import com.android.managedprovisioning.model.ProvisioningParams
+import com.android.onboarding.common.MANAGED_PROVISIONING
+import com.android.onboarding.contracts.IntentScope
+import com.android.onboarding.contracts.ScopedIntentSerializer
+import com.android.onboarding.contracts.VoidOnboardingActivityApiContract
+import com.android.onboarding.contracts.annotations.OnboardingNode
+import com.android.onboarding.contracts.provisioning.EXTRAS
+import com.android.onboarding.contracts.require
+import com.android.onboarding.contracts.setupwizard.SuwArguments
+import com.android.onboarding.contracts.setupwizard.SuwArgumentsSerializer
+import com.android.onboarding.contracts.setupwizard.WithSuwArguments
+import javax.inject.Inject
+
+/**
+ * @property location Url where the package (.apk) can be downloaded from. {@code null} if there is no download location specified.
+ * @property cookieHeader Cookie header for http request.
+ * @property checksum SHA-256 hash of the signature in the .apk file
+ * @property minVersion Minimum supported version code of the downloaded package.
+ */
+data class DownloadRoleHolderArguments(
+ override val suwArguments: SuwArguments,
+ override val provisioningParams: ProvisioningParams,
+ val location: String,
+ val checksum: SignatureChecksum,
+ val cookieHeader: String? = null,
+ val minVersion: Int = Int.MAX_VALUE,
+) : WithProvisioningParams, WithSuwArguments {
+ @LegacyApi
+ constructor(
+ suwArguments: SuwArguments,
+ provisioningParams: ProvisioningParams,
+ ) : this(
+ suwArguments = suwArguments,
+ provisioningParams = provisioningParams,
+ location = provisioningParams.roleHolderDownloadInfo?.location
+ ?.require("Download location must not be empty.", String::isNotBlank)
+ ?: error("Missing download location."),
+ checksum = provisioningParams.roleHolderDownloadInfo.signatureChecksum
+ .require("Checksum is missing", ByteArray::isNotEmpty)
+ .let(Checksum::SignatureChecksum),
+ cookieHeader = provisioningParams.roleHolderDownloadInfo.cookieHeader,
+ minVersion = provisioningParams.roleHolderDownloadInfo.minVersion
+ )
+}
+
+@OnboardingNode(
+ component = MANAGED_PROVISIONING,
+ name = "DownloadRoleHolder",
+ hasUi = OnboardingNode.HasUi.NO)
+class DownloadRoleHolderContract
+@Inject
+constructor(
+ private val screenManager: ScreenManager,
+ val suwArgumentsSerializer: SuwArgumentsSerializer
+) : VoidOnboardingActivityApiContract<DownloadRoleHolderArguments>(),
+ ScopedIntentSerializer<DownloadRoleHolderArguments> {
+
+ override fun performCreateIntent(context: Context, arg: DownloadRoleHolderArguments): Intent =
+ Intent(context, screenManager.getActivityClassForScreen(DOWNLOAD_ROLE_HOLDER))
+ .also { write(it, arg) }
+
+ override fun performExtractArgument(intent: Intent): DownloadRoleHolderArguments = read(intent)
+ override fun IntentScope.write(value: DownloadRoleHolderArguments) {
+ write(suwArgumentsSerializer, value.suwArguments)
+ this[EXTRAS.EXTRA_PROVISIONING_PARAMS] =
+ value.provisioningParams.toBuilder()
+ .setRoleHolderDownloadInfo(
+ PackageDownloadInfo.Builder()
+ .setLocation(value.location)
+ .setCookieHeader(value.cookieHeader)
+ .setMinVersion(value.minVersion)
+ .setSignatureChecksum(value.checksum.bytes)
+ .build())
+ .build()
+ }
+
+ override fun IntentScope.read(): DownloadRoleHolderArguments {
+ val provisioningParams =
+ parcelableExtra<ProvisioningParams>(EXTRAS.EXTRA_PROVISIONING_PARAMS)
+ val params = provisioningParams.roleHolderDownloadInfo
+ ?: error("Missing role holder extras")
+ return DownloadRoleHolderArguments(
+ suwArguments = read(suwArgumentsSerializer),
+ provisioningParams = provisioningParams,
+ location = params.location,
+ checksum = SignatureChecksum(params.signatureChecksum),
+ cookieHeader = params.cookieHeader,
+ minVersion = params.minVersion,
+ )
+ }
+} \ No newline at end of file
diff --git a/src/com/android/managedprovisioning/contracts/ProvisioningArgumentsSerializer.kt b/src/com/android/managedprovisioning/contracts/ProvisioningArgumentsSerializer.kt
new file mode 100644
index 000000000..4bfdb928a
--- /dev/null
+++ b/src/com/android/managedprovisioning/contracts/ProvisioningArgumentsSerializer.kt
@@ -0,0 +1,84 @@
+package com.android.managedprovisioning.contracts
+
+import android.content.ComponentName
+import com.android.managedprovisioning.annotations.LegacyApi
+import com.android.managedprovisioning.model.PackageDownloadInfo
+import com.android.managedprovisioning.model.ProvisioningParams
+import com.android.managedprovisioning.model.WifiInfo
+import com.android.onboarding.contracts.IntentScope
+import com.android.onboarding.contracts.ScopedIntentSerializer
+import com.android.onboarding.contracts.provisioning.EXTRAS
+import javax.inject.Inject
+
+interface WithProvisioningParams : WithOptionalProvisioningParams {
+ override val provisioningParams: ProvisioningParams
+}
+
+interface WithOptionalProvisioningParams {
+ /** Only needed to preserve data parity when passing provisioning params bundle along */
+ val provisioningParams: ProvisioningParams?
+}
+
+enum class FlowType {
+ Unspecified,
+ Legacy,
+ AdminIntegrated
+}
+
+data class BaseProvisioningArguments(
+ override val provisioningParams: ProvisioningParams,
+ val flowType: FlowType,
+ val deviceAdminDownloadInfo: PackageDownloadInfo?,
+ val deviceAdminComponentName: ComponentName?,
+ val wifiInfo: WifiInfo?,
+ val useMobileData: Boolean,
+ val isNfc: Boolean,
+ val isQr: Boolean,
+) : WithProvisioningParams {
+ @LegacyApi
+ constructor(
+ provisioningParams: ProvisioningParams
+ ) : this(
+ provisioningParams = provisioningParams,
+ flowType = FlowType.values()[provisioningParams.flowType],
+ deviceAdminDownloadInfo = provisioningParams.deviceAdminDownloadInfo,
+ deviceAdminComponentName = provisioningParams.deviceAdminComponentName,
+ wifiInfo = provisioningParams.wifiInfo,
+ useMobileData = provisioningParams.useMobileData,
+ isNfc = provisioningParams.isNfc,
+ isQr = provisioningParams.isQrProvisioning,
+ )
+}
+
+class ProvisioningArgumentsSerializer @Inject constructor() :
+ ScopedIntentSerializer<BaseProvisioningArguments> {
+
+ override fun IntentScope.write(value: BaseProvisioningArguments) {
+ val params =
+ value.provisioningParams
+ .toBuilder()
+ .setFlowType(value.flowType.ordinal)
+ .setDeviceAdminDownloadInfo(value.deviceAdminDownloadInfo)
+ .setDeviceAdminComponentName(value.deviceAdminComponentName)
+ .setWifiInfo(value.wifiInfo)
+ .setUseMobileData(value.useMobileData)
+ .setIsNfc(value.isNfc)
+ .setIsQrProvisioning(value.isQr)
+ .build()
+ this[EXTRAS.EXTRA_PROVISIONING_PARAMS] = params
+ }
+
+ override fun IntentScope.read(): BaseProvisioningArguments =
+ parcelableExtra<ProvisioningParams>(EXTRAS.EXTRA_PROVISIONING_PARAMS).let {
+ BaseProvisioningArguments(
+ provisioningParams = it,
+ flowType = FlowType.entries[it.flowType],
+ deviceAdminDownloadInfo = it.deviceAdminDownloadInfo,
+ deviceAdminComponentName = it.deviceAdminComponentName,
+ wifiInfo = it.wifiInfo,
+ useMobileData = it.useMobileData,
+ isNfc = it.isNfc,
+ isQr = it.isQrProvisioning,
+ )
+ }
+}
diff --git a/src/com/android/managedprovisioning/preprovisioning/DownloadRoleHolderActivity.java b/src/com/android/managedprovisioning/preprovisioning/DownloadRoleHolderActivity.java
index 6d6c27e09..0ddefe138 100644
--- a/src/com/android/managedprovisioning/preprovisioning/DownloadRoleHolderActivity.java
+++ b/src/com/android/managedprovisioning/preprovisioning/DownloadRoleHolderActivity.java
@@ -26,11 +26,17 @@ import com.android.managedprovisioning.ManagedProvisioningBaseApplication;
import com.android.managedprovisioning.R;
import com.android.managedprovisioning.common.ErrorDialogUtils;
import com.android.managedprovisioning.common.ErrorWrapper;
+import com.android.managedprovisioning.common.Flags;
import com.android.managedprovisioning.common.RoleHolderProvider;
import com.android.managedprovisioning.common.SetupGlifLayoutActivity;
+import com.android.managedprovisioning.contracts.DownloadRoleHolderContract;
import com.android.managedprovisioning.model.ProvisioningParams;
import com.android.managedprovisioning.preprovisioning.DownloadRoleHolderViewModel.DownloadRoleHolderViewModelFactory;
+import dagger.hilt.android.AndroidEntryPoint;
+
+import javax.inject.Inject;
+
/**
* Spinner which takes care of network connectivity if needed, and downloading of the role holder.
*
@@ -43,12 +49,22 @@ import com.android.managedprovisioning.preprovisioning.DownloadRoleHolderViewMod
* ErrorDialogUtils#EXTRA_FACTORY_RESET_REQUIRED} which can be used to display in a user-visible
* dialog.
*/
-public class DownloadRoleHolderActivity extends SetupGlifLayoutActivity {
+@AndroidEntryPoint(SetupGlifLayoutActivity.class)
+public class DownloadRoleHolderActivity extends Hilt_DownloadRoleHolderActivity {
private DownloadRoleHolderViewModel mViewModel;
+ @Inject
+ protected Flags mFlags;
+
+ @Inject
+ protected DownloadRoleHolderContract mContract;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (mFlags.isCosmicRayEnabled()) {
+ mContract.validate(this, getIntent());
+ }
ProvisioningParams params = getIntent().getParcelableExtra(EXTRA_PROVISIONING_PARAMS);
if (params.roleHolderDownloadInfo == null) {
@@ -72,7 +88,7 @@ public class DownloadRoleHolderActivity extends SetupGlifLayoutActivity {
}
private void onStateChanged(Integer state) {
- switch(state) {
+ switch (state) {
case DownloadRoleHolderViewModel.STATE_IDLE:
break;
case DownloadRoleHolderViewModel.STATE_DOWNLOADING:
diff --git a/src/com/android/managedprovisioning/preprovisioning/PreProvisioningActivity.java b/src/com/android/managedprovisioning/preprovisioning/PreProvisioningActivity.java
index 9cbc2001e..bde89623c 100644
--- a/src/com/android/managedprovisioning/preprovisioning/PreProvisioningActivity.java
+++ b/src/com/android/managedprovisioning/preprovisioning/PreProvisioningActivity.java
@@ -72,6 +72,7 @@ import com.android.managedprovisioning.common.DefaultFeatureFlagChecker;
import com.android.managedprovisioning.common.DefaultIntentResolverChecker;
import com.android.managedprovisioning.common.DefaultPackageInstallChecker;
import com.android.managedprovisioning.common.DeviceManagementRoleHolderUpdaterHelper;
+import com.android.managedprovisioning.common.Flags;
import com.android.managedprovisioning.common.GetProvisioningModeUtils;
import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
import com.android.managedprovisioning.common.ProvisionLogger;
@@ -85,6 +86,8 @@ import com.android.managedprovisioning.common.ThemeHelper;
import com.android.managedprovisioning.common.ThemeHelper.DefaultNightModeChecker;
import com.android.managedprovisioning.common.ThemeHelper.DefaultSetupWizardBridge;
import com.android.managedprovisioning.common.Utils;
+import com.android.managedprovisioning.contracts.DownloadRoleHolderArguments;
+import com.android.managedprovisioning.contracts.DownloadRoleHolderContract;
import com.android.managedprovisioning.model.ProvisioningParams;
import com.android.managedprovisioning.preprovisioning.PreProvisioningActivityController.UiParams;
import com.android.managedprovisioning.provisioning.AdminIntegratedFlowPrepareActivity;
@@ -97,7 +100,12 @@ import com.google.android.setupcompat.logging.SetupMetricsLogger;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.transition.TransitionHelper;
-public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
+import dagger.hilt.android.AndroidEntryPoint;
+
+import javax.inject.Inject;
+
+@AndroidEntryPoint(SetupGlifLayoutActivity.class)
+public class PreProvisioningActivity extends Hilt_PreProvisioningActivity implements
SimpleDialog.SimpleDialogListener, PreProvisioningActivityController.Ui {
private static final int ENCRYPT_DEVICE_REQUEST_CODE = 1;
@@ -126,7 +134,7 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
"ShowPreProvisioningScreen";
private PreProvisioningActivityController mController;
- private ControllerProvider mControllerProvider;
+ private final ControllerProvider mControllerProvider;
private final AccessibilityContextMenuMaker mContextMenuMaker;
private PreProvisioningActivityBridge mBridge;
private boolean mShouldForwardTransition;
@@ -140,15 +148,20 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
protected ScreenKey mScreenKey;
protected String setupMetricScreenName;
+ @Inject
+ protected Flags mFlags;
+ @Inject
+ protected DownloadRoleHolderContract mDownloadRoleHolderContract;
+
public PreProvisioningActivity() {
this(activity ->
- new PreProvisioningActivityController(activity, activity),
+ new PreProvisioningActivityController(activity, activity),
null,
new Utils(),
new SettingsFacade(),
new ThemeHelper(
- new DefaultNightModeChecker(),
- new DefaultSetupWizardBridge()),
+ new DefaultNightModeChecker(),
+ new DefaultSetupWizardBridge()),
RoleHolderProvider.DEFAULT,
RoleHolderUpdaterProvider.DEFAULT);
}
@@ -325,7 +338,7 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
case GET_PROVISIONING_MODE_REQUEST_CODE:
mShouldForwardTransition = true;
if (resultCode == RESULT_OK) {
- if(data != null && mController.updateProvisioningParamsFromIntent(data)) {
+ if (data != null && mController.updateProvisioningParamsFromIntent(data)) {
mController.showUserConsentScreen();
} else {
ProvisionLogger.loge(
@@ -456,7 +469,7 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
if (TextUtils.isEmpty(
mRoleHolderUpdaterProvider.getPackageName(this))) {
ProvisionLogger.logw("Role holder requested update, but there is no role "
- + "holder updater present. Restarting the role holder.");
+ + "holder updater present. Restarting the role holder.");
boolean isProvisioningStarted = mController.startAppropriateProvisioning(
getIntent(),
createRoleHolderAdditionalExtras(resultCode),
@@ -511,9 +524,9 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
mAnalyticsTracker.logRoleHolderUpdaterUpdateFailed();
failRoleHolderUpdate();
ProvisionLogger.loge("Failed to start provisioning after a "
- + "platform-requested role holder update. Result is " + resultCode
- + " and allow offline provisioning is "
- + mController.getParams().allowOffline);
+ + "platform-requested role holder update. Result is " + resultCode
+ + " and allow offline provisioning is "
+ + mController.getParams().allowOffline);
SetupMetricsLogger.logMetrics(this, mScreenKey,
SetupMetric.ofError(setupMetricScreenName, resultCode));
}
@@ -801,7 +814,7 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
isRoleHolderRequestedUpdate));
mAnalyticsTracker.logRoleHolderUpdaterUpdateStart();
getTransitionHelper().startActivityForResultWithTransition(
- this,
+ this,
intent,
isRoleHolderRequestedUpdate
? START_ROLE_HOLDER_REQUESTED_UPDATE_REQUEST_CODE
@@ -829,11 +842,22 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
@Override
public void startPlatformDrivenRoleHolderDownload() {
mAnalyticsTracker.logPlatformRoleHolderUpdateStart();
- Intent intent = new Intent(this,
- getActivityForScreen(ManagedProvisioningScreens.DOWNLOAD_ROLE_HOLDER));
- WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
- intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS,
- mController.getParams());
+
+ Intent intent;
+ if (mFlags.isCosmicRayEnabled()) {
+ intent = mDownloadRoleHolderContract.createIntent(
+ this,
+ new DownloadRoleHolderArguments(
+ mDownloadRoleHolderContract.getSuwArgumentsSerializer().read(
+ getIntent()),
+ requireNonNull(mController.getParams())));
+ } else {
+ intent = new Intent(this,
+ getActivityForScreen(ManagedProvisioningScreens.DOWNLOAD_ROLE_HOLDER));
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS,
+ mController.getParams());
+ }
getTransitionHelper().startActivityForResultWithTransition(
this, intent, DOWNLOAD_DEVICE_MANAGEMENT_ROLE_HOLDER_FROM_PLATFORM_REQUEST_CODE);
}
@@ -860,6 +884,7 @@ public class PreProvisioningActivity extends SetupGlifLayoutActivity implements
// TODO: The below group of methods do not belong in the activity.
// Move them to the controller instead.
+
/**
* Starts either the admin-integrated or the legacy flow, depending on the device state and
* DPC capabilities.
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 4a433d5df..185ca9827 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -26,6 +26,8 @@ android_robolectric_test {
"androidx.test.rules",
"androidx.core_core",
"testng", // used only for assertThrows
+ "android_onboarding.contracts.testing",
+ "hilt_android_testing",
],
static_libs: [
diff --git a/tests/robotests/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContractTest.kt b/tests/robotests/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContractTest.kt
new file mode 100644
index 000000000..7269efd34
--- /dev/null
+++ b/tests/robotests/src/com/android/managedprovisioning/contracts/DownloadRoleHolderContractTest.kt
@@ -0,0 +1,45 @@
+package com.android.managedprovisioning.contracts
+
+import android.os.Build
+import com.android.onboarding.contracts.testing.assertArgumentEncodesCorrectly
+import dagger.hilt.android.testing.HiltAndroidRule
+import dagger.hilt.android.testing.HiltAndroidTest
+import dagger.hilt.android.testing.HiltTestApplication
+import javax.inject.Inject
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+
+@RunWith(RobolectricTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.VANILLA_ICE_CREAM, application = HiltTestApplication::class)
+@HiltAndroidTest
+class DownloadRoleHolderContractTest {
+ @get:Rule
+ val hiltRule = HiltAndroidRule(this)
+
+ @Inject
+ lateinit var contract: DownloadRoleHolderContract
+
+ @Before
+ fun setUp() {
+ hiltRule.inject()
+ }
+
+ @Test
+ fun completeArgument_encodesCorrectly() {
+ val rhDownloadInfo = requireNotNull(aProvisioningParams.roleHolderDownloadInfo)
+ val args =
+ DownloadRoleHolderArguments(
+ suwArguments = aSuwArguments,
+ provisioningParams = aProvisioningParams,
+ location = rhDownloadInfo.location,
+ checksum = Checksum.SignatureChecksum(rhDownloadInfo.signatureChecksum),
+ cookieHeader = rhDownloadInfo.cookieHeader,
+ minVersion = rhDownloadInfo.minVersion,
+ )
+ assertArgumentEncodesCorrectly(contract, args)
+ }
+}
diff --git a/tests/robotests/src/com/android/managedprovisioning/contracts/data.kt b/tests/robotests/src/com/android/managedprovisioning/contracts/data.kt
new file mode 100644
index 000000000..ccea229e5
--- /dev/null
+++ b/tests/robotests/src/com/android/managedprovisioning/contracts/data.kt
@@ -0,0 +1,89 @@
+package com.android.managedprovisioning.contracts
+
+import android.content.ComponentName
+import android.os.Bundle
+import com.android.managedprovisioning.model.DisclaimersParam
+import com.android.managedprovisioning.model.PackageDownloadInfo
+import com.android.managedprovisioning.model.ProvisioningParams
+import com.android.managedprovisioning.model.WifiInfo
+import com.android.onboarding.contracts.provisioning.ACTIONS
+import com.android.onboarding.contracts.provisioning.FLAGS
+import com.android.onboarding.contracts.setupwizard.SuwArguments
+
+/**
+ * Stub [SuwArguments] prebuilt for testing. Further customisation is available via
+ * [SuwArguments.copy] method
+ */
+val aSuwArguments =
+ SuwArguments(
+ isSubactivityFirstLaunched = true,
+ isSuwSuggestedActionFlow = true,
+ isSetupFlow = true,
+ preDeferredSetup = true,
+ deferredSetup = false,
+ firstRun = true,
+ portalSetup = false,
+ hasMultipleUsers = false,
+ theme = "dark",
+ wizardBundle = Bundle.EMPTY
+ )
+
+val aProvisioningParams: ProvisioningParams = run {
+ val flowType = FlowType.AdminIntegrated
+ val deviceAdminDownloadInfo =
+ PackageDownloadInfo.Builder()
+ .setLocation("some/body")
+ .setMinVersion(69)
+ .setPackageChecksum("checksum".toByteArray())
+ .build()
+ val deviceAdminComponentName = ComponentName("org.test", "Test")
+ val wifiInfo = WifiInfo.Builder().setSsid("MyFi").setPassword("secret").build()
+ val packageDownloadInfo = PackageDownloadInfo.Builder()
+ .setLocation("http://test.local")
+ .setMinVersion(420)
+ .setSignatureChecksum("69".toByteArray())
+ .setCookieHeader("I'm a cookie monster, gimmie all your cookies or else!")
+ .build()
+ ProvisioningParams.Builder()
+ .setProvisioningAction(ACTIONS.ACTION_PROVISION_MANAGED_PROFILE)
+ .setDeviceAdminComponentName(ComponentName("org.test", "local"))
+ .setFlowType(flowType.ordinal)
+ .setDeviceAdminDownloadInfo(deviceAdminDownloadInfo)
+ .setDeviceAdminComponentName(deviceAdminComponentName)
+ .setWifiInfo(wifiInfo)
+ .setUseMobileData(true)
+ .setIsNfc(true)
+ .setIsQrProvisioning(true)
+ .setSupportUrl("https://help.test")
+ .setInitiatorRequestedProvisioningModes(
+ FLAGS.FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED or FLAGS.FLAG_SUPPORTED_MODES_DEVICE_OWNER
+ )
+ .setDisclaimersParam(
+ DisclaimersParam.Builder()
+ .setDisclaimers(
+ arrayOf(
+ DisclaimersParam.Disclaimer("a", "a.html"),
+ DisclaimersParam.Disclaimer("b", "b.html"),
+ )
+ )
+ .build()
+ )
+ .setRoleHolderDownloadInfo(packageDownloadInfo)
+ .setIsOrganizationOwnedProvisioning(true)
+ .setSkipEducationScreens(true)
+ .setReturnBeforePolicyCompliance(true)
+ .setDeviceOwnerPermissionGrantOptOut(true)
+ .setAllowProvisioningAfterUserSetupComplete(true)
+ .build()
+}
+
+val aProvisioningArguments: BaseProvisioningArguments = BaseProvisioningArguments(
+ provisioningParams = aProvisioningParams,
+ flowType = FlowType.entries[aProvisioningParams.flowType],
+ deviceAdminDownloadInfo = aProvisioningParams.deviceAdminDownloadInfo,
+ deviceAdminComponentName = aProvisioningParams.deviceAdminComponentName,
+ wifiInfo = aProvisioningParams.wifiInfo,
+ useMobileData = aProvisioningParams.useMobileData,
+ isNfc = aProvisioningParams.isNfc,
+ isQr = aProvisioningParams.isQrProvisioning,
+)