summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/test-current.txt2
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java4
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java10
-rw-r--r--core/java/android/window/TaskFragmentOrganizer.java9
-rw-r--r--core/java/android/window/WindowOrganizer.java7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java13
-rw-r--r--services/core/java/com/android/server/notification/SnoozeHelper.java29
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java29
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java99
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java40
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java14
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java19
15 files changed, 251 insertions, 57 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1796c7b971a9..1ca46428d708 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3436,7 +3436,7 @@ package android.window {
public class WindowOrganizer {
ctor public WindowOrganizer();
- method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public void applyTransaction(@NonNull android.window.WindowContainerTransaction);
}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index c17fbf19516b..dd955406e690 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2523,6 +2523,10 @@ public abstract class AccessibilityService extends Service {
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (mInfo != null && connection != null) {
+ if (!mInfo.isWithinParcelableSize()) {
+ throw new IllegalStateException(
+ "Cannot update service info: size is larger than safe parcelable limits.");
+ }
try {
connection.setServiceInfo(mInfo);
mInfo = null;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 530de0f3af6b..0cbcdb5a2b62 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -40,6 +40,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
@@ -1128,6 +1129,15 @@ public class AccessibilityServiceInfo implements Parcelable {
return 0;
}
+ /** @hide */
+ public final boolean isWithinParcelableSize() {
+ final Parcel parcel = Parcel.obtain();
+ writeToParcel(parcel, 0);
+ final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
+ parcel.recycle();
+ return result;
+ }
+
public void writeToParcel(Parcel parcel, int flagz) {
parcel.writeInt(eventTypes);
parcel.writeStringArray(packageNames);
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 2ef49c3e2aac..7745ff7c31d7 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -179,15 +179,6 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
super.applyTransaction(t);
}
- // Suppress the lint because it is not a registration method.
- @SuppressWarnings("ExecutorRegistration")
- @Override
- public int applySyncTransaction(@NonNull WindowContainerTransaction t,
- @NonNull WindowContainerTransactionCallback callback) {
- t.setTaskFragmentOrganizer(mInterface);
- return super.applySyncTransaction(t, callback);
- }
-
private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
@Override
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java
index 4ea5ea5694fa..a902003f66dc 100644
--- a/core/java/android/window/WindowOrganizer.java
+++ b/core/java/android/window/WindowOrganizer.java
@@ -61,9 +61,7 @@ public class WindowOrganizer {
* Apply multiple WindowContainer operations at once.
*
* Note that using this API requires the caller to hold
- * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using
- * {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
- * created by itself.
+ * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
*
* @param t The transaction to apply.
* @param callback This transaction will use the synchronization scheme described in
@@ -72,8 +70,7 @@ public class WindowOrganizer {
* @return An ID for the sync operation which will later be passed to transactionReady callback.
* This lets the caller differentiate overlapping sync operations.
*/
- @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
- conditional = true)
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
public int applySyncTransaction(@NonNull WindowContainerTransaction t,
@NonNull WindowContainerTransactionCallback callback) {
try {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 29194c58bd0c..3818a884c94a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1848,6 +1848,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
AccessibilityServiceInfo accessibilityServiceInfo;
try {
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+ if (!accessibilityServiceInfo.isWithinParcelableSize()) {
+ Slog.e(LOG_TAG, "Skipping service "
+ + accessibilityServiceInfo.getResolveInfo().getComponentInfo()
+ + " because service info size is larger than safe parcelable limits.");
+ continue;
+ }
if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
// Restore the crashed attribute.
accessibilityServiceInfo.crashed = true;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9c7d9447a1a6..40c0057fb3ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13053,12 +13053,17 @@ public class ActivityManagerService extends IActivityManager.Stub
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
+ enforceNotIsolatedCaller("registerReceiver");
+
// Allow Sandbox process to register only unexported receivers.
- if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
- enforceNotIsolatedCaller("registerReceiver");
- } else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) {
- enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+ boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
+ if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
+ && Process.isSdkSandboxUid(Binder.getCallingUid())
+ && !unexported) {
+ throw new SecurityException("SDK sandbox process not allowed to call "
+ + "registerReceiver");
}
+
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 15d7c1e7a210..ffce13f41f24 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -64,6 +64,9 @@ public class SnoozeHelper {
static final int CONCURRENT_SNOOZE_LIMIT = 500;
+ // A safe size for strings to be put in persistent storage, to avoid breaking the XML write.
+ static final int MAX_STRING_LENGTH = 1000;
+
protected static final String XML_TAG_NAME = "snoozed-notifications";
private static final String XML_SNOOZED_NOTIFICATION = "notification";
@@ -153,7 +156,7 @@ public class SnoozeHelper {
ArrayMap<String, Long> snoozed =
mPersistedSnoozedNotifications.get(getPkgKey(userId, pkg));
if (snoozed != null) {
- time = snoozed.get(key);
+ time = snoozed.get(getTrimmedString(key));
}
}
if (time == null) {
@@ -167,7 +170,7 @@ public class SnoozeHelper {
ArrayMap<String, String> snoozed =
mPersistedSnoozedNotificationsWithContext.get(getPkgKey(userId, pkg));
if (snoozed != null) {
- return snoozed.get(key);
+ return snoozed.get(getTrimmedString(key));
}
}
return null;
@@ -252,7 +255,8 @@ public class SnoozeHelper {
scheduleRepost(pkg, key, userId, duration);
Long activateAt = System.currentTimeMillis() + duration;
synchronized (mLock) {
- storeRecordLocked(pkg, key, userId, mPersistedSnoozedNotifications, activateAt);
+ storeRecordLocked(pkg, getTrimmedString(key), userId, mPersistedSnoozedNotifications,
+ activateAt);
}
}
@@ -263,8 +267,10 @@ public class SnoozeHelper {
int userId = record.getUser().getIdentifier();
if (contextId != null) {
synchronized (mLock) {
- storeRecordLocked(record.getSbn().getPackageName(), record.getKey(),
- userId, mPersistedSnoozedNotificationsWithContext, contextId);
+ storeRecordLocked(record.getSbn().getPackageName(),
+ getTrimmedString(record.getKey()),
+ userId, mPersistedSnoozedNotificationsWithContext,
+ getTrimmedString(contextId));
}
}
snooze(record);
@@ -281,6 +287,13 @@ public class SnoozeHelper {
}
}
+ private String getTrimmedString(String key) {
+ if (key != null && key.length() > MAX_STRING_LENGTH) {
+ return key.substring(0, MAX_STRING_LENGTH);
+ }
+ return key;
+ }
+
private <T> void storeRecordLocked(String pkg, String key, Integer userId,
ArrayMap<String, ArrayMap<String, T>> targets, T object) {
@@ -385,12 +398,14 @@ public class SnoozeHelper {
}
protected void repost(String key, int userId, boolean muteOnReturn) {
+ final String trimmedKey = getTrimmedString(key);
+
NotificationRecord record;
synchronized (mLock) {
final String pkg = mPackages.remove(key);
mUsers.remove(key);
- removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotifications);
- removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
+ removeRecordLocked(pkg, trimmedKey, userId, mPersistedSnoozedNotifications);
+ removeRecordLocked(pkg, trimmedKey, userId, mPersistedSnoozedNotificationsWithContext);
ArrayMap<String, NotificationRecord> records =
mSnoozedNotifications.get(getPkgKey(userId, pkg));
if (records == null) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 3b8673dc6a28..5d73de103e90 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2429,10 +2429,10 @@ final class InstallPackageHelper {
// will be null whereas dataOwnerPkg will contain information about the package
// which was uninstalled while keeping its data.
AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
+ PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName);
if (dataOwnerPkg == null) {
- PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
- if (ps != null) {
- dataOwnerPkg = ps.getPkg();
+ if (dataOwnerPs != null) {
+ dataOwnerPkg = dataOwnerPs.getPkg();
}
}
@@ -2460,6 +2460,7 @@ final class InstallPackageHelper {
if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
dataOwnerPkg.isDebuggable())) {
+ // Downgrade is not permitted; a lower version of the app will not be allowed
try {
PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
@@ -2468,6 +2469,28 @@ final class InstallPackageHelper {
return Pair.create(
PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
}
+ } else if (dataOwnerPs.isSystem()) {
+ // Downgrade is permitted, but system apps can't be downgraded below
+ // the version preloaded onto the system image
+ final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
+ dataOwnerPs);
+ if (disabledPs != null) {
+ dataOwnerPkg = disabledPs.getPkg();
+ }
+ if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) {
+ // Only restrict non-debuggable builds and non-debuggable version of the app
+ try {
+ PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
+ } catch (PackageManagerException e) {
+ String errorMsg =
+ "System app: " + packageName + " cannot be downgraded to"
+ + " older than its preloaded version on the system"
+ + " image. " + e.getMessage();
+ Slog.w(TAG, errorMsg);
+ return Pair.create(
+ PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
+ }
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 890c89152a7c..8507ad028a19 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@ class ShortcutPackage extends ShortcutPackageItem {
@NonNull List<ShortcutInfo> changedShortcuts) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"pushDynamicShortcuts() cannot publish disabled shortcuts");
+ ensureShortcutCountBeforePush();
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -437,7 +438,7 @@ class ShortcutPackage extends ShortcutPackageItem {
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
boolean deleted = false;
- if (oldShortcut == null) {
+ if (oldShortcut == null || !oldShortcut.isDynamic()) {
final ShortcutService service = mShortcutUser.mService;
final int maxShortcuts = service.getMaxActivityShortcuts();
@@ -446,18 +447,12 @@ class ShortcutPackage extends ShortcutPackageItem {
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
- Slog.e(TAG, "Error pushing shortcut. There are already "
- + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
- + " shortcuts limit when pushing the new shortcut " + newShortcut
- + ". Id of shortcuts currently available in system memory are "
- + activityShortcuts.stream().map(ShortcutInfo::getId)
- .collect(Collectors.joining(",", "[", "]")));
- // TODO: This should not have happened. If it does, identify the root cause where
- // possible, otherwise bail-out early to prevent memory issue.
+ // Root cause was discovered in b/233155034, so this should not be happening.
+ service.wtf("Error pushing shortcut. There are already "
+ + activityShortcuts.size() + " shortcuts.");
}
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
// Max has reached. Delete the shortcut with lowest rank.
-
// Sort by isManifestShortcut() and getRank().
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
@@ -473,7 +468,8 @@ class ShortcutPackage extends ShortcutPackageItem {
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
/*ignorePersistedShortcuts=*/ true) != null;
}
- } else {
+ }
+ if (oldShortcut != null) {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@ class ShortcutPackage extends ShortcutPackageItem {
return deleted;
}
+ private void ensureShortcutCountBeforePush() {
+ final ShortcutService service = mShortcutUser.mService;
+ // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+ final int maxShortcutPerApp = service.getMaxAppShortcuts();
+ synchronized (mLock) {
+ final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+ !si.isPinned()).collect(Collectors.toList());
+ if (appShortcuts.size() >= maxShortcutPerApp) {
+ // Max has reached. Removes shortcuts until they fall within the hard cap.
+ // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+ Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+ while (appShortcuts.size() >= maxShortcutPerApp) {
+ final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+ if (shortcut.isDeclaredInManifest()) {
+ // All shortcuts are manifest shortcuts and cannot be removed.
+ throw new IllegalArgumentException(getPackageName() + " has published "
+ + appShortcuts.size() + " manifest shortcuts across different"
+ + " activities.");
+ }
+ forceDeleteShortcutInner(shortcut.getId());
+ }
+ }
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*
@@ -1367,6 +1389,61 @@ class ShortcutPackage extends ShortcutPackageItem {
};
/**
+ * To sort by isManifestShortcut(), isDynamic(), getRank() and
+ * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+ * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+ *
+ * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+ * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+ *
+ * (Note the number of manifest shortcuts is always <= the max number, because if there are
+ * more, ShortcutParser would ignore the rest.)
+ */
+ final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+ ShortcutInfo b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
+ }
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ if (a.isDynamic() && b.isDynamic()) {
+ return Integer.compare(a.getRank(), b.getRank());
+ }
+ if (a.isDynamic()) {
+ return -1;
+ }
+ if (b.isDynamic()) {
+ return 1;
+ }
+ if (a.isCached() && b.isCached()) {
+ // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return 1;
+ }
+ // followed by bubbles.
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return 1;
+ }
+ }
+ if (a.isCached()) {
+ return -1;
+ }
+ if (b.isCached()) {
+ return 1;
+ }
+ return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+ };
+
+ /**
* Build a list of shortcuts for each target activity and return as a map. The result won't
* contain "floating" shortcuts because they don't belong on any activities.
*/
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index f2bcf5e461a7..2f3056e89614 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -181,6 +181,9 @@ public class ShortcutService extends IShortcutService.Stub {
static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
+ static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+ @VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@VisibleForTesting
@@ -257,6 +260,11 @@ public class ShortcutService extends IShortcutService.Stub {
String KEY_MAX_SHORTCUTS = "max_shortcuts";
/**
+ * Key name for the max shortcuts can be retained in system ram per app. (int)
+ */
+ String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+ /**
* Key name for icon compression quality, 0-100.
*/
String KEY_ICON_QUALITY = "icon_quality";
@@ -328,11 +336,16 @@ public class ShortcutService extends IShortcutService.Stub {
new SparseArray<>();
/**
- * Max number of dynamic + manifest shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each activity can have at a time.
*/
private int mMaxShortcuts;
/**
+ * Max number of shortcuts that can exists in system ram for each application.
+ */
+ private int mMaxShortcutsPerApp;
+
+ /**
* Max number of updating API calls that each application can make during the interval.
*/
int mMaxUpdatesPerInterval;
@@ -806,6 +819,9 @@ public class ShortcutService extends IShortcutService.Stub {
mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
+ mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1758,6 +1774,13 @@ public class ShortcutService extends IShortcutService.Stub {
}
/**
+ * Return the max number of shortcuts can be retaiend in system ram for each application.
+ */
+ int getMaxAppShortcuts() {
+ return mMaxShortcutsPerApp;
+ }
+
+ /**
* - Sends a notification to LauncherApps
* - Write to file
*/
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 22d6237411f3..0bd28467d649 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -188,7 +188,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
if (t == null) {
throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
}
- enforceTaskPermission("applySyncTransaction()", t);
+ enforceTaskPermission("applySyncTransaction()");
final CallerInfo caller = new CallerInfo();
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 8bead5774548..8d559fea3dc7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -248,6 +248,37 @@ public class SnoozeHelperTest extends UiServiceTestCase {
}
@Test
+ public void testLongTagPersistedNotification() throws Exception {
+ String longTag = "A".repeat(66000);
+ NotificationRecord r = getNotificationRecord("pkg", 1, longTag, UserHandle.SYSTEM);
+ mSnoozeHelper.snooze(r, 0);
+
+ // We store the full key in temp storage.
+ ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAm).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
+ assertEquals(66010, captor.getValue().getIntent().getStringExtra(EXTRA_KEY).length());
+
+ TypedXmlSerializer serializer = Xml.newFastSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+ serializer.startDocument(null, true);
+ mSnoozeHelper.writeXml(serializer);
+ serializer.endDocument();
+ serializer.flush();
+
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), "utf-8");
+ mSnoozeHelper.readXml(parser, 4);
+
+ mSnoozeHelper.scheduleRepostsForPersistedNotifications(5);
+
+ // We trim the key in persistent storage.
+ verify(mAm, times(2)).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
+ assertEquals(1000, captor.getValue().getIntent().getStringExtra(EXTRA_KEY).length());
+ }
+
+ @Test
public void testSnoozeForTime() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
@@ -595,13 +626,20 @@ public class SnoozeHelperTest extends UiServiceTestCase {
public void testClearData() {
// snooze 2 from same package
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
- NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+ NotificationRecord r2 = getNotificationRecord("pkg", 2, "two" + "2".repeat(66000),
+ UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
mSnoozeHelper.snooze(r2, 1000);
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r2.getSbn().getPackageName(), r2.getKey()));
+ assertFalse(0L == mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r.getUser().getIdentifier(), r.getSbn().getPackageName(),
+ r.getSbn().getKey()));
+ assertFalse(0L == mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r2.getUser().getIdentifier(), r2.getSbn().getPackageName(),
+ r2.getSbn().getKey()));
// clear data
mSnoozeHelper.clearData(UserHandle.USER_SYSTEM, "pkg");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 8202cd915527..679aeea17a2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -61,7 +61,6 @@ import android.window.TaskFragmentOrganizer;
import android.window.TaskFragmentOrganizerToken;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransactionCallback;
import androidx.test.filters.SmallTest;
@@ -335,19 +334,6 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
}
@Test
- public void testWindowContainerTransaction_setTaskFragmentOrganizer() {
- mOrganizer.applyTransaction(mTransaction);
-
- assertEquals(mIOrganizer, mTransaction.getTaskFragmentOrganizer());
-
- mTransaction = new WindowContainerTransaction();
- mOrganizer.applySyncTransaction(
- mTransaction, mock(WindowContainerTransactionCallback.class));
-
- assertEquals(mIOrganizer, mTransaction.getTaskFragmentOrganizer());
- }
-
- @Test
public void testApplyTransaction_enforceConfigurationChangeOnOrganizedTaskFragment()
throws RemoteException {
mOrganizer.applyTransaction(mTransaction);
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index ec18c6a696b8..7a53447c1eee 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -555,6 +555,11 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the address. See {@link PhoneAccount#getAddress}.
+ * <p>
+ * Note: The entire URI value is limited to 256 characters. This check is
+ * enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
+ * {@link IllegalArgumentException} to be thrown if URI is over 256.
*
* @param value The address of the phone account.
* @return The builder.
@@ -588,6 +593,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Sets the icon. See {@link PhoneAccount#getIcon}.
+ * <p>
+ * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory.
+ * This check is enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
*
* @param icon The icon to set.
*/
@@ -621,6 +630,10 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies an additional URI scheme supported by the {@link PhoneAccount}.
*
+ * <p>
+ * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will
+ * cause an {@link IllegalArgumentException} to be thrown when the account is registered.
+ *
* @param uriScheme The URI scheme.
* @return The builder.
*/
@@ -634,6 +647,12 @@ public final class PhoneAccount implements Parcelable {
/**
* Specifies the URI schemes supported by the {@link PhoneAccount}.
*
+ * <p>
+ * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is
+ * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any
+ * scheme will cause an {@link IllegalArgumentException} to be thrown when the account
+ * is registered.
+ *
* @param uriSchemes The URI schemes.
* @return The builder.
*/