Allow uninstallation of current home app
Change the behavior to allow uninstallation of the current home app if it is a non-system app and/or there are other candidate apps available. Bug: 131721576 Test: atest com.android.settings.applications.appinfo.AppButtonsPreferenceControllerTest Test: atest com.android.settings.spa.app.appinfo.AppButtonRepositoryTest Change-Id: I556966894240aaf91c0e6424dce514b6a35d1001
This commit is contained in:
@@ -32,6 +32,7 @@ import android.content.IntentFilter;
|
||||
import android.content.om.OverlayInfo;
|
||||
import android.content.om.OverlayManager;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.Flags;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
@@ -434,10 +435,17 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
// No preferred default, so permit uninstall only when
|
||||
// there is more than one candidate
|
||||
enabled = (mHomePackages.size() > 1);
|
||||
} else {
|
||||
// There is an explicit default home app -- forbid uninstall of
|
||||
// that one, but permit it for installed-but-inactive ones.
|
||||
enabled = !mPackageInfo.packageName.equals(currentDefaultHome.getPackageName());
|
||||
} else if (mPackageInfo.packageName.equals(currentDefaultHome.getPackageName())) {
|
||||
if (Flags.improveHomeAppBehavior()) {
|
||||
// Allow uninstallation of current home app if it is a non-system app
|
||||
// and/or there are other candidate apps available.
|
||||
if (mPackageInfo.applicationInfo.isSystemApp()
|
||||
|| mHomePackages.size() == 1) {
|
||||
enabled = false;
|
||||
}
|
||||
} else {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.om.OverlayManager
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.Flags
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.util.Log
|
||||
@@ -95,7 +96,7 @@ class AppButtonRepository(private val context: Context) {
|
||||
|
||||
isDisallowControl(app) -> return false
|
||||
|
||||
uninstallDisallowedDueToHomeApp(app.packageName) -> return false
|
||||
uninstallDisallowedDueToHomeApp(app) -> return false
|
||||
|
||||
// Resource overlays can be uninstalled iff they are public (installed on /data) and
|
||||
// disabled. ("Enabled" means they are in use by resource management.)
|
||||
@@ -113,7 +114,8 @@ class AppButtonRepository(private val context: Context) {
|
||||
* can go to Home settings and pick a different one, after which we'll permit uninstallation
|
||||
* of the now-not-default one.
|
||||
*/
|
||||
private fun uninstallDisallowedDueToHomeApp(packageName: String): Boolean {
|
||||
fun uninstallDisallowedDueToHomeApp(applicationInfo: ApplicationInfo): Boolean {
|
||||
val packageName = applicationInfo.packageName
|
||||
val homePackageInfo = getHomePackageInfo()
|
||||
return when {
|
||||
packageName !in homePackageInfo.homePackages -> false
|
||||
@@ -121,8 +123,17 @@ class AppButtonRepository(private val context: Context) {
|
||||
// Disallow uninstall when this is the only home app.
|
||||
homePackageInfo.homePackages.size == 1 -> true
|
||||
|
||||
// Disallow if this is the explicit default home app.
|
||||
else -> packageName == homePackageInfo.currentDefaultHome?.packageName
|
||||
packageName == homePackageInfo.currentDefaultHome?.packageName -> {
|
||||
if (Flags.improveHomeAppBehavior()) {
|
||||
// Disallow the uninstallation of the current home app if it is a system app.
|
||||
return applicationInfo.isSystemApp()
|
||||
} else {
|
||||
// Disallow if this is the explicit default home app.
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
@@ -38,15 +39,18 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.om.OverlayInfo;
|
||||
import android.content.om.OverlayManager;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.Flags;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserManager;
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||
import android.util.ArraySet;
|
||||
import android.view.View;
|
||||
|
||||
@@ -107,7 +111,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Mock
|
||||
private OverlayManager mOverlayManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManger;
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private DevicePolicyManager mDpm;
|
||||
@Mock
|
||||
@@ -132,7 +136,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
doReturn(mDpm).when(mSettingsActivity).getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
doReturn(mUserManager).when(mSettingsActivity).getSystemService(Context.USER_SERVICE);
|
||||
doReturn(mPackageManger).when(mSettingsActivity).getPackageManager();
|
||||
doReturn(mPackageManager).when(mSettingsActivity).getPackageManager();
|
||||
doReturn(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE);
|
||||
doReturn(mOverlayManager).when(mSettingsActivity).
|
||||
getSystemService(OverlayManager.class);
|
||||
@@ -184,7 +188,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Test
|
||||
public void retrieveAppEntry_hasAppEntry_notNull()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
|
||||
@@ -195,7 +199,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
@Test
|
||||
public void retrieveAppEntry_noAppEntry_null() throws PackageManager.NameNotFoundException {
|
||||
doReturn(null).when(mState).getEntry(eq(PACKAGE_NAME), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
|
||||
@@ -207,7 +211,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
public void retrieveAppEntry_throwException_null() throws
|
||||
PackageManager.NameNotFoundException {
|
||||
doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManger).getPackageInfo(
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
anyString(), anyInt());
|
||||
|
||||
mController.retrieveAppEntry();
|
||||
@@ -225,7 +229,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void updateOpenButton_haveLaunchIntent_buttonShouldBeEnable() {
|
||||
doReturn(new Intent()).when(mPackageManger).getLaunchIntentForPackage(anyString());
|
||||
doReturn(new Intent()).when(mPackageManager).getLaunchIntentForPackage(anyString());
|
||||
|
||||
mController.updateOpenButton();
|
||||
|
||||
@@ -346,6 +350,35 @@ public class AppButtonsPreferenceControllerTest {
|
||||
verify(mButtonPrefs).setButton2Enabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
public void updateUninstallButton_isNotSystemAndIsCurrentHomeAndHasOneHome_setButtonDisable() {
|
||||
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
|
||||
doReturn(new ComponentName(PACKAGE_NAME, "cls")).when(mPackageManager).getHomeActivities(
|
||||
anyList());
|
||||
|
||||
mController.mHomePackages.add(PACKAGE_NAME);
|
||||
|
||||
mController.updateUninstallButton();
|
||||
|
||||
verify(mButtonPrefs).setButton2Enabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
public void updateUninstallButton_isNotSystemAndIsCurrentHomeAndHasOtherHome_setButtonEnable() {
|
||||
doReturn(false).when(mController).isSystemPackage(any(), any(), any());
|
||||
doReturn(new ComponentName(PACKAGE_NAME, "cls")).when(mPackageManager).getHomeActivities(
|
||||
anyList());
|
||||
|
||||
mController.mHomePackages.add(PACKAGE_NAME);
|
||||
mController.mHomePackages.add("com.android.home.fake");
|
||||
|
||||
mController.updateUninstallButton();
|
||||
|
||||
verify(mButtonPrefs).setButton2Enabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateUninstallButton_isSystemRro_setButtonDisable() {
|
||||
mAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
|
||||
@@ -477,7 +510,7 @@ public class AppButtonsPreferenceControllerTest {
|
||||
throws PackageManager.NameNotFoundException {
|
||||
doReturn(AppButtonsPreferenceController.AVAILABLE)
|
||||
.when(mController).getAvailabilityStatus();
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mButtonPrefs).when(mScreen).findPreference(anyString());
|
||||
mController.displayPreference(mScreen);
|
||||
mController.mButtonsPref = null;
|
||||
|
@@ -20,8 +20,11 @@ import android.app.ActivityManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.Flags
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.platform.test.annotations.RequiresFlagsEnabled
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
@@ -126,9 +129,62 @@ class AppButtonRepositoryTest {
|
||||
assertThat(homePackageInfo.homePackages).containsExactly(PACKAGE_NAME)
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
fun uninstallDisallowedDueToHomeApp_isNotSystemAndIsCurrentHomeAndHasOnlyOneHomeApp() {
|
||||
val app = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
|
||||
mockGetHomeActivities(
|
||||
homeActivities = listOf(RESOLVE_INFO),
|
||||
currentDefaultHome = COMPONENT_NAME,
|
||||
)
|
||||
|
||||
val value = appButtonRepository.uninstallDisallowedDueToHomeApp(app)
|
||||
|
||||
assertThat(value).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
fun uninstallDisallowedDueToHomeApp_isNotSystemAndIsCurrentHomeAndHasOtherHomeApps() {
|
||||
val app = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
|
||||
mockGetHomeActivities(
|
||||
homeActivities = listOf(RESOLVE_INFO, RESOLVE_INFO_FAKE),
|
||||
currentDefaultHome = COMPONENT_NAME,
|
||||
)
|
||||
|
||||
val value = appButtonRepository.uninstallDisallowedDueToHomeApp(app)
|
||||
|
||||
assertThat(value).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_IMPROVE_HOME_APP_BEHAVIOR)
|
||||
fun uninstallDisallowedDueToHomeApp_isSystemAndIsCurrentHomeAndHasOtherHomeApps() {
|
||||
val app = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
flags = ApplicationInfo.FLAG_SYSTEM
|
||||
}
|
||||
|
||||
mockGetHomeActivities(
|
||||
homeActivities = listOf(RESOLVE_INFO, RESOLVE_INFO_FAKE),
|
||||
currentDefaultHome = COMPONENT_NAME,
|
||||
)
|
||||
|
||||
val value = appButtonRepository.uninstallDisallowedDueToHomeApp(app)
|
||||
|
||||
assertThat(value).isTrue()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val PACKAGE_NAME = "packageName"
|
||||
const val PACKAGE_NAME_ALTERNATE = "packageName.alternate"
|
||||
const val PACKAGE_NAME_FAKE = "packageName.fake"
|
||||
const val ACTIVITY_NAME = "activityName"
|
||||
val COMPONENT_NAME = ComponentName(PACKAGE_NAME, ACTIVITY_NAME)
|
||||
val RESOLVE_INFO = ResolveInfo().apply {
|
||||
@@ -136,6 +192,11 @@ class AppButtonRepositoryTest {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
}
|
||||
val RESOLVE_INFO_FAKE = ResolveInfo().apply {
|
||||
activityInfo = ActivityInfo().apply {
|
||||
packageName = PACKAGE_NAME_FAKE
|
||||
}
|
||||
}
|
||||
val RESOLVE_INFO_WITH_ALTERNATE = ResolveInfo().apply {
|
||||
activityInfo = ActivityInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
|
Reference in New Issue
Block a user