Skip to content

Commit 984a78d

Browse files
Android Build Coastguard Workerandroid-build-merge-worker-robot
authored andcommitted
Merge cherrypicks of ['googleplex-android-review.googlesource.com/21159680', 'googleplex-android-review.googlesource.com/21266934', 'googleplex-android-review.googlesource.com/21389013', 'googleplex-android-review.googlesource.com/21422765', 'googleplex-android-review.googlesource.com/21238189', 'googleplex-android-review.googlesource.com/21568941', 'googleplex-android-review.googlesource.com/21534012', 'googleplex-android-review.googlesource.com/21649216', 'googleplex-android-review.googlesource.com/21688022'] into tm-qpr2-release. am: e24735c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22317051 Change-Id: I227d73a8f240ac3592f2c045820a06a8c55e8129 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
2 parents cf90d55 + e24735c commit 984a78d

15 files changed

Lines changed: 231 additions & 33 deletions

File tree

core/api/test-current.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3452,7 +3452,7 @@ package android.window {
34523452

34533453
public class WindowOrganizer {
34543454
ctor public WindowOrganizer();
3455-
method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
3455+
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
34563456
method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public void applyTransaction(@NonNull android.window.WindowContainerTransaction);
34573457
}
34583458

core/java/android/accessibilityservice/AccessibilityService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,10 @@ private void sendServiceInfo() {
25232523
IAccessibilityServiceConnection connection =
25242524
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
25252525
if (mInfo != null && connection != null) {
2526+
if (!mInfo.isWithinParcelableSize()) {
2527+
throw new IllegalStateException(
2528+
"Cannot update service info: size is larger than safe parcelable limits.");
2529+
}
25262530
try {
25272531
connection.setServiceInfo(mInfo);
25282532
mInfo = null;

core/java/android/accessibilityservice/AccessibilityServiceInfo.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import android.graphics.drawable.Drawable;
4141
import android.hardware.fingerprint.FingerprintManager;
4242
import android.os.Build;
43+
import android.os.IBinder;
4344
import android.os.Parcel;
4445
import android.os.Parcelable;
4546
import android.os.RemoteException;
@@ -1128,6 +1129,15 @@ public int describeContents() {
11281129
return 0;
11291130
}
11301131

1132+
/** @hide */
1133+
public final boolean isWithinParcelableSize() {
1134+
final Parcel parcel = Parcel.obtain();
1135+
writeToParcel(parcel, 0);
1136+
final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
1137+
parcel.recycle();
1138+
return result;
1139+
}
1140+
11311141
public void writeToParcel(Parcel parcel, int flagz) {
11321142
parcel.writeInt(eventTypes);
11331143
parcel.writeStringArray(packageNames);

core/java/android/window/WindowOrganizer.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@ public void applyTransaction(@NonNull WindowContainerTransaction t) {
6161
* Apply multiple WindowContainer operations at once.
6262
*
6363
* Note that using this API requires the caller to hold
64-
* {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using
65-
* {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
66-
* created by itself.
64+
* {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
6765
*
6866
* @param t The transaction to apply.
6967
* @param callback This transaction will use the synchronization scheme described in
@@ -72,8 +70,7 @@ public void applyTransaction(@NonNull WindowContainerTransaction t) {
7270
* @return An ID for the sync operation which will later be passed to transactionReady callback.
7371
* This lets the caller differentiate overlapping sync operations.
7472
*/
75-
@RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
76-
conditional = true)
73+
@RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
7774
public int applySyncTransaction(@NonNull WindowContainerTransaction t,
7875
@NonNull WindowContainerTransactionCallback callback) {
7976
try {

core/java/com/android/internal/app/ChooserActivity.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
2222
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
2323
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
24+
import static android.content.ContentProvider.getUserIdFromUri;
2425
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
2526
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
2627

@@ -161,6 +162,7 @@
161162
import java.util.Map;
162163
import java.util.Objects;
163164
import java.util.function.Supplier;
165+
import java.util.stream.Collectors;
164166

165167
/**
166168
* The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1424,7 +1426,11 @@ private ViewGroup displayImageContentPreview(Intent targetIntent, LayoutInflater
14241426

14251427
String action = targetIntent.getAction();
14261428
if (Intent.ACTION_SEND.equals(action)) {
1427-
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
1429+
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
1430+
if (!validForContentPreview(uri)) {
1431+
contentPreviewLayout.setVisibility(View.GONE);
1432+
return contentPreviewLayout;
1433+
}
14281434
imagePreview.findViewById(R.id.content_preview_image_1_large)
14291435
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
14301436
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
@@ -1434,7 +1440,7 @@ private ViewGroup displayImageContentPreview(Intent targetIntent, LayoutInflater
14341440
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
14351441
List<Uri> imageUris = new ArrayList<>();
14361442
for (Uri uri : uris) {
1437-
if (isImageType(resolver.getType(uri))) {
1443+
if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
14381444
imageUris.add(uri);
14391445
}
14401446
}
@@ -1544,9 +1550,16 @@ private ViewGroup displayFileContentPreview(Intent targetIntent, LayoutInflater
15441550
String action = targetIntent.getAction();
15451551
if (Intent.ACTION_SEND.equals(action)) {
15461552
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
1553+
if (!validForContentPreview(uri)) {
1554+
contentPreviewLayout.setVisibility(View.GONE);
1555+
return contentPreviewLayout;
1556+
}
15471557
loadFileUriIntoView(uri, contentPreviewLayout);
15481558
} else {
15491559
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
1560+
uris = uris.stream()
1561+
.filter(ChooserActivity::validForContentPreview)
1562+
.collect(Collectors.toList());
15501563
int uriCount = uris.size();
15511564

15521565
if (uriCount == 0) {
@@ -1605,6 +1618,24 @@ private void loadFileUriIntoView(final Uri uri, final View parent) {
16051618
}
16061619
}
16071620

1621+
/**
1622+
* Indicate if the incoming content URI should be allowed.
1623+
*
1624+
* @param uri the uri to test
1625+
* @return true if the URI is allowed for content preview
1626+
*/
1627+
private static boolean validForContentPreview(Uri uri) throws SecurityException {
1628+
if (uri == null) {
1629+
return false;
1630+
}
1631+
int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
1632+
if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
1633+
Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
1634+
return false;
1635+
}
1636+
return true;
1637+
}
1638+
16081639
@VisibleForTesting
16091640
protected boolean isImageType(String mimeType) {
16101641
return mimeType != null && mimeType.startsWith("image/");

services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,12 @@ private boolean readInstalledAccessibilityServiceLocked(AccessibilityUserState u
18481848
AccessibilityServiceInfo accessibilityServiceInfo;
18491849
try {
18501850
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
1851+
if (!accessibilityServiceInfo.isWithinParcelableSize()) {
1852+
Slog.e(LOG_TAG, "Skipping service "
1853+
+ accessibilityServiceInfo.getResolveInfo().getComponentInfo()
1854+
+ " because service info size is larger than safe parcelable limits.");
1855+
continue;
1856+
}
18511857
if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
18521858
// Restore the crashed attribute.
18531859
accessibilityServiceInfo.crashed = true;

services/core/java/com/android/server/am/ActivityManagerService.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13087,12 +13087,17 @@ public Intent registerReceiver(IApplicationThread caller, String callerPackage,
1308713087
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
1308813088
String callerFeatureId, String receiverId, IIntentReceiver receiver,
1308913089
IntentFilter filter, String permission, int userId, int flags) {
13090+
enforceNotIsolatedCaller("registerReceiver");
13091+
1309013092
// Allow Sandbox process to register only unexported receivers.
13091-
if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
13092-
enforceNotIsolatedCaller("registerReceiver");
13093-
} else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) {
13094-
enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
13093+
boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
13094+
if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
13095+
&& Process.isSdkSandboxUid(Binder.getCallingUid())
13096+
&& !unexported) {
13097+
throw new SecurityException("SDK sandbox process not allowed to call "
13098+
+ "registerReceiver");
1309513099
}
13100+
1309613101
ArrayList<Intent> stickyIntents = null;
1309713102
ProcessRecord callerApp = null;
1309813103
final boolean visibleToInstantApps

services/core/java/com/android/server/pm/InstallPackageHelper.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,10 +2429,10 @@ Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
24292429
// will be null whereas dataOwnerPkg will contain information about the package
24302430
// which was uninstalled while keeping its data.
24312431
AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
2432+
PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName);
24322433
if (dataOwnerPkg == null) {
2433-
PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
2434-
if (ps != null) {
2435-
dataOwnerPkg = ps.getPkg();
2434+
if (dataOwnerPs != null) {
2435+
dataOwnerPkg = dataOwnerPs.getPkg();
24362436
}
24372437
}
24382438

@@ -2460,6 +2460,7 @@ Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
24602460
if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
24612461
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
24622462
dataOwnerPkg.isDebuggable())) {
2463+
// Downgrade is not permitted; a lower version of the app will not be allowed
24632464
try {
24642465
PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
24652466
} catch (PackageManagerException e) {
@@ -2468,6 +2469,28 @@ Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
24682469
return Pair.create(
24692470
PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
24702471
}
2472+
} else if (dataOwnerPs.isSystem()) {
2473+
// Downgrade is permitted, but system apps can't be downgraded below
2474+
// the version preloaded onto the system image
2475+
final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
2476+
dataOwnerPs);
2477+
if (disabledPs != null) {
2478+
dataOwnerPkg = disabledPs.getPkg();
2479+
}
2480+
if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) {
2481+
// Only restrict non-debuggable builds and non-debuggable version of the app
2482+
try {
2483+
PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
2484+
} catch (PackageManagerException e) {
2485+
String errorMsg =
2486+
"System app: " + packageName + " cannot be downgraded to"
2487+
+ " older than its preloaded version on the system"
2488+
+ " image. " + e.getMessage();
2489+
Slog.w(TAG, errorMsg);
2490+
return Pair.create(
2491+
PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
2492+
}
2493+
}
24712494
}
24722495
}
24732496
}

services/core/java/com/android/server/pm/ShortcutPackage.java

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,15 @@ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut,
430430
@NonNull List<ShortcutInfo> changedShortcuts) {
431431
Preconditions.checkArgument(newShortcut.isEnabled(),
432432
"pushDynamicShortcuts() cannot publish disabled shortcuts");
433+
ensureShortcutCountBeforePush();
433434

434435
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
435436

436437
changedShortcuts.clear();
437438
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
438439
boolean deleted = false;
439440

440-
if (oldShortcut == null) {
441+
if (oldShortcut == null || !oldShortcut.isDynamic()) {
441442
final ShortcutService service = mShortcutUser.mService;
442443
final int maxShortcuts = service.getMaxActivityShortcuts();
443444

@@ -446,18 +447,12 @@ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut,
446447
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
447448

448449
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
449-
Slog.e(TAG, "Error pushing shortcut. There are already "
450-
+ activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
451-
+ " shortcuts limit when pushing the new shortcut " + newShortcut
452-
+ ". Id of shortcuts currently available in system memory are "
453-
+ activityShortcuts.stream().map(ShortcutInfo::getId)
454-
.collect(Collectors.joining(",", "[", "]")));
455-
// TODO: This should not have happened. If it does, identify the root cause where
456-
// possible, otherwise bail-out early to prevent memory issue.
450+
// Root cause was discovered in b/233155034, so this should not be happening.
451+
service.wtf("Error pushing shortcut. There are already "
452+
+ activityShortcuts.size() + " shortcuts.");
457453
}
458454
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
459455
// Max has reached. Delete the shortcut with lowest rank.
460-
461456
// Sort by isManifestShortcut() and getRank().
462457
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
463458

@@ -473,7 +468,8 @@ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut,
473468
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
474469
/*ignorePersistedShortcuts=*/ true) != null;
475470
}
476-
} else {
471+
}
472+
if (oldShortcut != null) {
477473
// It's an update case.
478474
// Make sure the target is updatable. (i.e. should be mutable.)
479475
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@ public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut,
505501
return deleted;
506502
}
507503

504+
private void ensureShortcutCountBeforePush() {
505+
final ShortcutService service = mShortcutUser.mService;
506+
// Ensure the total number of shortcuts doesn't exceed the hard limit per app.
507+
final int maxShortcutPerApp = service.getMaxAppShortcuts();
508+
synchronized (mLock) {
509+
final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
510+
!si.isPinned()).collect(Collectors.toList());
511+
if (appShortcuts.size() >= maxShortcutPerApp) {
512+
// Max has reached. Removes shortcuts until they fall within the hard cap.
513+
// Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
514+
Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
515+
516+
while (appShortcuts.size() >= maxShortcutPerApp) {
517+
final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
518+
if (shortcut.isDeclaredInManifest()) {
519+
// All shortcuts are manifest shortcuts and cannot be removed.
520+
throw new IllegalArgumentException(getPackageName() + " has published "
521+
+ appShortcuts.size() + " manifest shortcuts across different"
522+
+ " activities.");
523+
}
524+
forceDeleteShortcutInner(shortcut.getId());
525+
}
526+
}
527+
}
528+
}
529+
508530
/**
509531
* Remove all shortcuts that aren't pinned, cached nor dynamic.
510532
*
@@ -1366,6 +1388,61 @@ private boolean pushOutExcessShortcuts() {
13661388
return Integer.compare(a.getRank(), b.getRank());
13671389
};
13681390

1391+
/**
1392+
* To sort by isManifestShortcut(), isDynamic(), getRank() and
1393+
* getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
1394+
* dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
1395+
*
1396+
* This is used to decide which shortcuts to remove when the total number of shortcuts retained
1397+
* for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
1398+
*
1399+
* (Note the number of manifest shortcuts is always <= the max number, because if there are
1400+
* more, ShortcutParser would ignore the rest.)
1401+
*/
1402+
final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
1403+
ShortcutInfo b) -> {
1404+
if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
1405+
return -1;
1406+
}
1407+
if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
1408+
return 1;
1409+
}
1410+
if (a.isDynamic() && b.isDynamic()) {
1411+
return Integer.compare(a.getRank(), b.getRank());
1412+
}
1413+
if (a.isDynamic()) {
1414+
return -1;
1415+
}
1416+
if (b.isDynamic()) {
1417+
return 1;
1418+
}
1419+
if (a.isCached() && b.isCached()) {
1420+
// if both shortcuts are cached, prioritize shortcuts cached by people tile,
1421+
if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
1422+
&& !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
1423+
return -1;
1424+
} else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
1425+
&& b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
1426+
return 1;
1427+
}
1428+
// followed by bubbles.
1429+
if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
1430+
&& !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
1431+
return -1;
1432+
} else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
1433+
&& b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
1434+
return 1;
1435+
}
1436+
}
1437+
if (a.isCached()) {
1438+
return -1;
1439+
}
1440+
if (b.isCached()) {
1441+
return 1;
1442+
}
1443+
return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
1444+
};
1445+
13691446
/**
13701447
* Build a list of shortcuts for each target activity and return as a map. The result won't
13711448
* contain "floating" shortcuts because they don't belong on any activities.

0 commit comments

Comments
 (0)