From 2d709131bac0fc4bfd12efe0f316c635c0ca700d Mon Sep 17 00:00:00 2001 From: Raff Tsai Date: Mon, 29 Jul 2019 16:24:39 +0800 Subject: [PATCH] Fix Settings crash when click uninstall button When mPackageName is null, mFinish is true. OnResume() doesn't invoke refreshUI(). It causes uninstall button is still enabled. The solution is hiding AppButtonsPreference when mFinish is true. Fixes: 138524326 Test: make RunSettingsRoboTests ROBOTEST_FILTER Change-Id: I9759e53f002afbd4c88d8d536df3bf01c343135e (cherry picked from commit 88228c33994fe963022b950ff4affc81d4bf3021) --- .../AppButtonsPreferenceController.java | 4 +- .../AppButtonsPreferenceControllerTest.java | 45 +++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java index e15b0e3e4b1..e526417d892 100644 --- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java @@ -160,7 +160,7 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp @Override public int getAvailabilityStatus() { // TODO(b/37313605): Re-enable once this controller supports instant apps - return isInstantApp() || isSystemModule() ? DISABLED_FOR_USER : AVAILABLE; + return mFinishing || isInstantApp() || isSystemModule() ? DISABLED_FOR_USER : AVAILABLE; } @Override @@ -189,7 +189,7 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp @Override public void onResume() { - if (isAvailable() && !mFinishing) { + if (isAvailable()) { mAppsControlDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction( mActivity, UserManager.DISALLOW_APPS_CONTROL, mUserId); mAppsControlDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java index e42c3d21f74..637ffbce93b 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java @@ -19,8 +19,8 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; @@ -39,8 +39,8 @@ import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; -import android.content.om.OverlayManager; import android.content.om.OverlayInfo; +import android.content.om.OverlayManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -49,6 +49,8 @@ import android.os.UserManager; import android.util.ArraySet; import android.view.View; +import androidx.preference.PreferenceScreen; + import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.core.InstrumentedPreferenceFragment; @@ -59,7 +61,6 @@ import com.android.settingslib.applications.instantapps.InstantAppDataProvider; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.ActionButtonsPreference; -import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -70,12 +71,15 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.annotation.Resetter; import org.robolectric.util.ReflectionHelpers; +import java.util.Set; + @RunWith(RobolectricTestRunner.class) public class AppButtonsPreferenceControllerTest { @@ -112,10 +116,9 @@ public class AppButtonsPreferenceControllerTest { @Mock private UserManager mUserManager; @Mock - private Application mApplication; - @Mock private PackageInfo mPackageInfo; + private Context mContext; private Intent mUninstallIntent; private ActionButtonsPreference mButtonPrefs; private AppButtonsPreferenceController mController; @@ -125,14 +128,15 @@ public class AppButtonsPreferenceControllerTest { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(); + 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(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE); doReturn(mOverlayManager).when(mSettingsActivity). - getSystemService(OverlayManager.class); + getSystemService(OverlayManager.class); doReturn(mAppEntry).when(mState).getEntry(anyString(), anyInt()); - when(mSettingsActivity.getApplication()).thenReturn(mApplication); + doReturn(mContext).when(mSettingsActivity).getApplicationContext(); when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(RESOURCE_STRING); mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment, @@ -161,6 +165,21 @@ public class AppButtonsPreferenceControllerTest { ShadowAppUtils.reset(); } + @Test + @Config(shadows = ShadowAppUtils.class) + public void isAvailable_validPackageName_isTrue() { + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_nullPackageName_isFalse() { + final AppButtonsPreferenceController controller = spy( + new AppButtonsPreferenceController(mSettingsActivity, mFragment, + mLifecycle, null, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN)); + + assertThat(controller.isAvailable()).isFalse(); + } + @Test public void retrieveAppEntry_hasAppEntry_notNull() throws PackageManager.NameNotFoundException { @@ -306,10 +325,10 @@ public class AppButtonsPreferenceControllerTest { @Test public void updateUninstallButton_isNonSystemRro_setButtonDisable() - throws RemoteException { + throws RemoteException { when(mAppInfo.isResourceOverlay()).thenReturn(true); when(mOverlayManager.getOverlayInfo(anyString(), any())) - .thenReturn(OVERLAY_ENABLED); + .thenReturn(OVERLAY_ENABLED); mController.updateUninstallButton(); @@ -318,10 +337,10 @@ public class AppButtonsPreferenceControllerTest { @Test public void updateUninstallButton_isNonSystemRro_setButtonEnable() - throws RemoteException { + throws RemoteException { when(mAppInfo.isResourceOverlay()).thenReturn(true); when(mOverlayManager.getOverlayInfo(anyString(), any())) - .thenReturn(OVERLAY_DISABLED); + .thenReturn(OVERLAY_DISABLED); mController.updateUninstallButton(); @@ -423,7 +442,7 @@ public class AppButtonsPreferenceControllerTest { @Test public void onPackageListChanged_available_shouldRefreshUi() { doReturn(AppButtonsPreferenceController.AVAILABLE) - .when(mController).getAvailabilityStatus(); + .when(mController).getAvailabilityStatus(); doReturn(true).when(mController).refreshUi(); mController.onPackageListChanged(); @@ -434,7 +453,7 @@ public class AppButtonsPreferenceControllerTest { @Test public void onPackageListChanged_notAvailable_shouldNotRefreshUiAndNoCrash() { doReturn(AppButtonsPreferenceController.DISABLED_FOR_USER) - .when(mController).getAvailabilityStatus(); + .when(mController).getAvailabilityStatus(); mController.onPackageListChanged();