• 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.UserManager
22 import androidx.compose.material.icons.Icons
23 import androidx.compose.material.icons.outlined.WarningAmber
24 import androidx.compose.material3.Text
25 import androidx.compose.runtime.Composable
26 import androidx.compose.ui.res.stringResource
27 import com.android.settings.R
28 import com.android.settingslib.RestrictedLockUtils
29 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
30 import com.android.settingslib.RestrictedLockUtilsInternal
31 import com.android.settingslib.spa.widget.button.ActionButton
32 import com.android.settingslib.spa.widget.dialog.AlertDialogButton
33 import com.android.settingslib.spa.widget.dialog.AlertDialogPresenter
34 import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
35 import com.android.settingslib.spaprivileged.model.app.hasFlag
36 import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
37 import com.android.settingslib.spaprivileged.model.app.userId
38 
39 class AppForceStopButton(
40     private val packageInfoPresenter: PackageInfoPresenter,
41 ) {
42     private val context = packageInfoPresenter.context
43     private val appButtonRepository = AppButtonRepository(context)
44     private val packageManager = context.packageManager
45 
46     @Composable
47     fun getActionButton(app: ApplicationInfo): ActionButton {
48         val dialogPresenter = confirmDialogPresenter()
49         return ActionButton(
50             text = context.getString(R.string.force_stop),
51             imageVector = Icons.Outlined.WarningAmber,
52             enabled = isForceStopButtonEnable(app),
53         ) { onForceStopButtonClicked(app, dialogPresenter) }
54     }
55 
56     /**
57      * Gets whether a package can be force stopped.
58      */
59     private fun isForceStopButtonEnable(app: ApplicationInfo): Boolean = when {
60         // User can't force stop device admin.
61         app.isActiveAdmin(context) -> false
62 
63         appButtonRepository.isDisallowControl(app) -> false
64 
65         // If the app isn't explicitly stopped, then always show the force stop button.
66         else -> !app.hasFlag(ApplicationInfo.FLAG_STOPPED)
67     }
68 
69     private fun onForceStopButtonClicked(
70         app: ApplicationInfo,
71         dialogPresenter: AlertDialogPresenter,
72     ) {
73         packageInfoPresenter.logAction(SettingsEnums.ACTION_APP_INFO_FORCE_STOP)
74         getAdminRestriction(app)?.let { admin ->
75             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin)
76             return
77         }
78         dialogPresenter.open()
79     }
80 
81     private fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
82         packageManager.isPackageStateProtected(app.packageName, app.userId) -> {
83             RestrictedLockUtilsInternal.getDeviceOwner(context)
84         }
85 
86         else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
87             context, UserManager.DISALLOW_APPS_CONTROL, app.userId
88         )
89     }
90 
91     @Composable
92     private fun confirmDialogPresenter() = rememberAlertDialogPresenter(
93         confirmButton = AlertDialogButton(
94             text = stringResource(R.string.okay),
95             onClick = packageInfoPresenter::forceStop,
96         ),
97         dismissButton = AlertDialogButton(stringResource(R.string.cancel)),
98         title = stringResource(R.string.force_stop_dlg_title),
99         text = { Text(stringResource(R.string.force_stop_dlg_text)) },
100     )
101 }
102