Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3772a875 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/25705787',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/25705787', 'googleplex-android-review.googlesource.com/25828251', 'googleplex-android-review.googlesource.com/25949515', 'googleplex-android-review.googlesource.com/25842163', 'googleplex-android-review.googlesource.com/25891466'] into security-aosp-tm-release.

Change-Id: I81d3d1dd3b1d1d3d00f9c9b727a5af63d3c36a6d
parents e0fda2f2 b2371681
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -294,6 +294,43 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa
        XmlUtils.writeMapXml(mMap, out, this);
    }

    /**
     * Checks whether all keys and values are within the given character limit.
     * Note: Maximum character limit of String that can be saved to XML as part of bundle is 65535.
     * Otherwise IOException is thrown.
     * @param limit length of String keys and values in the PersistableBundle, including nested
     *                    PersistableBundles to check against.
     *
     * @hide
     */
    public boolean isBundleContentsWithinLengthLimit(int limit) {
        unparcel();
        if (mMap == null) {
            return true;
        }
        for (int i = 0; i < mMap.size(); i++) {
            if (mMap.keyAt(i) != null && mMap.keyAt(i).length() > limit) {
                return false;
            }
            final Object value = mMap.valueAt(i);
            if (value instanceof String && ((String) value).length() > limit) {
                return false;
            } else if (value instanceof String[]) {
                String[] stringArray =  (String[]) value;
                for (int j = 0; j < stringArray.length; j++) {
                    if (stringArray[j] != null
                            && stringArray[j].length() > limit) {
                        return false;
                    }
                }
            } else if (value instanceof PersistableBundle
                    && !((PersistableBundle) value).isBundleContentsWithinLengthLimit(limit)) {
                return false;
            }
        }
        return true;
    }

    /** @hide */
    static class MyReadMapCallback implements  XmlUtils.ReadMapCallback {
        @Override
+19 −4
Original line number Diff line number Diff line
@@ -101,6 +101,21 @@ public class UserManager {
    /** The userType of UserHandle.myUserId(); empty string if not a profile; null until cached. */
    private String mProfileTypeOfProcessUser = null;

    /** Maximum length of username.
     * @hide
     */
    public static final int MAX_USER_NAME_LENGTH = 100;

    /** Maximum length of user property String value.
     * @hide
     */
    public static final int MAX_ACCOUNT_STRING_LENGTH = 500;

    /** Maximum length of account options String values.
     * @hide
     */
    public static final int MAX_ACCOUNT_OPTIONS_LENGTH = 1000;

    /**
     * User type representing a {@link UserHandle#USER_SYSTEM system} user that is a human user.
     * This type of user cannot be created; it can only pre-exist on first boot.
@@ -3633,15 +3648,15 @@ public class UserManager {
     * time, the preferred user name and account information are used by the setup process for that
     * user.
     *
     * @param userName Optional name to assign to the user.
     * @param userName Optional name to assign to the user. Character limit is 100.
     * @param accountName Optional account name that will be used by the setup wizard to initialize
     *                    the user.
     *                    the user. Character limit is 500.
     * @param accountType Optional account type for the account to be created. This is required
     *                    if the account name is specified.
     *                    if the account name is specified. Character limit is 500.
     * @param accountOptions Optional bundle of data to be passed in during account creation in the
     *                       new user via {@link AccountManager#addAccount(String, String, String[],
     *                       Bundle, android.app.Activity, android.accounts.AccountManagerCallback,
     *                       Handler)}.
     *                       Handler)}. Character limit is 1000.
     * @return An Intent that can be launched from an Activity.
     * @see #USER_CREATION_FAILED_NOT_PERMITTED
     * @see #USER_CREATION_FAILED_NO_MORE_USERS
+12 −0
Original line number Diff line number Diff line
@@ -114,6 +114,14 @@ public class ConfirmUserCreationActivity extends AlertActivity
        if (cantCreateUser) {
            setResult(UserManager.USER_CREATION_FAILED_NOT_PERMITTED);
            return null;
        } else if (!(isUserPropertyWithinLimit(mUserName, UserManager.MAX_USER_NAME_LENGTH)
                && isUserPropertyWithinLimit(mAccountName, UserManager.MAX_ACCOUNT_STRING_LENGTH)
                && isUserPropertyWithinLimit(mAccountType, UserManager.MAX_ACCOUNT_STRING_LENGTH))
                || (mAccountOptions != null && !mAccountOptions.isBundleContentsWithinLengthLimit(
                UserManager.MAX_ACCOUNT_OPTIONS_LENGTH))) {
            setResult(UserManager.USER_CREATION_FAILED_NOT_PERMITTED);
            Log.i(TAG, "User properties must not exceed their character limits");
            return null;
        } else if (cantCreateAnyMoreUsers) {
            setResult(UserManager.USER_CREATION_FAILED_NO_MORE_USERS);
            return null;
@@ -141,4 +149,8 @@ public class ConfirmUserCreationActivity extends AlertActivity
        }
        finish();
    }

    private boolean isUserPropertyWithinLimit(String property, int limit) {
        return property == null || property.length() <= limit;
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -1279,8 +1279,8 @@ public class LockPatternUtils {
    }

    public boolean isUserInLockdown(int userId) {
        return getStrongAuthForUser(userId)
                == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
        return (getStrongAuthForUser(userId)
                & StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) != 0;
    }

    private static class WrappedCallback extends ICheckCredentialProgressCallback.Stub {
+36 −5
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ package com.android.internal.util;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;

import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -62,12 +66,15 @@ import java.util.List;
@SmallTest
public class LockPatternUtilsTest {

    private ILockSettings mLockSettings;
    private static final int USER_ID = 1;
    private static final int DEMO_USER_ID = 5;

    private LockPatternUtils mLockPatternUtils;

    private void configureTest(boolean isSecure, boolean isDemoUser, int deviceDemoMode)
            throws Exception {
        mLockSettings = Mockito.mock(ILockSettings.class);
        final Context context = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));

        final MockContentResolver cr = new MockContentResolver(context);
@@ -75,15 +82,14 @@ public class LockPatternUtilsTest {
        when(context.getContentResolver()).thenReturn(cr);
        Settings.Global.putInt(cr, Settings.Global.DEVICE_DEMO_MODE, deviceDemoMode);

        final ILockSettings ils = Mockito.mock(ILockSettings.class);
        when(ils.getCredentialType(DEMO_USER_ID)).thenReturn(
        when(mLockSettings.getCredentialType(DEMO_USER_ID)).thenReturn(
                isSecure ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
                         : LockPatternUtils.CREDENTIAL_TYPE_NONE);
        when(ils.getLong("lockscreen.password_type", PASSWORD_QUALITY_UNSPECIFIED, DEMO_USER_ID))
                .thenReturn((long) PASSWORD_QUALITY_MANAGED);
        when(mLockSettings.getLong("lockscreen.password_type", PASSWORD_QUALITY_UNSPECIFIED,
                DEMO_USER_ID)).thenReturn((long) PASSWORD_QUALITY_MANAGED);
        // TODO(b/63758238): stop spying the class under test
        mLockPatternUtils = spy(new LockPatternUtils(context));
        when(mLockPatternUtils.getLockSettings()).thenReturn(ils);
        when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
        doReturn(true).when(mLockPatternUtils).hasSecureLockScreen();

        final UserInfo userInfo = Mockito.mock(UserInfo.class);
@@ -93,6 +99,31 @@ public class LockPatternUtilsTest {
        when(context.getSystemService(Context.USER_SERVICE)).thenReturn(um);
    }

    @Test
    public void isUserInLockDown() throws Exception {
        configureTest(true, false, 2);

        // GIVEN strong auth not required
        when(mLockSettings.getStrongAuthForUser(USER_ID)).thenReturn(STRONG_AUTH_NOT_REQUIRED);

        // THEN user isn't in lockdown
        assertFalse(mLockPatternUtils.isUserInLockdown(USER_ID));

        // GIVEN lockdown
        when(mLockSettings.getStrongAuthForUser(USER_ID)).thenReturn(
                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);

        // THEN user is in lockdown
        assertTrue(mLockPatternUtils.isUserInLockdown(USER_ID));

        // GIVEN lockdown and lockout
        when(mLockSettings.getStrongAuthForUser(USER_ID)).thenReturn(
                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN | STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);

        // THEN user is in lockdown
        assertTrue(mLockPatternUtils.isUserInLockdown(USER_ID));
    }

    @Test
    public void isLockScreenDisabled_isDemoUser_true() throws Exception {
        configureTest(false, true, 2);
Loading