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.flags.Flags
38 import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
39 import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
40 import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
41 import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider
42 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
43 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
44 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
45 import com.android.settingslib.spa.framework.common.SettingsPageProvider
46 import com.android.settingslib.spa.framework.compose.navigator
47 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
48 import com.android.settingslib.spa.widget.ui.Category
49 import com.android.settingslib.spaprivileged.model.app.toRoute
50 import com.android.settingslib.spaprivileged.template.app.AppInfoProvider
51 import kotlinx.coroutines.flow.MutableStateFlow
52 import android.content.pm.FeatureFlags as PmFeatureFlags
53 import android.content.pm.FeatureFlagsImpl as PmFeatureFlagsImpl
54
55 private const val PACKAGE_NAME = "packageName"
56 private const val USER_ID = "userId"
57
58 object AppInfoSettingsProvider : SettingsPageProvider {
59 override val name = "AppInfoSettings"
60
61 override val parameter = listOf(
62 navArgument(PACKAGE_NAME) { type = NavType.StringType },
63 navArgument(USER_ID) { type = NavType.IntType },
64 )
65
66 const val METRICS_CATEGORY = SettingsEnums.APPLICATIONS_INSTALLED_APP_DETAILS
67
68 @Composable
69 override fun Page(arguments: Bundle?) {
70 val packageName = arguments!!.getString(PACKAGE_NAME)!!
71 val userId = arguments.getInt(USER_ID)
72 val context = LocalContext.current
73 val coroutineScope = rememberCoroutineScope()
74 val packageInfoPresenter = remember {
75 PackageInfoPresenter(context, packageName, userId, coroutineScope)
76 }
77 AppInfoSettings(packageInfoPresenter)
78 packageInfoPresenter.PackageFullyRemovedEffect()
79 }
80
81 @Composable
82 fun navigator(app: ApplicationInfo) = navigator(route = "$name/${app.toRoute()}")
83
84 /**
85 * Gets the route to the App Info Settings page.
86 *
87 * Expose route to enable enter from non-SPA pages.
88 */
89 fun getRoute(packageName: String, userId: Int): String = "$name/$packageName/$userId"
90
91 /**
92 * Starts the App Info Settings page from non-SPA.
93 *
94 * Will starts SPA version if flag [FeatureFlagUtils.SETTINGS_ENABLE_SPA] is true.
95 */
96 @JvmStatic
97 fun startAppInfoSettings(
98 packageName: String,
99 uid: Int,
100 source: Fragment,
101 request: Int,
102 sourceMetricsCategory: Int,
103 ) {
104 val context = source.context ?: return
105 if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_ENABLE_SPA)) {
106 context.startSpaActivity(getRoute(packageName, UserHandle.getUserId(uid)))
107 } else {
108 AppInfoBase.startAppInfoFragment(
109 AppInfoDashboardFragment::class.java,
110 context.getString(R.string.application_info_label),
111 packageName,
112 uid,
113 source,
114 request,
115 sourceMetricsCategory,
116 )
117 }
118 }
119 }
120
121 @Composable
AppInfoSettingsnull122 private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
123 val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle()
124 val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
125 RegularScaffold(
126 title = stringResource(R.string.application_info_label),
127 actions = {
128 packageInfoState.value?.applicationInfo?.let { app ->
129 if (isArchivingEnabled(featureFlags)) TopBarAppLaunchButton(packageInfoPresenter, app)
130 AppInfoSettingsMoreOptions(packageInfoPresenter, app)
131 }
132 }
133 ) {
134 val packageInfo = packageInfoState.value ?: return@RegularScaffold
135 val app = packageInfo.applicationInfo ?: return@RegularScaffold
136 val appInfoProvider = remember(packageInfo) { AppInfoProvider(packageInfo) }
137 val isHibernationSwitchEnabledStateFlow = MutableStateFlow(false)
138
139 appInfoProvider.AppInfo()
140
141 AppButtons(packageInfoPresenter, isHibernationSwitchEnabledStateFlow)
142
143 AppSettingsPreference(app)
144 AppAllServicesPreference(app)
145 AppNotificationPreference(app)
146 AppPermissionPreference(app)
147 AppStoragePreference(app)
148 InstantAppDomainsPreference(app)
149 AppDataUsagePreference(app)
150 AppTimeSpentPreference(app)
151 AppBatteryPreference(app)
152 AppLocalePreference(app)
153 AppOpenByDefaultPreference(app)
154 DefaultAppShortcuts(app)
155
156 Category(title = stringResource(R.string.unused_apps_category)) {
157 HibernationSwitchPreference(app, isHibernationSwitchEnabledStateFlow)
158 }
159
160 Category(title = stringResource(R.string.advanced_apps)) {
161 UserAspectRatioAppPreference(app)
162 DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app)
163 ModifySystemSettingsAppListProvider.InfoPageEntryItem(app)
164 PictureInPictureListProvider.InfoPageEntryItem(app)
165 InstallUnknownAppsListProvider.InfoPageEntryItem(app)
166 InteractAcrossProfilesDetailsPreference(app)
167 AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
168 }
169
170 Category(title = stringResource(R.string.app_install_details_group_title)) {
171 AppInstallerInfoPreference(app)
172 }
173 appInfoProvider.FooterAppVersion()
174 }
175 }
176
isArchivingEnablednull177 fun isArchivingEnabled(featureFlags: PmFeatureFlags) =
178 featureFlags.archiving() || Flags.appArchiving()