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.Intent
21 import android.content.pm.ApplicationInfo
22 import android.os.UserHandle
23 import android.os.UserManager
24 import androidx.compose.runtime.Composable
25 import androidx.compose.runtime.remember
26 import androidx.compose.ui.graphics.vector.ImageVector
27 import androidx.compose.ui.res.vectorResource
28 import androidx.lifecycle.compose.collectAsStateWithLifecycle
29 import com.android.settings.R
30 import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd
31 import com.android.settingslib.spa.widget.button.ActionButton
32 import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
33 import com.android.settingslib.spaprivileged.model.app.userHandle
34 import kotlinx.coroutines.Dispatchers
35 import kotlinx.coroutines.flow.flow
36 import kotlinx.coroutines.flow.flowOn
37 
38 class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter) {
39     private val context = packageInfoPresenter.context
40     private val appButtonRepository = AppButtonRepository(context)
41     private val userManager = context.getSystemService(UserManager::class.java)!!
42 
43     @Composable
getActionButtonnull44     fun getActionButton(app: ApplicationInfo): ActionButton? {
45         if (app.isSystemApp || app.isInstantApp) return null
46         return uninstallButton(app)
47     }
48 
49     @Composable
uninstallButtonnull50     private fun uninstallButton(app: ApplicationInfo) = ActionButton(
51         text = if (isCloneApp(app)) context.getString(R.string.delete) else
52             context.getString(R.string.uninstall_text),
53         imageVector = ImageVector.vectorResource(R.drawable.ic_settings_delete),
54         enabled = remember(app) {
55             flow {
56                 emit(appButtonRepository.isAllowUninstallOrArchive(context, app))
57             }.flowOn(Dispatchers.Default)
58         }.collectAsStateWithLifecycle(false).value,
<lambda>null59     ) { onUninstallClicked(app) }
60 
onUninstallClickednull61     private fun onUninstallClicked(app: ApplicationInfo) {
62         if (appButtonRepository.isUninstallBlockedByAdmin(app)) {
63             return
64         } else if (app.isActiveAdmin(context)) {
65                 val uninstallDaIntent = Intent(context, DeviceAdminAdd::class.java)
66                 uninstallDaIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME,
67                         app.packageName)
68                 packageInfoPresenter.logAction(
69                     SettingsEnums.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN)
70                 context.startActivityAsUser(uninstallDaIntent, app.userHandle)
71                 return
72         }
73         packageInfoPresenter.startUninstallActivity()
74     }
75 
isCloneAppnull76     private fun isCloneApp(app: ApplicationInfo): Boolean  {
77         val userInfo = userManager.getUserInfo(UserHandle.getUserId(app.uid))
78         return userInfo != null && userInfo.isCloneProfile
79     }
80 }
81