summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-21 19:18:35 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-21 19:18:35 +0000
commit5a3e5cdddb7505dfbcc6aa1ff44f8806dfbf48fd (patch)
tree58f9c18a59b8c526c2c6e70784d9e1dab737fd54
parentf45c3bc5faa0ce5433bb5dc3e8d1311c8f77b85e (diff)
parentb79f404eab1ddbf19a5788bbee1b47b0834255dc (diff)
downloadbase-5a3e5cdddb7505dfbcc6aa1ff44f8806dfbf48fd.tar.gz
Merge cherrypicks of ['googleplex-android-review.googlesource.com/25753314', 'googleplex-android-review.googlesource.com/25791015', 'googleplex-android-review.googlesource.com/25704204', 'googleplex-android-review.googlesource.com/25939141', 'googleplex-android-review.googlesource.com/25851459'] into 24Q1-release.
Change-Id: Ib6ba7a1407c3bcbac7fc1598c0948daa437dbb3b
-rw-r--r--core/java/android/os/PersistableBundle.java37
-rw-r--r--core/java/android/os/UserManager.java23
-rw-r--r--core/java/com/android/internal/app/ConfirmUserCreationActivity.java12
-rw-r--r--core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java2
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java4
-rw-r--r--core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java41
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java38
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java7
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java29
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java102
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java35
13 files changed, 308 insertions, 30 deletions
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 02704f5b346b..236194d16ad8 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -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
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c280d132ae38..1994cd740c85 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -106,6 +106,21 @@ public class UserManager {
/** Whether the device is in headless system user mode; null until cached. */
private static Boolean sIsHeadlessSystemUser = 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.
@@ -4423,15 +4438,15 @@ public class UserManager {
* This API should only be called if the current user is an {@link #isAdminUser() admin} user,
* as otherwise the returned intent will not be able to create a 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
diff --git a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
index 0a28997885ff..b4e87498f09b 100644
--- a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
+++ b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
@@ -116,6 +116,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;
@@ -144,4 +152,8 @@ public class ConfirmUserCreationActivity extends AlertActivity
}
finish();
}
+
+ private boolean isUserPropertyWithinLimit(String property, int limit) {
+ return property == null || property.length() <= limit;
+ }
}
diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
index e3bfb38802db..e419d13730c2 100644
--- a/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
@@ -38,7 +38,7 @@ import java.util.List;
public class ParsedAttributionImpl implements ParsedAttribution, Parcelable {
/** Maximum amount of attributions per package */
- static final int MAX_NUM_ATTRIBUTIONS = 10000;
+ static final int MAX_NUM_ATTRIBUTIONS = 400;
/** Tag of the attribution */
private @NonNull String tag;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index bf8e6135fd01..757978b71a01 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1384,8 +1384,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 {
diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
index 0df5b0a4093e..dcaf67660ffa 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
@@ -19,8 +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.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED;
+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 com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED;
import static com.google.common.truth.Truth.assertThat;
@@ -76,12 +78,15 @@ public class LockPatternUtilsTest {
@Rule
public final RavenwoodRule mRavenwood = new RavenwoodRule();
+ 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);
@@ -89,15 +94,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);
@@ -108,6 +112,31 @@ public class LockPatternUtilsTest {
}
@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);
assertTrue(mLockPatternUtils.isLockScreenDisabled(DEMO_USER_ID));
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index d80638af697e..8e8b9956f3cc 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2880,6 +2880,10 @@ public class AppOpsService extends IAppOpsService.Stub {
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
+ if (proxyAttributionTag != null
+ && !isAttributionTagDefined(packageName, proxyPackageName, proxyAttributionTag)) {
+ proxyAttributionTag = null;
+ }
synchronized (this) {
final Ops ops = getOpsLocked(uid, packageName, attributionTag,
@@ -3453,6 +3457,10 @@ public class AppOpsService extends IAppOpsService.Stub {
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
+ if (proxyAttributionTag != null
+ && !isAttributionTagDefined(packageName, proxyPackageName, proxyAttributionTag)) {
+ proxyAttributionTag = null;
+ }
boolean isRestricted = false;
int startType = START_TYPE_FAILED;
@@ -4306,6 +4314,36 @@ public class AppOpsService extends IAppOpsService.Stub {
return false;
}
+ /**
+ * Checks to see if the attribution tag is defined in either package or proxyPackage.
+ * This method is intended for ProxyAttributionTag validation and returns false
+ * if it does not exist in either one of them.
+ *
+ * @param packageName Name of the package
+ * @param proxyPackageName Name of the proxy package
+ * @param attributionTag attribution tag to be checked
+ *
+ * @return boolean specifying if attribution tag is valid or not
+ */
+ private boolean isAttributionTagDefined(@Nullable String packageName,
+ @Nullable String proxyPackageName,
+ @Nullable String attributionTag) {
+ if (packageName == null) {
+ return false;
+ } else if (attributionTag == null) {
+ return true;
+ }
+ PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
+ if (proxyPackageName != null) {
+ AndroidPackage proxyPkg = pmInt.getPackage(proxyPackageName);
+ if (proxyPkg != null && isAttributionInPackage(proxyPkg, attributionTag)) {
+ return true;
+ }
+ }
+ AndroidPackage pkg = pmInt.getPackage(packageName);
+ return isAttributionInPackage(pkg, attributionTag);
+ }
+
private void logVerifyAndGetBypassFailure(int uid, @NonNull SecurityException e,
@NonNull String methodName) {
if (Process.isIsolated(uid)) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6b956e2ae9d7..a0e69cff12a5 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5111,8 +5111,10 @@ public class NotificationManagerService extends SystemService {
for (int userId : mUm.getProfileIds(info.userid, false)) {
try {
int uid = getUidForPackageAndUser(pkg, UserHandle.of(userId));
- VersionedPackage vp = new VersionedPackage(pkg, uid);
- nlf.addPackage(vp);
+ if (uid != INVALID_UID) {
+ VersionedPackage vp = new VersionedPackage(pkg, uid);
+ nlf.addPackage(vp);
+ }
} catch (Exception e) {
// pkg doesn't exist on that user; skip
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 117ad4729efb..2ed4dfa4e8db 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -4580,7 +4580,9 @@ final class InstallPackageHelper {
private void assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg)
throws PackageManagerException {
- if (!AndroidPackageLegacyUtils.isPrivileged(pkg) && (pkg.getSharedUserId() != null)) {
+ if (!AndroidPackageLegacyUtils.isPrivileged(pkg)
+ && (pkg.getSharedUserId() != null)
+ && !pkg.isLeavingSharedUser()) {
SharedUserSetting sharedUserSetting = null;
try {
synchronized (mPm.mLock) {
@@ -4620,7 +4622,8 @@ final class InstallPackageHelper {
if (((scanFlags & SCAN_AS_PRIVILEGED) == 0)
&& !AndroidPackageLegacyUtils.isPrivileged(pkg)
&& (pkg.getSharedUserId() != null)
- && !skipVendorPrivilegeScan) {
+ && !skipVendorPrivilegeScan
+ && !pkg.isLeavingSharedUser()) {
SharedUserSetting sharedUserSetting = null;
synchronized (mPm.mLock) {
try {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c48eccf2aac5..6f75a96c05db 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -285,8 +285,6 @@ public class UserManagerService extends IUserManager.Stub {
private static final int USER_VERSION = 11;
- private static final int MAX_USER_STRING_LENGTH = 500;
-
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
static final int WRITE_USER_MSG = 1;
@@ -4420,16 +4418,18 @@ public class UserManagerService extends IUserManager.Stub {
if (userData.persistSeedData) {
if (userData.seedAccountName != null) {
serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME,
- truncateString(userData.seedAccountName));
+ truncateString(userData.seedAccountName,
+ UserManager.MAX_ACCOUNT_STRING_LENGTH));
}
if (userData.seedAccountType != null) {
serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE,
- truncateString(userData.seedAccountType));
+ truncateString(userData.seedAccountType,
+ UserManager.MAX_ACCOUNT_STRING_LENGTH));
}
}
if (userInfo.name != null) {
serializer.startTag(null, TAG_NAME);
- serializer.text(truncateString(userInfo.name));
+ serializer.text(truncateString(userInfo.name, UserManager.MAX_USER_NAME_LENGTH));
serializer.endTag(null, TAG_NAME);
}
synchronized (mRestrictionsLock) {
@@ -4493,11 +4493,11 @@ public class UserManagerService extends IUserManager.Stub {
serializer.endDocument();
}
- private String truncateString(String original) {
- if (original == null || original.length() <= MAX_USER_STRING_LENGTH) {
+ private String truncateString(String original, int limit) {
+ if (original == null || original.length() <= limit) {
return original;
}
- return original.substring(0, MAX_USER_STRING_LENGTH);
+ return original.substring(0, limit);
}
/*
@@ -4964,7 +4964,7 @@ public class UserManagerService extends IUserManager.Stub {
@UserIdInt int parentId, boolean preCreate, @Nullable String[] disallowedPackages,
@NonNull TimingsTraceAndSlog t, @Nullable Object token)
throws UserManager.CheckedUserOperationException {
- String truncatedName = truncateString(name);
+ String truncatedName = truncateString(name, UserManager.MAX_USER_NAME_LENGTH);
final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
if (userTypeDetails == null) {
throwCheckedUserOperationException(
@@ -6549,9 +6549,14 @@ public class UserManagerService extends IUserManager.Stub {
Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId);
return;
}
- userData.seedAccountName = truncateString(accountName);
- userData.seedAccountType = truncateString(accountType);
- userData.seedAccountOptions = accountOptions;
+ userData.seedAccountName = truncateString(accountName,
+ UserManager.MAX_ACCOUNT_STRING_LENGTH);
+ userData.seedAccountType = truncateString(accountType,
+ UserManager.MAX_ACCOUNT_STRING_LENGTH);
+ if (accountOptions != null && accountOptions.isBundleContentsWithinLengthLimit(
+ UserManager.MAX_ACCOUNT_OPTIONS_LENGTH)) {
+ userData.seedAccountOptions = accountOptions;
+ }
userData.persistSeedData = persist;
}
if (persist) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index fd6aa0c1ffab..e6ccbfd3fcdd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -538,7 +538,7 @@ public final class UserManagerServiceTest {
@Test
public void testCreateUserWithLongName_TruncatesName() {
UserInfo user = mUms.createUserWithThrow(generateLongString(), USER_TYPE_FULL_SECONDARY, 0);
- assertThat(user.name.length()).isEqualTo(500);
+ assertThat(user.name.length()).isEqualTo(UserManager.MAX_USER_NAME_LENGTH);
UserInfo user1 = mUms.createUserWithThrow("Test", USER_TYPE_FULL_SECONDARY, 0);
assertThat(user1.name.length()).isEqualTo(4);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index a743fff5d2ea..06be456be0db 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.testng.Assert.assertEquals;
@@ -33,6 +34,7 @@ import android.content.pm.UserProperties;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Postsubmit;
@@ -1632,6 +1634,106 @@ public final class UserManagerTest {
assertThat(mainUserCount).isEqualTo(1);
}
+ @Test
+ public void testAddUserAccountData_validStringValuesAreSaved_validBundleIsSaved() {
+ assumeManagedUsersSupported();
+
+ String userName = "User";
+ String accountName = "accountName";
+ String accountType = "accountType";
+ String arrayKey = "StringArrayKey";
+ String stringKey = "StringKey";
+ String intKey = "IntKey";
+ String nestedBundleKey = "PersistableBundleKey";
+ String value1 = "Value 1";
+ String value2 = "Value 2";
+ String value3 = "Value 3";
+
+ UserInfo userInfo = mUserManager.createUser(userName,
+ UserManager.USER_TYPE_FULL_SECONDARY, 0);
+
+ PersistableBundle accountOptions = new PersistableBundle();
+ String[] stringArray = {value1, value2};
+ accountOptions.putInt(intKey, 1234);
+ PersistableBundle nested = new PersistableBundle();
+ nested.putString(stringKey, value3);
+ accountOptions.putPersistableBundle(nestedBundleKey, nested);
+ accountOptions.putStringArray(arrayKey, stringArray);
+
+ mUserManager.clearSeedAccountData();
+ mUserManager.setSeedAccountData(mContext.getUserId(), accountName,
+ accountType, accountOptions);
+
+ //assert userName accountName and accountType were saved correctly
+ assertTrue(mUserManager.getUserInfo(userInfo.id).name.equals(userName));
+ assertTrue(mUserManager.getSeedAccountName().equals(accountName));
+ assertTrue(mUserManager.getSeedAccountType().equals(accountType));
+
+ //assert bundle with correct values was added
+ assertThat(mUserManager.getSeedAccountOptions().containsKey(arrayKey)).isTrue();
+ assertThat(mUserManager.getSeedAccountOptions().getPersistableBundle(nestedBundleKey)
+ .getString(stringKey)).isEqualTo(value3);
+ assertThat(mUserManager.getSeedAccountOptions().getStringArray(arrayKey)[0])
+ .isEqualTo(value1);
+
+ mUserManager.removeUser(userInfo.id);
+ }
+
+ @Test
+ public void testAddUserAccountData_invalidStringValuesAreTruncated_invalidBundleIsDropped() {
+ assumeManagedUsersSupported();
+
+ String tooLongString = generateLongString();
+ String userName = "User " + tooLongString;
+ String accountType = "Account Type " + tooLongString;
+ String accountName = "accountName " + tooLongString;
+ String arrayKey = "StringArrayKey";
+ String stringKey = "StringKey";
+ String intKey = "IntKey";
+ String nestedBundleKey = "PersistableBundleKey";
+ String value1 = "Value 1";
+ String value2 = "Value 2";
+
+ UserInfo userInfo = mUserManager.createUser(userName,
+ UserManager.USER_TYPE_FULL_SECONDARY, 0);
+
+ PersistableBundle accountOptions = new PersistableBundle();
+ String[] stringArray = {value1, value2};
+ accountOptions.putInt(intKey, 1234);
+ PersistableBundle nested = new PersistableBundle();
+ nested.putString(stringKey, tooLongString);
+ accountOptions.putPersistableBundle(nestedBundleKey, nested);
+ accountOptions.putStringArray(arrayKey, stringArray);
+ mUserManager.clearSeedAccountData();
+ mUserManager.setSeedAccountData(mContext.getUserId(), accountName,
+ accountType, accountOptions);
+
+ //assert userName was truncated
+ assertTrue(mUserManager.getUserInfo(userInfo.id).name.length()
+ == UserManager.MAX_USER_NAME_LENGTH);
+
+ //assert accountName and accountType got truncated
+ assertTrue(mUserManager.getSeedAccountName().length()
+ == UserManager.MAX_ACCOUNT_STRING_LENGTH);
+ assertTrue(mUserManager.getSeedAccountType().length()
+ == UserManager.MAX_ACCOUNT_STRING_LENGTH);
+
+ //assert bundle with invalid values was dropped
+ assertThat(mUserManager.getSeedAccountOptions() == null).isTrue();
+
+ mUserManager.removeUser(userInfo.id);
+ }
+
+ private String generateLongString() {
+ String partialString = "Test Name Test Name Test Name Test Name Test Name Test Name Test "
+ + "Name Test Name Test Name Test Name "; //String of length 100
+ StringBuilder resultString = new StringBuilder();
+ for (int i = 0; i < 600; i++) {
+ resultString.append(partialString);
+ }
+ return resultString.toString();
+ }
+
private boolean isPackageInstalledForUser(String packageName, int userId) {
try {
return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index b93fffcb1869..d7c2c6e645d2 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -110,6 +110,7 @@ import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Matchers.anyBoolean;
@@ -11001,6 +11002,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testMigrateNotificationFilter_invalidPackage() throws Exception {
+ int[] userIds = new int[] {mUserId, 1000};
+ when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);
+ List<String> disallowedApps = ImmutableList.of("apples", "bananas", "cherries");
+ for (int userId : userIds) {
+ when(mPackageManager.getPackageUid("apples", 0, userId)).thenThrow(
+ new RemoteException(""));
+ when(mPackageManager.getPackageUid("bananas", 0, userId)).thenReturn(9000);
+ when(mPackageManager.getPackageUid("cherries", 0, userId)).thenReturn(9001);
+ }
+
+ when(mListeners.getNotificationListenerFilter(any())).thenReturn(
+ new NotificationListenerFilter());
+
+ mBinderService.migrateNotificationFilter(null,
+ FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
+ disallowedApps);
+
+ ArgumentCaptor<NotificationListenerFilter> captor =
+ ArgumentCaptor.forClass(NotificationListenerFilter.class);
+ verify(mListeners).setNotificationListenerFilter(any(), captor.capture());
+
+ assertEquals(FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ONGOING,
+ captor.getValue().getTypes());
+ // valid values stay
+ assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("bananas", 9000)));
+ assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("cherries", 9001)));
+ // don't store invalid values
+ for (VersionedPackage vp : captor.getValue().getDisallowedPackages()) {
+ assertNotEquals("apples", vp.getPackageName());
+ }
+ }
+
+ @Test
public void testMigrateNotificationFilter_noPreexistingFilter() throws Exception {
int[] userIds = new int[] {mUserId};
when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(userIds);