Merge changes from topics "AlarmsAndRemindersAppList", "TogglePermissionAppInfoPage-entry"
* changes: Add ApplicationInfo.userHandle Add entry item for TogglePermissionAppInfoPage
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- [CHAR LIMIT=25] Text shown when there are no applications to display. -->
|
||||
<string name="no_applications">No apps.</string>
|
||||
<!-- [CHAR LIMIT=NONE] Menu for manage apps to control whether system processes are shown -->
|
||||
@@ -25,4 +25,6 @@
|
||||
<string name="app_permission_summary_allowed">Allowed</string>
|
||||
<!-- Preference summary text for an app when it is disallowed for a permission. [CHAR LIMIT=45] -->
|
||||
<string name="app_permission_summary_not_allowed">Not allowed</string>
|
||||
<!-- Manage applications, version string displayed in app snippet -->
|
||||
<string name="version_text">version <xliff:g id="version_num">%1$s</xliff:g></string>
|
||||
</resources>
|
||||
|
||||
@@ -22,4 +22,7 @@ import android.os.UserHandle
|
||||
val ApplicationInfo.userId: Int
|
||||
get() = UserHandle.getUserId(uid)
|
||||
|
||||
val ApplicationInfo.userHandle: UserHandle
|
||||
get() = UserHandle.getUserHandleForUid(uid)
|
||||
|
||||
fun ApplicationInfo.toRoute() = "$packageName/$userId"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.settingslib.spaprivileged.template.app
|
||||
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.text.BidiFormatter
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -25,49 +27,60 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.android.settingslib.spa.framework.compose.rememberDrawablePainter
|
||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||
import com.android.settingslib.spa.widget.ui.SettingsBody
|
||||
import com.android.settingslib.spa.widget.ui.SettingsTitle
|
||||
import com.android.settingslib.spaprivileged.model.app.PackageManagers
|
||||
import com.android.settingslib.spaprivileged.R
|
||||
import com.android.settingslib.spaprivileged.model.app.rememberAppRepository
|
||||
|
||||
@Composable
|
||||
fun AppInfo(packageName: String, userId: Int) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
horizontal = SettingsDimension.itemPaddingStart,
|
||||
vertical = SettingsDimension.itemPaddingVertical,
|
||||
),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
val packageInfo =
|
||||
remember { PackageManagers.getPackageInfoAsUser(packageName, userId) } ?: return
|
||||
Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
|
||||
AppIcon(app = packageInfo.applicationInfo, size = SettingsDimension.appIconInfoSize)
|
||||
class AppInfoProvider(private val packageInfo: PackageInfo) {
|
||||
@Composable
|
||||
fun AppInfo(displayVersion: Boolean = false) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
horizontal = SettingsDimension.itemPaddingStart,
|
||||
vertical = SettingsDimension.itemPaddingVertical,
|
||||
),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Box(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
|
||||
AppIcon(app = packageInfo.applicationInfo, size = SettingsDimension.appIconInfoSize)
|
||||
}
|
||||
AppLabel(packageInfo.applicationInfo)
|
||||
if (displayVersion) AppVersion()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppVersion() {
|
||||
if (packageInfo.versionName == null) return
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
SettingsBody(packageInfo.versionName)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FooterAppVersion() {
|
||||
if (packageInfo.versionName == null) return
|
||||
Divider()
|
||||
Box(modifier = Modifier.padding(SettingsDimension.itemPadding)) {
|
||||
val versionName = BidiFormatter.getInstance().unicodeWrap(packageInfo.versionName)
|
||||
SettingsBody(stringResource(R.string.version_text, versionName))
|
||||
}
|
||||
AppLabel(packageInfo.applicationInfo)
|
||||
AppVersion(packageInfo.versionName)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppVersion(versionName: String?) {
|
||||
if (versionName == null) return
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
SettingsBody(versionName)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppIcon(app: ApplicationInfo, size: Dp) {
|
||||
internal fun AppIcon(app: ApplicationInfo, size: Dp) {
|
||||
val appRepository = rememberAppRepository()
|
||||
Image(
|
||||
painter = rememberDrawablePainter(appRepository.produceIcon(app).value),
|
||||
@@ -77,7 +90,7 @@ fun AppIcon(app: ApplicationInfo, size: Dp) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppLabel(app: ApplicationInfo) {
|
||||
internal fun AppLabel(app: ApplicationInfo) {
|
||||
val appRepository = rememberAppRepository()
|
||||
SettingsTitle(appRepository.produceLabel(app))
|
||||
}
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package com.android.settingslib.spaprivileged.template.app
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||
import com.android.settingslib.spa.widget.ui.Footer
|
||||
import com.android.settingslib.spaprivileged.model.app.PackageManagers
|
||||
|
||||
@Composable
|
||||
fun AppInfoPage(
|
||||
@@ -29,7 +31,12 @@ fun AppInfoPage(
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
RegularScaffold(title = title) {
|
||||
AppInfo(packageName, userId)
|
||||
val appInfoProvider = remember {
|
||||
val packageInfo = PackageManagers.getPackageInfoAsUser(packageName, userId)
|
||||
?: return@RegularScaffold
|
||||
AppInfoProvider(packageInfo)
|
||||
}
|
||||
appInfoProvider.AppInfo(displayVersion = true)
|
||||
|
||||
content()
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
import com.android.settingslib.spaprivileged.model.app.PackageManagers
|
||||
@@ -80,10 +82,31 @@ internal class TogglePermissionAppInfoPageProvider(
|
||||
|
||||
companion object {
|
||||
@Composable
|
||||
internal fun navigator(permissionType: String, app: ApplicationInfo) =
|
||||
fun navigator(permissionType: String, app: ApplicationInfo) =
|
||||
navigator(route = "$PAGE_NAME/$permissionType/${app.toRoute()}")
|
||||
|
||||
internal fun buildPageData(permissionType: String): SettingsPage {
|
||||
@Composable
|
||||
fun <T : AppRecord> EntryItem(
|
||||
permissionType: String,
|
||||
app: ApplicationInfo,
|
||||
listModel: TogglePermissionAppListModel<T>,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val internalListModel = remember {
|
||||
TogglePermissionInternalAppListModel(context, listModel)
|
||||
}
|
||||
val record = remember { listModel.transformItem(app) }
|
||||
if (!remember { listModel.isChangeable(record) }) return
|
||||
Preference(
|
||||
object : PreferenceModel {
|
||||
override val title = stringResource(listModel.pageTitleResId)
|
||||
override val summary = internalListModel.getSummary(record)
|
||||
override val onClick = navigator(permissionType, app)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun buildPageData(permissionType: String): SettingsPage {
|
||||
return SettingsPage.create(
|
||||
PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType))
|
||||
}
|
||||
|
||||
@@ -20,13 +20,10 @@ import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.util.asyncMapItem
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -85,28 +82,22 @@ interface TogglePermissionAppListProvider {
|
||||
|
||||
fun createModel(context: Context): TogglePermissionAppListModel<out AppRecord>
|
||||
|
||||
fun buildInjectEntry(): SettingsEntryBuilder {
|
||||
return TogglePermissionAppListPageProvider.buildInjectEntry(permissionType)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EntryItem() {
|
||||
val listModel = rememberContext(::createModel)
|
||||
Preference(
|
||||
object : PreferenceModel {
|
||||
override val title = stringResource(listModel.pageTitleResId)
|
||||
override val onClick = TogglePermissionAppListPageProvider.navigator(permissionType)
|
||||
}
|
||||
)
|
||||
}
|
||||
fun buildAppListInjectEntry(): SettingsEntryBuilder =
|
||||
TogglePermissionAppListPageProvider.buildInjectEntry(permissionType) { createModel(it) }
|
||||
|
||||
/**
|
||||
* Gets the route to the toggle permission App List page.
|
||||
*
|
||||
* Expose route to enable enter from non-SPA pages.
|
||||
*/
|
||||
fun getRoute(): String =
|
||||
fun getAppListRoute(): String =
|
||||
TogglePermissionAppListPageProvider.getRoute(permissionType)
|
||||
|
||||
@Composable
|
||||
fun InfoPageEntryItem(app: ApplicationInfo) {
|
||||
val listModel = rememberContext(::createModel)
|
||||
TogglePermissionAppInfoPageProvider.EntryItem(permissionType, app, listModel)
|
||||
}
|
||||
}
|
||||
|
||||
class TogglePermissionAppListTemplate(
|
||||
|
||||
@@ -34,7 +34,10 @@ import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.util.getStringArg
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spaprivileged.R
|
||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
@@ -107,20 +110,29 @@ internal class TogglePermissionAppListPageProvider(
|
||||
*
|
||||
* Expose route to enable enter from non-SPA pages.
|
||||
*/
|
||||
internal fun getRoute(permissionType: String) = "$PAGE_NAME/$permissionType"
|
||||
fun getRoute(permissionType: String) = "$PAGE_NAME/$permissionType"
|
||||
|
||||
@Composable
|
||||
internal fun navigator(permissionType: String) = navigator(route = getRoute(permissionType))
|
||||
|
||||
internal fun buildInjectEntry(permissionType: String): SettingsEntryBuilder {
|
||||
fun buildInjectEntry(
|
||||
permissionType: String,
|
||||
listModelSupplier: (Context) -> TogglePermissionAppListModel<out AppRecord>,
|
||||
): SettingsEntryBuilder {
|
||||
val appListPage = SettingsPage.create(
|
||||
PAGE_NAME, PAGE_PARAMETER, bundleOf(PERMISSION to permissionType))
|
||||
return SettingsEntryBuilder.createInject(owner = appListPage).setIsAllowSearch(false)
|
||||
.setUiLayoutFn {
|
||||
val listModel = rememberContext(listModelSupplier)
|
||||
Preference(
|
||||
object : PreferenceModel {
|
||||
override val title = stringResource(listModel.pageTitleResId)
|
||||
override val onClick = navigator(route = getRoute(permissionType))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TogglePermissionInternalAppListModel<T : AppRecord>(
|
||||
internal class TogglePermissionInternalAppListModel<T : AppRecord>(
|
||||
private val context: Context,
|
||||
private val listModel: TogglePermissionAppListModel<T>,
|
||||
) : AppListModel<T> {
|
||||
@@ -132,6 +144,11 @@ private class TogglePermissionInternalAppListModel<T : AppRecord>(
|
||||
|
||||
@Composable
|
||||
override fun getSummary(option: Int, record: T): State<String> {
|
||||
return getSummary(record)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getSummary(record: T): State<String> {
|
||||
val restrictionsProvider = remember {
|
||||
val restrictions = Restrictions(
|
||||
userId = record.app.userId,
|
||||
|
||||
Reference in New Issue
Block a user