1 /*
<lambda>null2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.settings.spa.app.appinfo
18
19 import android.app.settings.SettingsEnums
20 import android.content.pm.ApplicationInfo
21 import android.os.Bundle
22 import android.os.SystemProperties
23 import android.os.UserHandle
24 import android.util.FeatureFlagUtils
25 import androidx.compose.runtime.Composable
26 import androidx.compose.runtime.remember
27 import androidx.compose.runtime.rememberCoroutineScope
28 import androidx.compose.ui.platform.LocalContext
29 import androidx.compose.ui.res.stringResource
30 import androidx.fragment.app.Fragment
31 import androidx.lifecycle.compose.collectAsStateWithLifecycle
32 import androidx.navigation.NavType
33 import androidx.navigation.navArgument
34 import com.android.settings.R
35 import com.android.settings.applications.AppInfoBase
36 import com.android.settings.applications.appinfo.AppInfoDashboardFragment
37 import com.android.settings.development.Enable16kUtils
38 import com.android.settings.flags.Flags
39 import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
40 import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
41 import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
42 import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider
43 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
44 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
45 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
46 import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider
47 import com.android.settingslib.spa.framework.common.SettingsPageProvider
48 import com.android.settingslib.spa.framework.compose.navigator
49 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
50 import com.android.settingslib.spa.widget.ui.Category
51 import com.android.settingslib.spaprivileged.model.app.toRoute
52 import com.android.settingslib.spaprivileged.template.app.AppInfoProvider
53 import kotlinx.coroutines.flow.MutableStateFlow
54 import android.content.pm.FeatureFlags as PmFeatureFlags
55 import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl
56
57 private const val PACKAGE_NAME = "packageName"
58 private const val USER_ID = "userId"
59
60 object AppInfoSettingsProvider : SettingsPageProvider {
61 override val name = "AppInfoSettings"
62
63 override val parameter = listOf(
64 navArgument(PACKAGE_NAME) { type = NavType.StringType },
65 navArgument(USER_ID) { type = NavType.IntType },
66 )
67
68 const val METRICS_CATEGORY = SettingsEnums.APPLICATIONS_INSTALLED_APP_DETAILS
69
70 @Composable
71 override fun Page(arguments: Bundle?) {
72 val packageName = arguments!!.getString(PACKAGE_NAME)!!
73 val userId = arguments.getInt(USER_ID)
74 val context = LocalContext.current
75 val coroutineScope = rememberCoroutineScope()
76 val packageInfoPresenter = remember {
77 PackageInfoPresenter(context, packageName, userId, coroutineScope)
78 }
79 AppInfoSettings(packageInfoPresenter)
80 packageInfoPresenter.PackageFullyRemovedEffect()
81 }
82
83 @Composable
84 fun navigator(app: ApplicationInfo) = navigator(route = "$name/${app.toRoute()}")
85
86 /**
87 * Gets the route to the App Info Settings page.
88 *
89 * Expose route to enable enter from non-SPA pages.
90 */
91 fun getRoute(packageName: String, userId: Int): String = "$name/$packageName/$userId"
92
93 /**
94 * Starts the App Info Settings page from non-SPA.
95 *
96 * Will starts SPA version if flag [FeatureFlagUtils.SETTINGS_ENABLE_SPA] is true.
97 */
98 @JvmStatic
99 fun startAppInfoSettings(
100 packageName: String,
101 uid: Int,
102 source: Fragment,
103 request: Int,
104 sourceMetricsCategory: Int,
105 ) {
106 val context = source.context ?: return
107 if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_ENABLE_SPA)) {
108 context.startSpaActivity(getRoute(packageName, UserHandle.getUserId(uid)))
109 } else {
110 AppInfoBase.startAppInfoFragment(
111 AppInfoDashboardFragment::class.java,
112 context.getString(R.string.application_info_label),
113 packageName,
114 uid,
115 source,
116 request,
117 sourceMetricsCategory,
118 )
119 }
120 }
121 }
122
123 @Composable
AppInfoSettingsnull124 private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
125 val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle()
126 val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
127 RegularScaffold(
128 title = stringResource(R.string.application_info_label),
129 actions = {
130 packageInfoState.value?.applicationInfo?.let { app ->
131 if (isArchivingEnabled(featureFlags)) TopBarAppLaunchButton(packageInfoPresenter, app)
132 AppInfoSettingsMoreOptions(packageInfoPresenter, app)
133 }
134 }
135 ) {
136 val packageInfo = packageInfoState.value ?: return@RegularScaffold
137 val app = packageInfo.applicationInfo ?: return@RegularScaffold
138 val appInfoProvider = remember(packageInfo) { AppInfoProvider(packageInfo) }
139 val isHibernationSwitchEnabledStateFlow = MutableStateFlow(false)
140
141 appInfoProvider.AppInfo()
142
143 AppButtons(packageInfoPresenter, isHibernationSwitchEnabledStateFlow)
144
145 Category {
146 AppSettingsPreference(app)
147 AppAllServicesPreference(app)
148 AppNotificationPreference(app)
149 AppPermissionPreference(app)
150 AppStoragePreference(app)
151 InstantAppDomainsPreference(app)
152 AppDataUsagePreference(app)
153 AppTimeSpentPreference(app)
154 AppBatteryPreference(app)
155 AppLocalePreference(app)
156 AppOpenByDefaultPreference(app)
157 DefaultAppShortcuts(app)
158 }
159
160 Category(title = stringResource(R.string.unused_apps_category)) {
161 HibernationSwitchPreference(app, isHibernationSwitchEnabledStateFlow)
162 }
163
164 Category(title = stringResource(R.string.advanced_apps)) {
165 UserAspectRatioAppPreference(app)
166 DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app)
167 ModifySystemSettingsAppListProvider.InfoPageEntryItem(app)
168 PictureInPictureListProvider.InfoPageEntryItem(app)
169 InstallUnknownAppsListProvider.InfoPageEntryItem(app)
170 InteractAcrossProfilesDetailsPreference(app)
171 AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
172 WriteSystemPreferencesAppListProvider.InfoPageEntryItem(app)
173 Enable16KbAppCompatPreference(app, packageInfoPresenter)
174 }
175
176 Category(title = stringResource(R.string.app_install_details_group_title)) {
177 AppInstallerInfoPreference(app)
178 }
179 appInfoProvider.FooterAppVersion()
180 }
181 }
182
isArchivingEnablednull183 fun isArchivingEnabled(featureFlags: PmFeatureFlags) =
184 featureFlags.archiving() || Flags.appArchiving()