diff options
18 files changed, 472 insertions, 41 deletions
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle index 8c97eca548b5..d38013679ad4 100644 --- a/packages/SettingsLib/Spa/build.gradle +++ b/packages/SettingsLib/Spa/build.gradle @@ -16,9 +16,9 @@ buildscript { ext { - minSdk_version = 31 - compose_version = '1.2.0-alpha04' - compose_material3_version = '1.0.0-alpha06' + spa_min_sdk = 31 + jetpack_compose_version = '1.2.0-alpha04' + jetpack_compose_material3_version = '1.0.0-alpha06' } } plugins { diff --git a/packages/SettingsLib/Spa/codelab/AndroidManifest.xml b/packages/SettingsLib/Spa/codelab/AndroidManifest.xml index 9a89e5efdddb..36b93134bdcb 100644 --- a/packages/SettingsLib/Spa/codelab/AndroidManifest.xml +++ b/packages/SettingsLib/Spa/codelab/AndroidManifest.xml @@ -13,14 +13,14 @@ 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. - --> +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.settingslib.spa.codelab"> <application android:label="@string/app_name" android:supportsRtl="true" - android:theme="@style/Theme.SettingsLib.Compose.DayNight"> + android:theme="@style/Theme.SpaLib.DayNight"> <activity android:name="com.android.settingslib.spa.codelab.MainActivity" android:exported="true"> diff --git a/packages/SettingsLib/Spa/codelab/build.gradle b/packages/SettingsLib/Spa/codelab/build.gradle index 5251ddd8c01d..169ecf08aeac 100644 --- a/packages/SettingsLib/Spa/codelab/build.gradle +++ b/packages/SettingsLib/Spa/codelab/build.gradle @@ -25,7 +25,7 @@ android { defaultConfig { applicationId "com.android.settingslib.spa.codelab" - minSdk minSdk_version + minSdk spa_min_sdk targetSdk 33 versionCode 1 versionName "1.0" @@ -52,7 +52,7 @@ android { compose true } composeOptions { - kotlinCompilerExtensionVersion compose_version + kotlinCompilerExtensionVersion jetpack_compose_version } packagingOptions { resources { diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle index 60794c88d00d..62f74d052471 100644 --- a/packages/SettingsLib/Spa/spa/build.gradle +++ b/packages/SettingsLib/Spa/spa/build.gradle @@ -24,7 +24,7 @@ android { compileSdk 33 defaultConfig { - minSdk minSdk_version + minSdk spa_min_sdk targetSdk 33 } @@ -49,7 +49,7 @@ android { compose true } composeOptions { - kotlinCompilerExtensionVersion compose_version + kotlinCompilerExtensionVersion jetpack_compose_version } packagingOptions { resources { @@ -59,11 +59,11 @@ android { } dependencies { - api "androidx.compose.material3:material3:$compose_material3_version" - api "androidx.compose.material:material-icons-extended:$compose_version" - api "androidx.compose.runtime:runtime-livedata:$compose_version" - api "androidx.compose.ui:ui-tooling-preview:$compose_version" + api "androidx.compose.material3:material3:$jetpack_compose_material3_version" + api "androidx.compose.material:material-icons-extended:$jetpack_compose_version" + api "androidx.compose.runtime:runtime-livedata:$jetpack_compose_version" + api "androidx.compose.ui:ui-tooling-preview:$jetpack_compose_version" api 'androidx.navigation:navigation-compose:2.5.0' api 'com.google.android.material:material:1.6.1' - debugApi "androidx.compose.ui:ui-tooling:$compose_version" + debugApi "androidx.compose.ui:ui-tooling:$jetpack_compose_version" } diff --git a/packages/SettingsLib/Spa/spa/res/values-night/themes.xml b/packages/SettingsLib/Spa/spa/res/values-night/themes.xml index 8b52b507bdd9..67dd2b0cc5e0 100644 --- a/packages/SettingsLib/Spa/spa/res/values-night/themes.xml +++ b/packages/SettingsLib/Spa/spa/res/values-night/themes.xml @@ -13,8 +13,8 @@ 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. - --> +--> <resources> - <style name="Theme.SettingsLib.Compose.DayNight" /> + <style name="Theme.SpaLib.DayNight" /> </resources> diff --git a/packages/SettingsLib/Spa/spa/res/values/themes.xml b/packages/SettingsLib/Spa/spa/res/values/themes.xml index 01f9ea592f6d..e0e5fc211ec6 100644 --- a/packages/SettingsLib/Spa/spa/res/values/themes.xml +++ b/packages/SettingsLib/Spa/spa/res/values/themes.xml @@ -13,15 +13,15 @@ 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. - --> +--> <resources> - <style name="Theme.SettingsLib.Compose" parent="Theme.Material3.DayNight.NoActionBar"> + <style name="Theme.SpaLib" parent="Theme.Material3.DayNight.NoActionBar"> <item name="android:statusBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item> </style> - <style name="Theme.SettingsLib.Compose.DayNight"> + <style name="Theme.SpaLib.DayNight"> <item name="android:windowLightStatusBar">true</item> </style> </resources> diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt new file mode 100644 index 000000000000..ae325f8862eb --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt @@ -0,0 +1,180 @@ +/* + * 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.spa.framework.compose + +import android.graphics.drawable.Animatable +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.os.Handler +import android.os.Looper +import android.view.View +import androidx.compose.runtime.Composable +import androidx.compose.runtime.RememberObserver +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.asAndroidColorFilter +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.withSave +import androidx.compose.ui.unit.LayoutDirection +import kotlin.math.roundToInt + +/** + * ************************************************************************************************* + * This file was forked from + * https://github.com/google/accompanist/blob/main/drawablepainter/src/main/java/com/google/accompanist/drawablepainter/DrawablePainter.kt + * and will be removed once it lands in AndroidX. + */ + +private val MAIN_HANDLER by lazy(LazyThreadSafetyMode.NONE) { + Handler(Looper.getMainLooper()) +} + +/** + * A [Painter] which draws an Android [Drawable] and supports [Animatable] drawables. Instances + * should be remembered to be able to start and stop [Animatable] animations. + * + * Instances are usually retrieved from [rememberDrawablePainter]. + */ +class DrawablePainter( + val drawable: Drawable +) : Painter(), RememberObserver { + private var drawInvalidateTick by mutableStateOf(0) + private var drawableIntrinsicSize by mutableStateOf(drawable.intrinsicSize) + + private val callback: Drawable.Callback by lazy { + object : Drawable.Callback { + override fun invalidateDrawable(d: Drawable) { + // Update the tick so that we get re-drawn + drawInvalidateTick++ + // Update our intrinsic size too + drawableIntrinsicSize = drawable.intrinsicSize + } + + override fun scheduleDrawable(d: Drawable, what: Runnable, time: Long) { + MAIN_HANDLER.postAtTime(what, time) + } + + override fun unscheduleDrawable(d: Drawable, what: Runnable) { + MAIN_HANDLER.removeCallbacks(what) + } + } + } + + init { + if (drawable.intrinsicWidth >= 0 && drawable.intrinsicHeight >= 0) { + // Update the drawable's bounds to match the intrinsic size + drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight) + } + } + + override fun onRemembered() { + drawable.callback = callback + drawable.setVisible(true, true) + if (drawable is Animatable) drawable.start() + } + + override fun onAbandoned() = onForgotten() + + override fun onForgotten() { + if (drawable is Animatable) drawable.stop() + drawable.setVisible(false, false) + drawable.callback = null + } + + override fun applyAlpha(alpha: Float): Boolean { + drawable.alpha = (alpha * 255).roundToInt().coerceIn(0, 255) + return true + } + + override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { + drawable.colorFilter = colorFilter?.asAndroidColorFilter() + return true + } + + override fun applyLayoutDirection(layoutDirection: LayoutDirection): Boolean = + drawable.setLayoutDirection( + when (layoutDirection) { + LayoutDirection.Ltr -> View.LAYOUT_DIRECTION_LTR + LayoutDirection.Rtl -> View.LAYOUT_DIRECTION_RTL + } + ) + + override val intrinsicSize: Size get() = drawableIntrinsicSize + + override fun DrawScope.onDraw() { + drawIntoCanvas { canvas -> + // Reading this ensures that we invalidate when invalidateDrawable() is called + drawInvalidateTick + + // Update the Drawable's bounds + drawable.setBounds(0, 0, size.width.roundToInt(), size.height.roundToInt()) + + canvas.withSave { + drawable.draw(canvas.nativeCanvas) + } + } + } +} + +/** + * Remembers [Drawable] wrapped up as a [Painter]. This function attempts to un-wrap the + * drawable contents and use Compose primitives where possible. + * + * If the provided [drawable] is `null`, an empty no-op painter is returned. + * + * This function tries to dispatch lifecycle events to [drawable] as much as possible from + * within Compose. + * + * @sample com.google.accompanist.sample.drawablepainter.BasicSample + */ +@Composable +fun rememberDrawablePainter(drawable: Drawable?): Painter = remember(drawable) { + when (drawable) { + null -> EmptyPainter + is BitmapDrawable -> BitmapPainter(drawable.bitmap.asImageBitmap()) + is ColorDrawable -> ColorPainter(Color(drawable.color)) + // Since the DrawablePainter will be remembered and it implements RememberObserver, it + // will receive the necessary events + else -> DrawablePainter(drawable.mutate()) + } +} + +private val Drawable.intrinsicSize: Size + get() = when { + // Only return a finite size if the drawable has an intrinsic size + intrinsicWidth >= 0 && intrinsicHeight >= 0 -> { + Size(width = intrinsicWidth.toFloat(), height = intrinsicHeight.toFloat()) + } + else -> Size.Unspecified + } + +internal object EmptyPainter : Painter() { + override val intrinsicSize: Size get() = Size.Unspecified + override fun DrawScope.onDraw() {} +} diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/RuntimeUtils.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/RuntimeUtils.kt index 7c8608da6724..ba8854653b0b 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/RuntimeUtils.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/RuntimeUtils.kt @@ -16,9 +16,17 @@ package com.android.settingslib.spa.framework.compose +import android.content.Context import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext + +@Composable +fun <T> rememberContext(constructor: (Context) -> T): T { + val context = LocalContext.current + return remember(context) { constructor(context) } +} /** * Remember the [State] initialized with the [this]. diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt index 6bdc294d888a..9a34dbf36735 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt @@ -25,8 +25,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Divider -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.ui.Alignment @@ -39,6 +37,7 @@ import com.android.settingslib.spa.framework.compose.toState import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsOpacity import com.android.settingslib.spa.framework.theme.SettingsTheme +import com.android.settingslib.spa.widget.ui.SettingsTitle @Composable internal fun BaseLayout( @@ -94,11 +93,7 @@ private fun BaseIcon( @Composable private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) { Column(modifier) { - Text( - text = title, - color = MaterialTheme.colorScheme.onSurface, - style = MaterialTheme.typography.titleMedium, - ) + SettingsTitle(title) subTitle() } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt index 3b99d36e630b..4b2c8e41a388 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt @@ -19,8 +19,6 @@ package com.android.settingslib.spa.widget.preference import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.BatteryChargingFull import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.ui.Modifier @@ -29,6 +27,7 @@ import androidx.compose.ui.unit.Dp import com.android.settingslib.spa.framework.compose.toState import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.theme.SettingsTheme +import com.android.settingslib.spa.widget.ui.SettingsBody @Composable internal fun BasePreference( @@ -44,15 +43,7 @@ internal fun BasePreference( ) { BaseLayout( title = title, - subTitle = { - if (summary.value.isNotEmpty()) { - Text( - text = summary.value, - color = MaterialTheme.colorScheme.onSurfaceVariant, - style = MaterialTheme.typography.bodyMedium, - ) - } - }, + subTitle = { SettingsBody(summary) }, modifier = modifier, icon = icon, enabled = enabled, diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt new file mode 100644 index 000000000000..a414c89dc24c --- /dev/null +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Text.kt @@ -0,0 +1,52 @@ +/* + * 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.spa.widget.ui + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State + +@Composable +fun SettingsTitle(title: State<String>) { + SettingsTitle(title.value) +} + +@Composable +fun SettingsTitle(title: String) { + Text( + text = title, + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.titleMedium, + ) +} + +@Composable +fun SettingsBody(body: State<String>) { + SettingsBody(body.value) +} + +@Composable +fun SettingsBody(body: String) { + if (body.isNotEmpty()) { + Text( + text = body, + color = MaterialTheme.colorScheme.onSurfaceVariant, + style = MaterialTheme.typography.bodyMedium, + ) + } +} diff --git a/packages/SettingsLib/Spa/tests/build.gradle b/packages/SettingsLib/Spa/tests/build.gradle index 707017e7e17f..be5a5ec40c4f 100644 --- a/packages/SettingsLib/Spa/tests/build.gradle +++ b/packages/SettingsLib/Spa/tests/build.gradle @@ -24,7 +24,7 @@ android { compileSdk 33 defaultConfig { - minSdk minSdk_version + minSdk spa_min_sdk targetSdk 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -50,7 +50,7 @@ android { compose true } composeOptions { - kotlinCompilerExtensionVersion compose_version + kotlinCompilerExtensionVersion jetpack_compose_version } packagingOptions { resources { @@ -62,6 +62,6 @@ android { dependencies { androidTestImplementation(project(":spa")) androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3' - androidTestImplementation("androidx.compose.ui:ui-test-junit4:$compose_version") - androidTestDebugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" + androidTestImplementation("androidx.compose.ui:ui-test-junit4:$jetpack_compose_version") + androidTestDebugImplementation "androidx.compose.ui:ui-test-manifest:$jetpack_compose_version" } diff --git a/packages/SettingsLib/SpaPrivileged/Android.bp b/packages/SettingsLib/SpaPrivileged/Android.bp new file mode 100644 index 000000000000..48f7ff270ac7 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/Android.bp @@ -0,0 +1,33 @@ +// +// 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 { + default_applicable_licenses: ["frameworks_base_license"], +} + +android_library { + name: "SpaPrivilegedLib", + + srcs: ["src/**/*.kt"], + + static_libs: [ + "SpaLib", + "SettingsLib", + "androidx.compose.runtime_runtime", + ], + kotlincflags: ["-Xjvm-default=all"], + min_sdk_version: "31", +} diff --git a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml new file mode 100644 index 000000000000..2efa10744bb3 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<manifest package="com.android.settingslib.spaprivileged" /> diff --git a/packages/SettingsLib/SpaPrivileged/OWNERS b/packages/SettingsLib/SpaPrivileged/OWNERS new file mode 100644 index 000000000000..9256ca5cc2b0 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/base:/packages/SettingsLib/Spa/OWNERS diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt new file mode 100644 index 000000000000..a6378ef53437 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/AppRepository.kt @@ -0,0 +1,58 @@ +/* + * 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.framework.app + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.graphics.drawable.Drawable +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.produceState +import com.android.settingslib.Utils +import com.android.settingslib.spa.framework.compose.rememberContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +@Composable +fun rememberAppRepository(): AppRepository = rememberContext(::AppRepositoryImpl) + +interface AppRepository { + @Composable + fun produceLabel(app: ApplicationInfo): State<String> + + @Composable + fun produceIcon(app: ApplicationInfo): State<Drawable?> +} + +private class AppRepositoryImpl(private val context: Context) : AppRepository { + private val packageManager = context.packageManager + + @Composable + override fun produceLabel(app: ApplicationInfo) = produceState(initialValue = "", app) { + withContext(Dispatchers.Default) { + value = app.loadLabel(packageManager).toString() + } + } + + @Composable + override fun produceIcon(app: ApplicationInfo) = + produceState<Drawable?>(initialValue = null, app) { + withContext(Dispatchers.Default) { + value = Utils.getBadgedIcon(context, app) + } + } +} diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt new file mode 100644 index 000000000000..5a3e66619c39 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/app/PackageManagers.kt @@ -0,0 +1,25 @@ +/* + * 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.framework.app + +import android.content.pm.PackageInfo +import android.content.pm.PackageManager + +object PackageManagers { + fun getPackageInfoAsUser(packageName: String, userId: Int): PackageInfo = + PackageManager.getPackageInfoAsUserCached(packageName, 0, userId) +} diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt new file mode 100644 index 000000000000..5ae514cfb524 --- /dev/null +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt @@ -0,0 +1,70 @@ +/* + * 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.app + +import android.content.pm.ApplicationInfo +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +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.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.android.settingslib.spa.framework.compose.rememberDrawablePainter +import com.android.settingslib.spa.widget.ui.SettingsBody +import com.android.settingslib.spa.widget.ui.SettingsTitle +import com.android.settingslib.spaprivileged.framework.app.PackageManagers +import com.android.settingslib.spaprivileged.framework.app.rememberAppRepository + +@Composable +fun AppInfo(packageName: String, userId: Int) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally) { + val packageInfo = remember { PackageManagers.getPackageInfoAsUser(packageName, userId) } + Box(modifier = Modifier.padding(8.dp)) { + AppIcon(app = packageInfo.applicationInfo, size = 48) + } + AppLabel(packageInfo.applicationInfo) + Spacer(modifier = Modifier.height(4.dp)) + SettingsBody(packageInfo.versionName) + } +} + +@Composable +fun AppIcon(app: ApplicationInfo, size: Int) { + val appRepository = rememberAppRepository() + Image( + painter = rememberDrawablePainter(appRepository.produceIcon(app).value), + contentDescription = null, + modifier = Modifier.size(size.dp) + ) +} + +@Composable +fun AppLabel(app: ApplicationInfo) { + val appRepository = rememberAppRepository() + SettingsTitle(appRepository.produceLabel(app)) +} |