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

Commit 046ea61c authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "Add SpaLib for Settings"

parents f53c8be2 805f903a
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ android_library {
    defaults: [
        "SettingsLibDefaults",
        "SettingsLib-search-defaults",
        "SpaPrivilegedLib-defaults",
    ],

    srcs: ["src/**/*.java", "src/**/*.kt"],
@@ -63,6 +64,7 @@ android_library {
        "androidx.core_core",
        "androidx.appcompat_appcompat",
        "androidx.cardview_cardview",
        "androidx.compose.runtime_runtime-livedata",
        "androidx.preference_preference",
        "androidx.recyclerview_recyclerview",
        "androidx.window_window",
@@ -103,7 +105,10 @@ platform_compat_config {

android_app {
    name: "Settings",
    defaults: ["platform_app_defaults"],
    defaults: [
        "platform_app_defaults",
        "SpaPrivilegedLib-defaults",
    ],
    platform_apis: true,
    certificate: "platform",
    system_ext_specific: true,
+5 −0
Original line number Diff line number Diff line
@@ -4584,6 +4584,11 @@
            </intent-filter>
        </activity>

        <activity
            android:name="com.android.settings.spa.SpaActivity"
            android:exported="false">
        </activity>

        <!-- This is the longest AndroidManifest.xml ever. -->
    </application>
</manifest>
+21 −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.settings.spa

import com.android.settingslib.spa.framework.BrowseActivity

class SpaActivity : BrowseActivity(settingsPageProviders)
+33 −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.settings.spa

import com.android.settings.spa.app.InstallUnknownAppsListProvider
import com.android.settings.spa.home.HomePageProvider
import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListTemplate

private val togglePermissionAppListTemplate = TogglePermissionAppListTemplate(
    allProviders = listOf(InstallUnknownAppsListProvider),
)

val settingsPageProviders = SettingsPageProviderRepository(
    allPagesList = listOf(
        HomePageProvider,
    ) + togglePermissionAppListTemplate.createPageProviders(),
    rootPages = listOf(HomePageProvider.name),
)
+94 −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.settings.spa.app

import android.Manifest
import android.app.AppGlobals
import android.app.AppOpsManager.MODE_DEFAULT
import android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES
import android.content.Context
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import com.android.settings.R
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.userId
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map

object InstallUnknownAppsListProvider : TogglePermissionAppListProvider {
    override val permissionType = "InstallUnknownApps"
    override fun createModel(context: Context) = InstallUnknownAppsListModel(context)
}

data class InstallUnknownAppsRecord(
    override val app: ApplicationInfo,
    val appOpsController: AppOpsController,
) : AppRecord

class InstallUnknownAppsListModel(private val context: Context) :
    TogglePermissionAppListModel<InstallUnknownAppsRecord> {
    override val pageTitleResId = R.string.install_other_apps
    override val switchTitleResId = R.string.external_source_switch_title
    override val footerResId = R.string.install_all_warning

    override fun transformItem(app: ApplicationInfo) = InstallUnknownAppsRecord(
        app = app,
        appOpsController = AppOpsController(
            context = context,
            app = app,
            op = OP_REQUEST_INSTALL_PACKAGES,
        ),
    )

    override fun filter(
        userIdFlow: Flow<Int>, recordListFlow: Flow<List<InstallUnknownAppsRecord>>,
    ) = userIdFlow.map(::getPotentialPackageNames)
        .combine(recordListFlow) { potentialPackageNames, recordList ->
            recordList.filter { record ->
                isChangeable(record, potentialPackageNames)
            }
        }

    @Composable
    override fun isAllowed(record: InstallUnknownAppsRecord) =
        record.appOpsController.isAllowed.observeAsState()

    override fun isChangeable(record: InstallUnknownAppsRecord) =
        isChangeable(record, getPotentialPackageNames(record.app.userId))

    override fun setAllowed(record: InstallUnknownAppsRecord, newAllowed: Boolean) {
        record.appOpsController.setAllowed(newAllowed)
    }

    companion object {
        private fun isChangeable(
            record: InstallUnknownAppsRecord,
            potentialPackageNames: Set<String>,
        ) = record.appOpsController.getMode() != MODE_DEFAULT ||
                record.app.packageName in potentialPackageNames

        private fun getPotentialPackageNames(userId: Int): Set<String> =
            AppGlobals.getPackageManager().getAppOpPermissionPackages(
                Manifest.permission.REQUEST_INSTALL_PACKAGES, userId
            ).toSet()
    }
}
Loading