Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f9e3753 authored by Sandy Pan's avatar Sandy Pan Committed by Android (Google) Code Review
Browse files

Merge "Invoke pin recovery setup activity after setup supervision" into main

parents f3d40ab5 56ee4125
Loading
Loading
Loading
Loading
+55 −11
Original line number Diff line number Diff line
@@ -19,11 +19,14 @@ import android.Manifest.permission.CREATE_USERS
import android.Manifest.permission.INTERACT_ACROSS_USERS
import android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
import android.Manifest.permission.MANAGE_USERS
import android.app.Activity
import android.app.ActivityManager
import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD
import android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY
import android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW
import android.app.supervision.SupervisionManager
import android.app.supervision.flags.Flags
import android.content.Intent
import android.os.Bundle
import android.os.UserHandle
@@ -38,13 +41,17 @@ import com.android.settingslib.supervision.SupervisionLog
/**
 * This activity starts the flow for setting up device supervision.
 *
 * Three things are required for device supervision: a supervising profile must be created, a lock
 * must be set up for this profile, and `SupervisionManager.isSupervisionEnabled()` must be set.
 * This activity handles the first two, while the third is managed by
 * `SupervisionMainSwitchPreference`.
 * The flow involves three essential steps:
 * 1. Creating a dedicated supervising user profile.
 * 2. Setting up a secure lock (e.g., PIN, password) for this profile.
 * 3. Enabling device supervision using `SupervisionManager.isSupervisionEnabled()`.
 *
 * Returns `Activity.RESULT_OK` if all steps of setup succeed, and `Activity.RESULT_CANCELED` if
 * any step fails, or the user does not finish setting up the lock for the supervising profile.
 * After completing these steps, the activity prompts the user to set up PIN recovery. The result of
 * the PIN recovery setup does not affect the activity's overall result.
 *
 * The activity returns:
 * - `Activity.RESULT_OK` if steps 1-3 are successful.
 * - `Activity.RESULT_CANCELED` if any of steps 1-3 fail, or if the user cancels lock setup.
 *
 * Usage:
 * 1. Start this activity using `startActivityForResult()`.
@@ -94,7 +101,8 @@ class SetupSupervisionActivity : FragmentActivity() {
    private fun startChooseLockActivity(userHandle: UserHandle) {
        // TODO(b/389712273) Intent directly to PIN selection screen to avoid giving the user
        //  the options for password/pattern during the initial setup flow
        val intent = Intent(ACTION_SET_NEW_PASSWORD).apply {
        val intent =
            Intent(ACTION_SET_NEW_PASSWORD).apply {
                putExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_LOW)
                putExtra(EXTRA_KEY_FINGERPRINT_ENROLLMENT_ONLY, true)
            }
@@ -104,6 +112,14 @@ class SetupSupervisionActivity : FragmentActivity() {
    @RequiresPermission(anyOf = [INTERACT_ACROSS_USERS_FULL, MANAGE_USERS])
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQUEST_CODE_SET_SUPERVISION_LOCK -> handleSetLockResult(resultCode)
            REQUEST_CODE_SET_PIN_RECOVERY -> handlePinRecoveryResult(resultCode)
        }
    }

    private fun handleSetLockResult(resultCode: Int) {
        val supervisionHelper = SupervisionHelper.getInstance(this)
        val supervisingUser = supervisionHelper.getSupervisingUserHandle()
        if (supervisingUser == null) {
@@ -121,10 +137,38 @@ class SetupSupervisionActivity : FragmentActivity() {
            finish()
            return
        }

        // Enable device supervision
        val supervisionManager = getSystemService(SupervisionManager::class.java)
        supervisionManager?.setSupervisionEnabled(true)

        // Start PIN recovery setup
        startPinRecoveryActivity()
    }

    private fun handlePinRecoveryResult(resultCode: Int) {
        if (resultCode == Activity.RESULT_CANCELED) {
            Log.i(SupervisionLog.TAG, "PIN recovery setup was skipped by the user.")
        }
        setResult(RESULT_OK)
        finish()
    }

    private fun startPinRecoveryActivity() {
        // prompt user to setup pin recovery if flag is enabled
        if (!Flags.enableSupervisionPinRecoveryScreen()) {
            Log.d(SupervisionLog.TAG, "PIN recovery setup is not enabled.")
            setResult(RESULT_OK)
            finish()
        }

        val intent =
            Intent(this, SupervisionPinRecoveryActivity::class.java).apply {
                action = SupervisionPinRecoveryActivity.ACTION_SETUP
            }
        startActivityForResult(intent, REQUEST_CODE_SET_PIN_RECOVERY, null)
    }

    @RequiresPermission(anyOf = [INTERACT_ACROSS_USERS_FULL, MANAGE_USERS])
    private fun tryStopProfile(supervisingUser: UserHandle, activityManager: ActivityManager) {
        if (!activityManager.stopProfile(supervisingUser)) {
@@ -134,6 +178,6 @@ class SetupSupervisionActivity : FragmentActivity() {

    companion object {
        private const val REQUEST_CODE_SET_SUPERVISION_LOCK = 0
        private const val REQUEST_CODE_SET_PIN_RECOVERY = 1
    }

}
+6 −5
Original line number Diff line number Diff line
@@ -89,7 +89,8 @@ class SupervisionMainSwitchPreference(
            supervisionMainSwitchStorage.getBoolean(KEY)!!,
        )

        val preferenceKeys = buildList<String> {
        val preferenceKeys =
            buildList<String> {
                mainSwitchPreference?.parent?.forEachRecursively {
                    if (it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1) {
                        add(it.key)
+4 −6
Original line number Diff line number Diff line
@@ -35,17 +35,15 @@ import com.android.settingslib.supervision.SupervisionLog
class SupervisionPinRecoveryActivity : FragmentActivity() {
    // ActivityResultLaunchers
    private val contract = ActivityResultContracts.StartActivityForResult()
    private val confirmPinLauncher: ActivityResultLauncher<Intent> by lazy {
    private val confirmPinLauncher: ActivityResultLauncher<Intent> =
        registerForActivityResult(contract) { result -> onPinConfirmed(result.resultCode) }
    }
    private val verificationLauncher: ActivityResultLauncher<Intent> by lazy {

    private val verificationLauncher: ActivityResultLauncher<Intent> =
        registerForActivityResult(contract) { result ->
            onVerification(result.resultCode, result.data)
        }
    }
    private val setPinLauncher: ActivityResultLauncher<Intent> by lazy {
    private val setPinLauncher: ActivityResultLauncher<Intent> =
        registerForActivityResult(contract) { result -> onPinSet(result.resultCode) }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)