Fix NPE if keyboard settings is launched by work apps

IME apps can request users to enable them by directly
launching the on-screen keyboard settings page.

If keyboard settings is launched by works apps, the
current userId would be work userId. There is no managed
profile for work user so the exception happened.

-. Use current userId if it's launched by work user
-. Use primary user info for personal fragment

Fix: 216395439
Test: Manual test with issue steps
Test: make RunSettingsRoboTests ROBOTEST_FILTER=AvailableVirtualKeyboardFragmentTest
Change-Id: Iea573922ee789d9932c0de05bf71179c4f005eeb
This commit is contained in:
Wilson Wu
2022-02-08 22:20:05 +08:00
parent e9e4c5bc6a
commit ddb5147649
3 changed files with 43 additions and 10 deletions

View File

@@ -68,16 +68,35 @@ public class AvailableVirtualKeyboardFragment extends DashboardFragment
public void onAttach(Context context) {
super.onAttach(context);
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
if (profileType == ProfileSelectFragment.ProfileType.WORK) {
final UserManager userManager = UserManager.get(context);
final UserHandle workUser = Utils.getManagedProfile(userManager);
// get work userId
mUserId = Utils.getManagedProfileId(userManager, UserHandle.myUserId());
mUserAwareContext = context.createContextAsUser(workUser, 0);
} else {
mUserId = UserHandle.myUserId();
mUserAwareContext = context;
final UserManager userManager = context.getSystemService(UserManager.class);
final int currentUserId = UserHandle.myUserId();
final int newUserId;
final Context newUserAwareContext;
switch (profileType) {
case ProfileSelectFragment.ProfileType.WORK: {
final UserHandle workUser;
if (currentUserId == UserHandle.MIN_SECONDARY_USER_ID) {
newUserId = currentUserId;
workUser = UserHandle.of(currentUserId);
} else {
newUserId = Utils.getManagedProfileId(userManager, currentUserId);
workUser = Utils.getManagedProfile(userManager);
}
newUserAwareContext = context.createContextAsUser(workUser, 0);
break;
}
case ProfileSelectFragment.ProfileType.PERSONAL: {
final UserHandle primaryUser = userManager.getPrimaryUser().getUserHandle();
newUserId = primaryUser.getIdentifier();
newUserAwareContext = context.createContextAsUser(primaryUser, 0);
break;
}
default:
newUserId = currentUserId;
newUserAwareContext = context;
}
mUserId = newUserId;
mUserAwareContext = newUserAwareContext;
}
@Override

View File

@@ -20,7 +20,9 @@ import static com.android.settings.dashboard.profileselector.ProfileSelectFragme
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -31,6 +33,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -43,6 +46,7 @@ import com.android.settings.R;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.inputmethod.InputMethodPreference;
import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
@@ -62,7 +66,8 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowSecureSettings.class,
ShadowInputMethodManagerWithMethodList.class
ShadowInputMethodManagerWithMethodList.class,
ShadowUserManager.class
})
public class AvailableVirtualKeyboardFragmentTest {
@@ -170,6 +175,7 @@ public class AvailableVirtualKeyboardFragmentTest {
when(mFragment.getPreferenceScreen()).thenReturn(mPreferenceScreen);
when(mPreferenceManager.getContext()).thenReturn(mContext);
when(mContext.getSystemService(InputMethodManager.class)).thenReturn(mInputMethodManager);
doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt());
}
private List<InputMethodInfo> createFakeInputMethodInfoList(final String name, int num) {

View File

@@ -44,6 +44,8 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
private static boolean sIsSupportsMultipleUsers;
private static final int PRIMARY_USER_ID = 0;
private final List<String> mBaseRestrictions = new ArrayList<>();
private final List<String> mGuestRestrictions = new ArrayList<>();
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
@@ -218,4 +220,10 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
mEnabledTypes.remove(type);
}
}
@Implementation
protected UserInfo getPrimaryUser() {
return new UserInfo(PRIMARY_USER_ID, null, null,
UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
}
}