Merge changes from topics "AlarmsAndRemindersAppList", "TogglePermissionAppInfoPage-entry"

* changes:
  Add ApplicationInfo.userHandle
  Add entry item for TogglePermissionAppInfoPage
This commit is contained in:
Chaohui Wang
2022-09-20 07:32:34 +00:00
committed by Android (Google) Code Review
7 changed files with 112 additions and 56 deletions

View File

@@ -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>

View File

@@ -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"

View File

@@ -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))
}

View File

@@ -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()

View File

@@ -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))
}

View File

@@ -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(

View File

@@ -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,