diff --git a/res/values/strings.xml b/res/values/strings.xml index 6e869f892c9..56d05eebb32 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7746,17 +7746,15 @@ Apps and data from this guest session will be deleted now, and all future guest activity will be deleted each time you exit guest mode + + Allow guest to use phone + + Call history will be shared with guest user - - Turn on phone calls Turn on phone calls & SMS Delete user - - Turn on phone calls? - - Call history will be shared with this user. Turn on phone calls & SMS? diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml index 58910e876f1..3b5cbe34dba 100644 --- a/res/xml/user_settings.xml +++ b/res/xml/user_settings.xml @@ -84,6 +84,13 @@ android:summary="@string/remove_guest_on_exit_summary" android:order="60"/> + + removeUser()); - case DIALOG_CONFIRM_ENABLE_CALLING: - return UserDialogs.createEnablePhoneCallsDialog(getActivity(), - (dialog, which) -> enableCallsAndSms(true)); case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS: return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(), (dialog, which) -> enableCallsAndSms(true)); @@ -308,13 +301,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment } if (mUserInfo.isGuest()) { - // These are not for an existing user, just general Guest settings. - // Default title is for calling and SMS. Change to calling-only here - // TODO(b/191483069): These settings can't be changed unless guest user exists - mPhonePref.setTitle(R.string.user_enable_calling); - mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions(); - mPhonePref.setChecked( - !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS)); + removePreference(KEY_ENABLE_TELEPHONY); mRemoveUserPref.setTitle(mGuestUserAutoCreated ? com.android.settingslib.R.string.guest_reset_guest : com.android.settingslib.R.string.guest_exit_guest); @@ -397,31 +384,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment private void enableCallsAndSms(boolean enabled) { mPhonePref.setChecked(enabled); - if (mUserInfo.isGuest()) { - mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled); - // SMS is always disabled for guest - mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true); - mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions); - - // Update the guest's restrictions, if there is a guest - // TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions - // on any existing guest rather than do it here with multiple Binder calls. - List users = mUserManager.getAliveUsers(); - for (UserInfo user : users) { - if (user.isGuest()) { - UserHandle userHandle = UserHandle.of(user.id); - for (String key : mDefaultGuestRestrictions.keySet()) { - mUserManager.setUserRestriction( - key, mDefaultGuestRestrictions.getBoolean(key), userHandle); - } - } - } - } else { - UserHandle userHandle = UserHandle.of(mUserInfo.id); - mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled, - userHandle); - mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle); - } + UserHandle userHandle = UserHandle.of(mUserInfo.id); + mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled, userHandle); + mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle); } private void removeUser() { diff --git a/src/com/android/settings/users/UserDialogs.java b/src/com/android/settings/users/UserDialogs.java index faaff4c118e..c2f2528530b 100644 --- a/src/com/android/settings/users/UserDialogs.java +++ b/src/com/android/settings/users/UserDialogs.java @@ -145,21 +145,6 @@ public final class UserDialogs { .create(); } - /** - * Creates a dialog to confirm that the user is ok to enable phone calls (no SMS). - * - * @param onConfirmListener Callback object for positive action - */ - public static Dialog createEnablePhoneCallsDialog(Context context, - DialogInterface.OnClickListener onConfirmListener) { - return new AlertDialog.Builder(context) - .setTitle(R.string.user_enable_calling_confirm_title) - .setMessage(R.string.user_enable_calling_confirm_message) - .setPositiveButton(R.string.okay, onConfirmListener) - .setNegativeButton(android.R.string.cancel, null) - .create(); - } - /** * Creates a dialog to confirm that the user is ok to start setting up a new user. * diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 2cfca950df0..9d5159e7787 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -125,6 +125,7 @@ public class UserSettings extends SettingsPreferenceFragment private static final String KEY_ADD_USER = "user_add"; private static final String KEY_ADD_SUPERVISED_USER = "supervised_user_add"; private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked"; + private static final String KEY_ENABLE_GUEST_TELEPHONY = "enable_guest_calling"; private static final String KEY_MULTIUSER_TOP_INTRO = "multiuser_top_intro"; private static final String KEY_TIMEOUT_TO_USER_ZERO = "timeout_to_user_zero_preference"; private static final String KEY_GUEST_CATEGORY = "guest_category"; @@ -215,6 +216,7 @@ public class UserSettings extends SettingsPreferenceFragment private EditUserInfoController mEditUserInfoController = new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY); private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController; + private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController; private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController; private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController; private TimeoutToUserZeroPreferenceController mTimeoutToUserZeroPreferenceController; @@ -304,6 +306,9 @@ public class UserSettings extends SettingsPreferenceFragment mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController( activity, KEY_ADD_USER_WHEN_LOCKED); + mGuestTelephonyPreferenceController = new GuestTelephonyPreferenceController( + activity, KEY_ENABLE_GUEST_TELEPHONY); + mRemoveGuestOnExitPreferenceController = new RemoveGuestOnExitPreferenceController( activity, KEY_REMOVE_GUEST_ON_EXIT, this, mHandler); @@ -315,6 +320,7 @@ public class UserSettings extends SettingsPreferenceFragment final PreferenceScreen screen = getPreferenceScreen(); mAddUserWhenLockedPreferenceController.displayPreference(screen); + mGuestTelephonyPreferenceController.displayPreference(screen); mRemoveGuestOnExitPreferenceController.displayPreference(screen); mMultiUserTopIntroPreferenceController.displayPreference(screen); mTimeoutToUserZeroPreferenceController.displayPreference(screen); @@ -322,6 +328,9 @@ public class UserSettings extends SettingsPreferenceFragment screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey()) .setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController); + screen.findPreference(mGuestTelephonyPreferenceController.getPreferenceKey()) + .setOnPreferenceChangeListener(mGuestTelephonyPreferenceController); + screen.findPreference(mRemoveGuestOnExitPreferenceController.getPreferenceKey()) .setOnPreferenceChangeListener(mRemoveGuestOnExitPreferenceController); @@ -393,6 +402,8 @@ public class UserSettings extends SettingsPreferenceFragment mAddUserWhenLockedPreferenceController.updateState(screen.findPreference( mAddUserWhenLockedPreferenceController.getPreferenceKey())); + mGuestTelephonyPreferenceController.updateState(screen.findPreference( + mGuestTelephonyPreferenceController.getPreferenceKey())); mTimeoutToUserZeroPreferenceController.updateState(screen.findPreference( mTimeoutToUserZeroPreferenceController.getPreferenceKey())); mRemoveGuestOnExitPreferenceController.updateState(screen.findPreference( @@ -1298,9 +1309,13 @@ public class UserSettings extends SettingsPreferenceFragment mAddUserWhenLockedPreferenceController.getPreferenceKey()); mAddUserWhenLockedPreferenceController.updateState(addUserOnLockScreen); - final Preference multiUserTopIntroPrefence = getPreferenceScreen().findPreference( + final Preference guestCallPreference = getPreferenceScreen().findPreference( + mGuestTelephonyPreferenceController.getPreferenceKey()); + mGuestTelephonyPreferenceController.updateState(guestCallPreference); + + final Preference multiUserTopIntroPreference = getPreferenceScreen().findPreference( mMultiUserTopIntroPreferenceController.getPreferenceKey()); - mMultiUserTopIntroPreferenceController.updateState(multiUserTopIntroPrefence); + mMultiUserTopIntroPreferenceController.updateState(multiUserTopIntroPreference); mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled); updateGuestPreferences(); updateGuestCategory(context, users); diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java index b865ea6ad15..90e098cf61a 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java @@ -47,7 +47,6 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager private static final int PRIMARY_USER_ID = 0; private final List mBaseRestrictions = new ArrayList<>(); - private final List mGuestRestrictions = new ArrayList<>(); private final Map> mRestrictionSources = new HashMap<>(); private final List mUserProfileInfos = new ArrayList<>(); private final Set mManagedProfiles = new HashSet<>(); @@ -55,6 +54,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager private boolean mIsQuietModeEnabled = false; private int[] profileIdsForUser = new int[0]; private boolean mUserSwitchEnabled; + private Bundle mDefaultGuestUserRestriction = new Bundle(); private @UserManager.UserSwitchabilityResult int mSwitchabilityStatus = UserManager.SWITCHABILITY_STATUS_OK; @@ -99,15 +99,24 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager @Implementation protected Bundle getDefaultGuestRestrictions() { - Bundle bundle = new Bundle(); - mGuestRestrictions.forEach(restriction -> bundle.putBoolean(restriction, true)); - return bundle; + return mDefaultGuestUserRestriction; + } + + @Implementation + protected void setDefaultGuestRestrictions(Bundle restrictions) { + mDefaultGuestUserRestriction = restrictions; } public void addGuestUserRestriction(String restriction) { - mGuestRestrictions.add(restriction); + mDefaultGuestUserRestriction.putBoolean(restriction, true); } + public boolean hasGuestUserRestriction(String restriction, boolean expectedValue) { + return mDefaultGuestUserRestriction.containsKey(restriction) + && mDefaultGuestUserRestriction.getBoolean(restriction) == expectedValue; + } + + @Implementation protected boolean hasUserRestriction(String restrictionKey) { return hasUserRestriction(restrictionKey, UserHandle.of(UserHandle.myUserId())); diff --git a/tests/robotests/src/com/android/settings/users/GuestTelephonyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/GuestTelephonyPreferenceControllerTest.java new file mode 100644 index 00000000000..aa84cb66576 --- /dev/null +++ b/tests/robotests/src/com/android/settings/users/GuestTelephonyPreferenceControllerTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.users; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Answers.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.SystemProperties; +import android.os.UserManager; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; +import com.android.settings.testutils.shadow.ShadowUserManager; +import com.android.settingslib.RestrictedSwitchPreference; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowUserManager.class, + ShadowDevicePolicyManager.class +}) +public class GuestTelephonyPreferenceControllerTest { + + @Mock(answer = RETURNS_DEEP_STUBS) + private PreferenceScreen mScreen; + + @Mock(answer = RETURNS_DEEP_STUBS) + private Context mContext; + private ShadowUserManager mUserManager; + private ShadowDevicePolicyManager mDpm; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mUserManager = ShadowUserManager.getShadow(); + mUserManager.setSupportsMultipleUsers(true); + mDpm = ShadowDevicePolicyManager.getShadow(); + } + + @After + public void tearDown() { + ShadowUserManager.reset(); + } + + @Test + public void displayPref_NotAdmin_shouldNotDisplay() { + mUserManager.setIsAdminUser(false); + + final GuestTelephonyPreferenceController controller = + new GuestTelephonyPreferenceController(mContext, "fake_key"); + final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class); + + when(preference.getKey()).thenReturn(controller.getPreferenceKey()); + when(mScreen.findPreference(preference.getKey())).thenReturn(preference); + + controller.displayPreference(mScreen); + + verify(preference).setVisible(false); + } + + @Test + public void updateState_NotAdmin_shouldNotDisplayPreference() { + mUserManager.setIsAdminUser(false); + + final GuestTelephonyPreferenceController controller = + new GuestTelephonyPreferenceController(mContext, "fake_key"); + final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class); + + controller.updateState(preference); + + verify(preference).setVisible(false); + } + + @Test + public void updateState_Admin_shouldDisplayPreference() { + SystemProperties.set("fw.max_users", Long.toBinaryString(4)); + mDpm.setDeviceOwner(null); + mUserManager.setIsAdminUser(true); + mUserManager.setUserSwitcherEnabled(true); + mUserManager.setSupportsMultipleUsers(true); + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED, true); + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_SYSTEM, true); + mUserManager.setUserTypeEnabled(UserManager.USER_TYPE_FULL_GUEST, true); + + final GuestTelephonyPreferenceController controller = + new GuestTelephonyPreferenceController(mContext, "fake_key"); + final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class); + + controller.updateState(preference); + + verify(preference).setVisible(true); + } + + @Test + public void setChecked_Guest_hasNoCallRestriction() { + mUserManager.setIsAdminUser(true); + + final GuestTelephonyPreferenceController controller = + new GuestTelephonyPreferenceController(mContext, "fake_key"); + + controller.setChecked(true); + + assertThat(mUserManager.hasGuestUserRestriction("no_outgoing_calls", false)).isTrue(); + assertThat(mUserManager.hasGuestUserRestriction("no_sms", true)).isTrue(); + } + + @Test + public void setUnchecked_Guest_hasCallRestriction() { + mUserManager.setIsAdminUser(true); + + final GuestTelephonyPreferenceController controller = + new GuestTelephonyPreferenceController(mContext, "fake_key"); + + controller.setChecked(false); + + assertThat(mUserManager.hasGuestUserRestriction("no_outgoing_calls", true)).isTrue(); + assertThat(mUserManager.hasGuestUserRestriction("no_sms", true)).isTrue(); + } + +} diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java index ccd2190db47..fad30aa01d4 100644 --- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java @@ -420,29 +420,6 @@ public class UserDetailsSettingsTest { verify(mPhonePref).setChecked(true); } - @Test - public void initialize_guestSelected_noCallRestriction_shouldSetPhonePreference() { - setupSelectedGuest(); - mUserManager.setIsAdminUser(true); - - mFragment.initialize(mActivity, mArguments); - - verify(mPhonePref).setTitle(R.string.user_enable_calling); - verify(mPhonePref).setChecked(true); - } - - @Test - public void initialize_guestSelected_callRestriction_shouldSetPhonePreference() { - setupSelectedGuest(); - mUserManager.setIsAdminUser(true); - mUserManager.addGuestUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS); - - mFragment.initialize(mActivity, mArguments); - - verify(mPhonePref).setTitle(R.string.user_enable_calling); - verify(mPhonePref).setChecked(false); - } - @Test public void initialize_switchUserDisallowed_shouldSetAdminDisabledOnSwitchPreference() { setupSelectedUser(); diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java index 97b8175a78e..588c6b150ff 100644 --- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java @@ -146,6 +146,8 @@ public class UserSettingsTest { mFragment = spy(new UserSettings()); ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController", mock(AddUserWhenLockedPreferenceController.class)); + ReflectionHelpers.setField(mFragment, "mGuestTelephonyPreferenceController", + mock(GuestTelephonyPreferenceController.class)); ReflectionHelpers.setField(mFragment, "mMultiUserTopIntroPreferenceController", mock(MultiUserTopIntroPreferenceController.class)); ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);