Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1472929 authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "Move common startUninstallActivity to AppUtil"

parents 588001bb 4710cfc7
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.spa.app

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.UserHandle

/**
 * Based on PackageManagerService design, and it looks like the suggested replacement in the
 * deprecate notes suggest that we use PackageInstaller.uninstall which does not guarantee a pop up
 * would open and depends on the calling application. Seems like further investigation is needed
 * before we can move over to the new API.
 */
@Suppress("DEPRECATION")
fun Context.startUninstallActivity(
    packageName: String,
    userHandle: UserHandle,
    forAllUsers: Boolean = false,
) {
    val packageUri = Uri.parse("package:$packageName")

    val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
        putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
    }
    startActivityAsUser(intent, userHandle)
}
 No newline at end of file
+2 −6
Original line number Diff line number Diff line
@@ -22,11 +22,11 @@ import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.UserHandle
import android.util.Log
import androidx.compose.runtime.Composable
import com.android.settings.overlay.FeatureFactory
import com.android.settings.spa.app.startUninstallActivity
import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spaprivileged.framework.common.activityManager
import com.android.settingslib.spaprivileged.framework.common.asUser
@@ -116,11 +116,7 @@ class PackageInfoPresenter(
    /** Starts the uninstallation activity. */
    fun startUninstallActivity(forAllUsers: Boolean = false) {
        logAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP)
        val packageUri = Uri.parse("package:${packageName}")
        val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
            putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
        }
        context.startActivityAsUser(intent, userHandle)
        context.startUninstallActivity(packageName, userHandle, forAllUsers)
    }

    /** Clears this instant app. */
+6 −26
Original line number Diff line number Diff line
@@ -17,13 +17,11 @@
package com.android.settings.spa.app.backgroundinstall

import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.IBackgroundInstallControlService
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.ParceledListSlice
import android.net.Uri
import android.os.Bundle
import android.os.ServiceManager
import android.provider.DeviceConfig
@@ -40,6 +38,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
import com.android.settings.spa.app.startUninstallActivity
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -54,6 +53,7 @@ import com.android.settingslib.spa.widget.ui.SettingsBody
import com.android.settingslib.spaprivileged.model.app.AppEntry
import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.userHandle
import com.android.settingslib.spaprivileged.template.app.AppList
import com.android.settingslib.spaprivileged.template.app.AppListButtonItem
import com.android.settingslib.spaprivileged.template.app.AppListInput
@@ -150,23 +150,6 @@ fun BackgroundInstalledAppList(
            }
    )
}
/*
Based on PackageManagerService design, and it looks like the suggested replacement in the deprecate
notes suggest that we use PackageInstaller.uninstall which does not guarantee a pop up would open
and depends on the calling application. Seems like further investigation is needed before we can
move over to the new API.
 */
@Suppress
@VisibleForTesting
fun startUninstallActivity(context: Context,
                                   packageName: String,
                                   forAllUsers: Boolean = false) {
    val packageUri = Uri.parse("package:${packageName}")
    val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
        putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
    }
    context.startActivityAsUser(intent, context.user)
}

data class BackgroundInstalledAppListWithGroupingAppRecord(
    override val app: ApplicationInfo,
@@ -190,9 +173,10 @@ class BackgroundInstalledAppsWithGroupingListModel(private val context: Context)
    @Composable
    override fun AppListItemModel<BackgroundInstalledAppListWithGroupingAppRecord>.AppItem() {
        val context = LocalContext.current
        val app = record.app
        AppListButtonItem(
            onClick = AppInfoSettingsProvider.navigator(app = record.app),
            onButtonClick = { startUninstallActivity(context, record.app.packageName) },
            onClick = AppInfoSettingsProvider.navigator(app = app),
            onButtonClick = { context.startUninstallActivity(app.packageName, app.userHandle) },
            buttonIcon = Icons.Outlined.Delete,
            buttonIconDescription = stringResource(
                R.string.background_install_uninstall_button_description))
@@ -209,11 +193,6 @@ class BackgroundInstalledAppsWithGroupingListModel(private val context: Context)
            }
        }

    @Composable
    override fun getSummary(option: Int, record: BackgroundInstalledAppListWithGroupingAppRecord)
        = null

    @Suppress
    override fun filter(
            userIdFlow: Flow<Int>,
            option: Int,
@@ -224,6 +203,7 @@ class BackgroundInstalledAppsWithGroupingListModel(private val context: Context)
            return flowOf()
        }
        return userIdFlow.combine(recordListFlow) { userId, recordList ->
            @Suppress("UNCHECKED_CAST")
            val appList = (backgroundInstallService.getBackgroundInstalledPackages(
                PackageManager.MATCH_ALL.toLong(), userId) as ParceledListSlice<PackageInfo>).list
            val appNameList = appList.map { it.packageName }
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.spa.app

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import org.junit.Rule

import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.eq
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

@RunWith(AndroidJUnit4::class)
class AppUtilTest {
    @get:Rule
    val mockito: MockitoRule = MockitoJUnit.rule()

    @Mock
    private lateinit var context: Context

    @Test
    fun startUninstallActivity() {
        context.startUninstallActivity(packageName = PACKAGE_NAME, userHandle = USER_HANDLE)

        val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
        verify(context).startActivityAsUser(intentCaptor.capture(), eq(USER_HANDLE))
        val intent = intentCaptor.value
        assertThat(intent.action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE)
        assertThat(intent.data).isEqualTo(Uri.parse("package:$PACKAGE_NAME"))
        assertThat(intent.extras?.getBoolean(Intent.EXTRA_UNINSTALL_ALL_USERS)).isFalse()
    }

    private companion object {
        const val PACKAGE_NAME = "package.name"
        val USER_HANDLE: UserHandle = UserHandle.of(0)
    }
}
 No newline at end of file
+0 −26
Original line number Diff line number Diff line
@@ -17,14 +17,11 @@
package com.android.settings.spa.app.backgroundinstall

import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.IBackgroundInstallControlService
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.ParceledListSlice
import android.net.Uri
import android.os.UserHandle
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
@@ -74,9 +71,6 @@ class BackgroundInstalledAppsPageProviderTest {
    private var packageInfoFlagsCaptor =
        ArgumentCaptor.forClass(PackageManager.PackageInfoFlags::class.java)

    private var intentCaptor =
        ArgumentCaptor.forClass(Intent::class.java)

    private val fakeNavControllerWrapper = FakeNavControllerWrapper()

    @Before
@@ -177,26 +171,6 @@ class BackgroundInstalledAppsPageProviderTest {
            .isEqualTo("AppInfoSettings/package.name/0")
    }

    @Suppress
    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun startUninstallActivity_success() = runTest {
        val expectedPackageUri = Uri.parse("package:package.name")
        val mockUserHandle = UserHandle(0)
        Mockito.`when`(mockContext.user).thenReturn(mockUserHandle)
        Mockito.`when`(mockContext.startActivityAsUser(
            intentCaptor.capture(),
            eq(mockUserHandle)
        )).then {  }

        startUninstallActivity(mockContext, TEST_PACKAGE_NAME)

        Truth.assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE)
        Truth.assertThat(intentCaptor.value.data).isEqualTo(expectedPackageUri)
        Truth.assertThat(intentCaptor.value.extras?.getBoolean(Intent.EXTRA_UNINSTALL_ALL_USERS))
            .isEqualTo(false)
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun backgroundInstalledAppsWithGroupingListModel_getGroupTitleOne() = runTest {