• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()