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

Commit b713e43c authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Create RestrictedSwitchPreference for SpaLib

This will be used at "Install unknown apps" page.

Bug: 235727273
Test: Manual with Test App
Change-Id: Iab83ac9d51806508398e04393e72299694481e93
parent e4df5f53
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settingslib.spaprivileged.model.enterprise

import android.app.admin.DevicePolicyResources.Strings.Settings
import android.content.Context
import android.os.UserHandle
import android.os.UserManager
import androidx.lifecycle.LiveData
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
import com.android.settingslib.RestrictedLockUtilsInternal
import com.android.settingslib.spaprivileged.R

data class Restrictions(
    val userId: Int,
    val keys: List<String>,
)

sealed class RestrictedMode

object NoRestricted : RestrictedMode()

object BaseUserRestricted : RestrictedMode()

data class BlockedByAdmin(
    val enterpriseRepository: EnterpriseRepository,
    val enforcedAdmin: EnforcedAdmin,
) : RestrictedMode() {
    fun getSummary(checked: Boolean?): String = when (checked) {
        true -> enterpriseRepository.getEnterpriseString(
            Settings.ENABLED_BY_ADMIN_SWITCH_SUMMARY, R.string.enabled_by_admin
        )
        false -> enterpriseRepository.getEnterpriseString(
            Settings.DISABLED_BY_ADMIN_SWITCH_SUMMARY, R.string.disabled_by_admin
        )
        else -> ""
    }
}

class RestrictionsProvider(
    private val context: Context,
    private val restrictions: Restrictions,
) {
    private val userManager by lazy { UserManager.get(context) }
    private val enterpriseRepository by lazy { EnterpriseRepository(context) }

    val restrictedMode = object : LiveData<RestrictedMode>() {
        override fun onActive() {
            postValue(getRestrictedMode())
        }

        override fun onInactive() {
        }
    }

    private fun getRestrictedMode(): RestrictedMode {
        for (key in restrictions.keys) {
            if (userManager.hasBaseUserRestriction(key, UserHandle.of(restrictions.userId))) {
                return BaseUserRestricted
            }
        }
        for (key in restrictions.keys) {
            RestrictedLockUtilsInternal
                .checkIfRestrictionEnforced(context, key, restrictions.userId)
                ?.let {
                    return BlockedByAdmin(
                        enterpriseRepository = enterpriseRepository,
                        enforcedAdmin = it,
                    )
                }
        }
        return NoRestricted
    }
}
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settingslib.spaprivileged.template.preference

import android.content.Context
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.Role
import com.android.settingslib.RestrictedLockUtils
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin
import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProvider

@Composable
fun RestrictedSwitchPreference(model: SwitchPreferenceModel, restrictions: Restrictions) {
    if (restrictions.keys.isEmpty()) {
        SwitchPreference(model)
        return
    }
    val context = LocalContext.current
    val restrictionsProvider = remember { RestrictionsProvider(context, restrictions) }
    val restrictedMode = restrictionsProvider.restrictedMode.observeAsState().value ?: return
    val restrictedSwitchModel = remember(restrictedMode) {
        RestrictedSwitchPreferenceModel(context, model, restrictedMode)
    }
    Box(remember { restrictedSwitchModel.getModifier() }) {
        SwitchPreference(restrictedSwitchModel)
    }
}

private class RestrictedSwitchPreferenceModel(
    private val context: Context,
    model: SwitchPreferenceModel,
    private val restrictedMode: RestrictedMode,
) : SwitchPreferenceModel {
    override val title = model.title

    override val summary = when (restrictedMode) {
        is NoRestricted -> model.summary
        is BaseUserRestricted -> stateOf(context.getString(R.string.disabled))
        is BlockedByAdmin -> derivedStateOf { restrictedMode.getSummary(model.checked.value) }
    }

    override val checked = when (restrictedMode) {
        is NoRestricted -> model.checked
        is BaseUserRestricted -> stateOf(false)
        is BlockedByAdmin -> model.checked
    }

    override val changeable = when (restrictedMode) {
        is NoRestricted -> model.changeable
        is BaseUserRestricted -> stateOf(false)
        is BlockedByAdmin -> stateOf(false)
    }

    override val onCheckedChange = when (restrictedMode) {
        is NoRestricted -> model.onCheckedChange
        is BaseUserRestricted -> null
        is BlockedByAdmin -> null
    }

    fun getModifier(): Modifier = when (restrictedMode) {
        is BlockedByAdmin -> Modifier.clickable(role = Role.Switch) {
            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
                context, restrictedMode.enforcedAdmin
            )
        }
        else -> Modifier
    }
}