OSDN Git Service

Fix a crash when opening uninstalled app detail page
authorFan Zhang <zhfan@google.com>
Tue, 7 Mar 2017 20:12:38 +0000 (12:12 -0800)
committerFan Zhang <zhfan@google.com>
Tue, 7 Mar 2017 21:24:31 +0000 (13:24 -0800)
Change-Id: I417e7eb6f9c857ace4e8047b226abe03a7c8248d
Fix: 36027848
Fix: 34392538
Test: make RunSettingsRoboTests

src/com/android/settings/applications/InstalledAppDetails.java
tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java

index c443e73..0bd56d9 100755 (executable)
@@ -16,8 +16,6 @@
 
 package com.android.settings.applications;
 
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
 import android.Manifest.permission;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -68,7 +66,6 @@ import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.webkit.IWebViewUpdateService;
 import android.widget.Button;
@@ -115,6 +112,8 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
 /**
  * Activity to display application information from Settings. This activity presents
  * extended information associated with a package like code, data, total size, permissions
@@ -325,6 +324,10 @@ public class InstalledAppDetails extends AppInfoBase
         super.onCreate(icicle);
         final Activity activity = getActivity();
 
+        if (!ensurePackageInfoAvailable(activity)) {
+            return;
+        }
+
         setHasOptionsMenu(true);
         addPreferencesFromResource(R.xml.installed_app_details_ia);
         addDynamicPrefs();
@@ -434,6 +437,23 @@ public class InstalledAppDetails extends AppInfoBase
         refreshUi();
     }
 
+    /**
+     * Ensures the {@link PackageInfo} is available to proceed. If it's not available, the fragment
+     * will finish.
+     *
+     * @return true if packageInfo is available.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    boolean ensurePackageInfoAvailable(Activity activity) {
+        if (mPackageInfo == null) {
+            mFinishing = true;
+            Log.w(LOG_TAG, "Package info not available. Is this package already uninstalled?");
+            activity.finishAndRemoveTask();
+            return false;
+        }
+        return true;
+    }
+
     private void prepareUninstallAndStop() {
         mForceStopButton = (Button) mFooter.findViewById(R.id.right_button);
         mForceStopButton.setText(R.string.force_stop);
index 4fe6293..b0cd8d5 100644 (file)
 
 package com.android.settings.applications;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
+import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -44,6 +40,14 @@ import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public final class InstalledAppDetailsTest {
@@ -51,24 +55,27 @@ public final class InstalledAppDetailsTest {
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private UserManager mUserManager;
     @Mock
+    private Activity mActivity;
+    @Mock
     private DevicePolicyManager mDevicePolicyManager;
 
+    private InstalledAppDetails mAppDetail;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mAppDetail = new InstalledAppDetails();
     }
 
     @Test
     public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
 
         assertThat(mAppDetail.getInstallationStatus(new ApplicationInfo()))
-            .isEqualTo(R.string.not_installed);
+                .isEqualTo(R.string.not_installed);
     }
 
     @Test
     public void getInstallationStatus_enabled_shouldReturnInstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = true;
@@ -78,7 +85,6 @@ public final class InstalledAppDetailsTest {
 
     @Test
     public void getInstallationStatus_disabled_shouldReturnDisabled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = false;
@@ -90,7 +96,6 @@ public final class InstalledAppDetailsTest {
     public void shouldShowUninstallForAll_installForOneOtherUserOnly_shouldReturnTrue() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -107,7 +112,6 @@ public final class InstalledAppDetailsTest {
     public void shouldShowUninstallForAll_installForSelfOnly_shouldReturnFalse() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -139,6 +143,22 @@ public final class InstalledAppDetailsTest {
 
         assertThat(InstalledAppDetails.getStorageSummary(context, stats, false))
                 .isEqualTo("1.00B used in Internal storage");
+    }
+
+    @Test
+    public void launchFragment_hasNoPackageInfo_shouldFinish() {
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", null);
+
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isFalse();
+        verify(mActivity).finishAndRemoveTask();
+    }
+
+    @Test
+    public void launchFragment_hasPackageInfo_shouldReturnTrue() {
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
 
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isTrue();
+        verify(mActivity, never()).finishAndRemoveTask();
     }
 }