1 /*
2 * 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.UserHandle
23 import android.util.FeatureFlagUtils
24 import androidx.compose.runtime.Composable
25 import androidx.compose.runtime.remember
26 import androidx.compose.runtime.rememberCoroutineScope
27 import androidx.compose.ui.platform.LocalContext
28 import androidx.compose.ui.res.stringResource
29 import androidx.fragment.app.Fragment
30 import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
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.spa.SpaActivity.Companion.startSpaActivity
38 import com.android.settings.spa.app.appcompat.UserAspectRatioAppPreference
39 import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
40 import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider
41 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
42 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
43 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
44 import com.android.settingslib.spa.framework.common.SettingsPageProvider
45 import com.android.settingslib.spa.framework.compose.LifecycleEffect
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
52 private const val PACKAGE_NAME = "packageName"
53 private const val USER_ID = "userId"
54
55 object AppInfoSettingsProvider : SettingsPageProvider {
56 override val name = "AppInfoSettings"
57
58 override val parameter = listOf(
<lambda>null59 navArgument(PACKAGE_NAME) { type = NavType.StringType },
<lambda>null60 navArgument(USER_ID) { type = NavType.IntType },
61 )
62
63 const val METRICS_CATEGORY = SettingsEnums.APPLICATIONS_INSTALLED_APP_DETAILS
64
65 @Composable
Pagenull66 override fun Page(arguments: Bundle?) {
67 val packageName = arguments!!.getString(PACKAGE_NAME)!!
68 val userId = arguments.getInt(USER_ID)
69 val context = LocalContext.current
70 val coroutineScope = rememberCoroutineScope()
71 val packageInfoPresenter = remember {
72 PackageInfoPresenter(context, packageName, userId, coroutineScope)
73 }
74 AppInfoSettings(packageInfoPresenter)
75 packageInfoPresenter.PackageRemoveDetector()
76 }
77
78 @Composable
navigatornull79 fun navigator(app: ApplicationInfo) = navigator(route = "$name/${app.toRoute()}")
80
81 /**
82 * Gets the route to the App Info Settings page.
83 *
84 * Expose route to enable enter from non-SPA pages.
85 */
86 fun getRoute(packageName: String, userId: Int): String = "$name/$packageName/$userId"
87
88 /**
89 * Starts the App Info Settings page from non-SPA.
90 *
91 * Will starts SPA version if flag [FeatureFlagUtils.SETTINGS_ENABLE_SPA] is true.
92 */
93 @JvmStatic
94 fun startAppInfoSettings(
95 packageName: String,
96 uid: Int,
97 source: Fragment,
98 request: Int,
99 sourceMetricsCategory: Int,
100 ) {
101 val context = source.context ?: return
102 if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_ENABLE_SPA)) {
103 context.startSpaActivity(getRoute(packageName, UserHandle.getUserId(uid)))
104 } else {
105 AppInfoBase.startAppInfoFragment(
106 AppInfoDashboardFragment::class.java,
107 context.getString(R.string.application_info_label),
108 packageName,
109 uid,
110 source,
111 request,
112 sourceMetricsCategory,
113 )
114 }
115 }
116 }
117
118 @OptIn(ExperimentalLifecycleComposeApi::class)
119 @Composable
AppInfoSettingsnull120 private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
121 LifecycleEffect(onStart = { packageInfoPresenter.reloadPackageInfo() })
122 val packageInfo = packageInfoPresenter.flow.collectAsStateWithLifecycle().value ?: return
123 val app = packageInfo.applicationInfo
124 RegularScaffold(
125 title = stringResource(R.string.application_info_label),
126 actions = {
127 AppInfoSettingsMoreOptions(packageInfoPresenter, app)
128 }
129 ) {
130 val appInfoProvider = remember { AppInfoProvider(packageInfo) }
131
132 appInfoProvider.AppInfo()
133
134 AppButtons(packageInfoPresenter)
135
136 AppSettingsPreference(app)
137 AppAllServicesPreference(app)
138 AppNotificationPreference(app)
139 AppPermissionPreference(app)
140 AppStoragePreference(app)
141 InstantAppDomainsPreference(app)
142 AppDataUsagePreference(app)
143 AppTimeSpentPreference(app)
144 AppBatteryPreference(app)
145 AppLocalePreference(app)
146 AppOpenByDefaultPreference(app)
147 DefaultAppShortcuts(app)
148
149 Category(title = stringResource(R.string.unused_apps_category)) {
150 HibernationSwitchPreference(app)
151 }
152
153 Category(title = stringResource(R.string.advanced_apps)) {
154 UserAspectRatioAppPreference(app)
155 DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app)
156 ModifySystemSettingsAppListProvider.InfoPageEntryItem(app)
157 PictureInPictureListProvider.InfoPageEntryItem(app)
158 InstallUnknownAppsListProvider.InfoPageEntryItem(app)
159 InteractAcrossProfilesDetailsPreference(app)
160 AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
161 }
162
163 Category(title = stringResource(R.string.app_install_details_group_title)) {
164 AppInstallerInfoPreference(app)
165 }
166 appInfoProvider.FooterAppVersion()
167 }
168 }
169