Fix NPE crash when opening the app info from shortcut suggestion
It occurs NPE in invoking refreshUi() of AppButtonsPreferenceController when user fully install the instant app from google play and then directly open app info from the shortcut suggestion in launcher. Root cause: AppButtonsPreferenceController.refreshUi() will be invoked when user directly open app info from the shortcut suggestion in launcher. In refreshUi(), we will update the information of button preference, but the preferences will not be initialized if device existed an instant version for the app. Solution: Check button preference and initial them if need in refreshUi(). Fixes: 137854835 Test: visual, robotests Change-Id: Id5c3e53b9db2683cab970c10eace7925d889eea3
This commit is contained in:
@@ -116,6 +116,7 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
private Intent mAppLaunchIntent;
|
||||
private ApplicationsState.Session mSession;
|
||||
private RestrictedLockUtils.EnforcedAdmin mAppsControlDisallowedAdmin;
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private boolean mUpdatedSysApp = false;
|
||||
private boolean mListeningToPackageRemove = false;
|
||||
@@ -167,19 +168,9 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mScreen = screen;
|
||||
if (isAvailable()) {
|
||||
mButtonsPref = ((ActionButtonsPreference) screen.findPreference(
|
||||
KEY_ACTION_BUTTONS))
|
||||
.setButton1Text(R.string.launch_instant_app)
|
||||
.setButton1Icon(R.drawable.ic_settings_open)
|
||||
.setButton1OnClickListener(v -> launchApplication())
|
||||
.setButton2Text(R.string.uninstall_text)
|
||||
.setButton2Icon(R.drawable.ic_settings_delete)
|
||||
.setButton2OnClickListener(new UninstallAndDisableButtonListener())
|
||||
.setButton3Text(R.string.force_stop)
|
||||
.setButton3Icon(R.drawable.ic_settings_force_stop)
|
||||
.setButton3OnClickListener(new ForceStopButtonListener())
|
||||
.setButton3Enabled(false);
|
||||
initButtonPreference();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +654,11 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
}
|
||||
}
|
||||
|
||||
// When the app was installed from instant state, buttons preferences could be null.
|
||||
if (mButtonsPref == null) {
|
||||
initButtonPreference();
|
||||
mButtonsPref.setVisible(true);
|
||||
}
|
||||
updateOpenButton();
|
||||
updateUninstallButton();
|
||||
updateForceStopButton();
|
||||
@@ -670,6 +666,21 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initButtonPreference() {
|
||||
mButtonsPref = ((ActionButtonsPreference) mScreen.findPreference(
|
||||
KEY_ACTION_BUTTONS))
|
||||
.setButton1Text(R.string.launch_instant_app)
|
||||
.setButton1Icon(R.drawable.ic_settings_open)
|
||||
.setButton1OnClickListener(v -> launchApplication())
|
||||
.setButton2Text(R.string.uninstall_text)
|
||||
.setButton2Icon(R.drawable.ic_settings_delete)
|
||||
.setButton2OnClickListener(new UninstallAndDisableButtonListener())
|
||||
.setButton3Text(R.string.force_stop)
|
||||
.setButton3Icon(R.drawable.ic_settings_force_stop)
|
||||
.setButton3OnClickListener(new ForceStopButtonListener())
|
||||
.setButton3Enabled(false);
|
||||
}
|
||||
|
||||
private void startListeningToPackageRemove() {
|
||||
if (mListeningToPackageRemove) {
|
||||
return;
|
||||
|
@@ -50,6 +50,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;
|
||||
@@ -116,6 +118,8 @@ public class AppButtonsPreferenceControllerTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private PackageInfo mPackageInfo;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private Context mContext;
|
||||
private Intent mUninstallIntent;
|
||||
@@ -471,6 +475,20 @@ public class AppButtonsPreferenceControllerTest {
|
||||
assertThat(mController.refreshUi()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_buttonPreferenceNull_shouldNotCrash()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
doReturn(AppButtonsPreferenceController.AVAILABLE)
|
||||
.when(mController).getAvailabilityStatus();
|
||||
doReturn(mPackageInfo).when(mPackageManger).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mButtonPrefs).when(mScreen).findPreference(anyString());
|
||||
mController.displayPreference(mScreen);
|
||||
mController.mButtonsPref = null;
|
||||
|
||||
// Should not crash in this method
|
||||
assertThat(mController.refreshUi()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPackageListChanged_available_shouldRefreshUi() {
|
||||
doReturn(AppButtonsPreferenceController.AVAILABLE)
|
||||
@@ -545,11 +563,19 @@ public class AppButtonsPreferenceControllerTest {
|
||||
|
||||
private ActionButtonsPreference createMock() {
|
||||
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
|
||||
when(pref.setButton1Text(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton1Icon(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
|
||||
when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
|
||||
when(pref.setButton2Text(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton2Icon(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
|
||||
when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
|
||||
when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
|
||||
when(pref.setButton3Text(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton3Icon(anyInt())).thenReturn(pref);
|
||||
when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
|
||||
when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
|
||||
|
||||
return pref;
|
||||
}
|
||||
|
Reference in New Issue
Block a user