Merge cherrypicks of ['googleplex-android-review.googlesource.com/30800649', 'googleplex-android-review.googlesource.com/30814870', 'googleplex-android-review.googlesource.com/31215755', 'googleplex-android-review.googlesource.com/30961573', 'googleplex-android-review.googlesource.com/31236504', 'googleplex-android-review.googlesource.com/31440406', 'googleplex-android-review.googlesource.com/31488916', 'googleplex-android-review.googlesource.com/31418596'] into 25Q1-release.
Change-Id: Ia51f979c418f7df5e3fc6b5bf5780ced1befffeb
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 5012127..e2315d5 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -475,10 +475,10 @@
map.erase();
map.ensureCapacity(count);
}
- int numLazyValues = 0;
+ int[] numLazyValues = new int[]{0};
try {
- numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
- /* lazy */ ownsParcel, mClassLoader);
+ parcelledData.readArrayMap(map, count, !parcelledByNative,
+ /* lazy */ ownsParcel, mClassLoader, numLazyValues);
} catch (BadParcelableException e) {
if (sShouldDefuse) {
Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -489,14 +489,14 @@
} finally {
mWeakParcelledData = null;
if (ownsParcel) {
- if (numLazyValues == 0) {
+ if (numLazyValues[0] == 0) {
recycleParcel(parcelledData);
} else {
mWeakParcelledData = new WeakReference<>(parcelledData);
}
}
- mLazyValues = numLazyValues;
+ mLazyValues = numLazyValues[0];
mParcelledByNative = false;
mMap = map;
// Set field last as it is volatile
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index cf473ec..26f768c 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -5538,7 +5538,7 @@
private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
int size, @Nullable ClassLoader loader) {
- readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
+ readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader, null);
}
/**
@@ -5548,17 +5548,16 @@
* @param lazy Whether to populate the map with lazy {@link Function} objects for
* length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
* details.
- * @return a count of the lazy values in the map
+ * @param lazyValueCount number of lazy values added here
* @hide
*/
- int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
- boolean lazy, @Nullable ClassLoader loader) {
- int lazyValues = 0;
+ void readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+ boolean lazy, @Nullable ClassLoader loader, int[] lazyValueCount) {
while (size > 0) {
String key = readString();
Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
if (value instanceof LazyValue) {
- lazyValues++;
+ lazyValueCount[0]++;
}
if (sorted) {
map.append(key, value);
@@ -5570,7 +5569,6 @@
if (sorted) {
map.validate();
}
- return lazyValues;
}
/**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index ca4d1b6..3bdf3d6 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
+import static android.content.ContentProvider.getUriWithoutUserId;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -40,7 +41,9 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.IUriGrantsManager;
import android.app.SharedElementCallback;
+import android.app.UriGrantsManager;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
@@ -77,6 +80,7 @@
import android.graphics.Path;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
@@ -86,6 +90,7 @@
import android.os.Message;
import android.os.Parcelable;
import android.os.PatternMatcher;
+import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
@@ -692,7 +697,11 @@
targets = null;
break;
}
- targets[i] = (ChooserTarget) pa[i];
+ ChooserTarget chooserTarget = (ChooserTarget) pa[i];
+ if (!hasValidIcon(chooserTarget)) {
+ chooserTarget = removeIcon(chooserTarget);
+ }
+ targets[i] = chooserTarget;
}
mCallerChooserTargets = targets;
}
@@ -4214,4 +4223,43 @@
private boolean shouldNearbyShareBeIncludedAsActionButton() {
return !shouldNearbyShareBeFirstInRankedRow();
}
+
+ private boolean hasValidIcon(ChooserTarget target) {
+ Icon icon = target.getIcon();
+ if (icon == null) {
+ return true;
+ }
+ if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+ Uri uri = icon.getUri();
+ try {
+ getUriGrantsManager().checkGrantUriPermission_ignoreNonSystem(
+ getLaunchedFromUid(),
+ getPackageName(),
+ getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ getUserIdFromUri(uri)
+ );
+ } catch (SecurityException | RemoteException e) {
+ Log.e(TAG, "Failed to get URI permission for: " + uri, e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private IUriGrantsManager getUriGrantsManager() {
+ return UriGrantsManager.getService();
+ }
+
+ private static ChooserTarget removeIcon(ChooserTarget target) {
+ if (target == null) {
+ return null;
+ }
+ return new ChooserTarget(
+ target.getTitle(),
+ null,
+ target.getScore(),
+ target.getComponentName(),
+ target.getIntentExtras());
+ }
}
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 644d699..d29ef38 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -599,24 +599,35 @@
Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
sanitizeIntent(forwardIntent);
- Intent intentToCheck = forwardIntent;
- if (Intent.ACTION_CHOOSER.equals(forwardIntent.getAction())) {
+ if (!canForwardInner(forwardIntent, sourceUserId, targetUserId, packageManager,
+ contentResolver)) {
return null;
}
if (forwardIntent.getSelector() != null) {
- intentToCheck = forwardIntent.getSelector();
+ sanitizeIntent(forwardIntent.getSelector());
+ if (!canForwardInner(forwardIntent.getSelector(), sourceUserId, targetUserId,
+ packageManager, contentResolver)) {
+ return null;
+ }
}
- String resolvedType = intentToCheck.resolveTypeIfNeeded(contentResolver);
- sanitizeIntent(intentToCheck);
+ return forwardIntent;
+ }
+
+ private static boolean canForwardInner(Intent intent, int sourceUserId, int targetUserId,
+ IPackageManager packageManager, ContentResolver contentResolver) {
+ if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
+ return false;
+ }
+ String resolvedType = intent.resolveTypeIfNeeded(contentResolver);
try {
if (packageManager.canForwardTo(
- intentToCheck, resolvedType, sourceUserId, targetUserId)) {
- return forwardIntent;
+ intent, resolvedType, sourceUserId, targetUserId)) {
+ return true;
}
} catch (RemoteException e) {
Slog.e(TAG, "PackageManagerService is dead?");
}
- return null;
+ return false;
}
/**
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 06c586f..82a51c3 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -603,7 +603,7 @@
}
}
- /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
+ /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */
private static final class PackageVerificationResult {
final RestrictionBypass bypass;
@@ -3086,10 +3086,10 @@
public int checkPackage(int uid, String packageName) {
Objects.requireNonNull(packageName);
try {
- verifyAndGetBypass(uid, packageName, null, null, true);
+ verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
// When the caller is the system, it's possible that the packageName is the special
// one (e.g., "root") which isn't actually existed.
- if (resolveUid(packageName) == uid
+ if (resolveNonAppUid(packageName) == uid
|| (isPackageExisted(packageName)
&& !filterAppAccessUnlocked(packageName, UserHandle.getUserId(uid)))) {
return AppOpsManager.MODE_ALLOWED;
@@ -3288,7 +3288,7 @@
boolean shouldCollectMessage) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -3875,7 +3875,7 @@
// Test if the proxied operation will succeed before starting the proxy operation
final SyncNotedAppOp testProxiedOp = startOperationDryRun(code,
proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag,
- proxiedVirtualDeviceId, resolvedProxyPackageName, proxiedFlags,
+ proxiedVirtualDeviceId, proxyUid, resolvedProxyPackageName, proxiedFlags,
startIfModeDefault);
if (!shouldStartForMode(testProxiedOp.getOpMode(), startIfModeDefault)) {
@@ -3915,7 +3915,7 @@
int attributionChainId) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -4042,11 +4042,11 @@
*/
private SyncNotedAppOp startOperationDryRun(int code, int uid,
@NonNull String packageName, @Nullable String attributionTag, int virtualDeviceId,
- String proxyPackageName, @OpFlags int flags,
+ int proxyUid, String proxyPackageName, @OpFlags int flags,
boolean startIfModeDefault) {
PackageVerificationResult pvr;
try {
- pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+ pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
if (!pvr.isAttributionTagValid) {
attributionTag = null;
}
@@ -4601,13 +4601,17 @@
private boolean isSpecialPackage(int callingUid, @Nullable String packageName) {
final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName);
return callingUid == Process.SYSTEM_UID
- || resolveUid(resolvedPackage) != Process.INVALID_UID;
+ || resolveNonAppUid(resolvedPackage) != Process.INVALID_UID;
}
private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) {
if (attributionSource.getUid() != Binder.getCallingUid()
&& attributionSource.isTrusted(mContext)) {
- return true;
+ // if there is a next attribution source, it must be trusted, as well.
+ if (attributionSource.getNext() == null
+ || attributionSource.getNext().isTrusted(mContext)) {
+ return true;
+ }
}
return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null)
@@ -4702,19 +4706,20 @@
}
/**
- * @see #verifyAndGetBypass(int, String, String, String, boolean)
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
@Nullable String attributionTag) {
- return verifyAndGetBypass(uid, packageName, attributionTag, null);
+ return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
}
/**
- * @see #verifyAndGetBypass(int, String, String, String, boolean)
+ * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
- @Nullable String attributionTag, @Nullable String proxyPackageName) {
- return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false);
+ @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
+ return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
+ false);
}
/**
@@ -4725,14 +4730,15 @@
* @param uid The uid the package belongs to
* @param packageName The package the might belong to the uid
* @param attributionTag attribution tag or {@code null} if no need to verify
- * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
+ * @param proxyUid The proxy uid, from which the attribution tag is to be pulled
+ * @param proxyPackageName The proxy package, from which the attribution tag may be pulled
* @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
*
* @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
* attribution tag is valid
*/
private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
- @Nullable String attributionTag, @Nullable String proxyPackageName,
+ @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
boolean suppressErrorLogs) {
if (uid == Process.ROOT_UID) {
// For backwards compatibility, don't check package name for root UID.
@@ -4776,34 +4782,47 @@
int callingUid = Binder.getCallingUid();
- // Allow any attribution tag for resolvable uids
- int pkgUid;
+ // Allow any attribution tag for resolvable, non-app uids
+ int nonAppUid;
if (Objects.equals(packageName, "com.android.shell")) {
// Special case for the shell which is a package but should be able
// to bypass app attribution tag restrictions.
- pkgUid = Process.SHELL_UID;
+ nonAppUid = Process.SHELL_UID;
} else {
- pkgUid = resolveUid(packageName);
+ nonAppUid = resolveNonAppUid(packageName);
}
- if (pkgUid != Process.INVALID_UID) {
- if (pkgUid != UserHandle.getAppId(uid)) {
+ if (nonAppUid != Process.INVALID_UID) {
+ if (nonAppUid != UserHandle.getAppId(uid)) {
if (!suppressErrorLogs) {
Slog.e(TAG, "Bad call made by uid " + callingUid + ". "
- + "Package \"" + packageName + "\" does not belong to uid " + uid
- + ".");
+ + "Package \"" + packageName + "\" does not belong to uid " + uid
+ + ".");
}
- String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
- throw new SecurityException("Specified package \"" + packageName + "\" under uid "
- + UserHandle.getAppId(uid) + otherUidMessage);
+ String otherUidMessage =
+ DEBUG ? " but it is really " + nonAppUid : " but it is not";
+ throw new SecurityException("Specified package \"" + packageName
+ + "\" under uid " + UserHandle.getAppId(uid) + otherUidMessage);
+ }
+ // We only allow bypassing the attribution tag verification if the proxy is a
+ // system app (or is null), in order to prevent abusive apps clogging the appops
+ // system with unlimited attribution tags via proxy calls.
+ boolean proxyIsSystemAppOrNull = true;
+ if (proxyPackageName != null) {
+ int proxyAppId = UserHandle.getAppId(proxyUid);
+ if (proxyAppId >= Process.FIRST_APPLICATION_UID) {
+ proxyIsSystemAppOrNull =
+ mPackageManagerInternal.isSystemPackage(proxyPackageName);
+ }
}
return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
- /* isAttributionTagValid */ true);
+ /* isAttributionTagValid */ proxyIsSystemAppOrNull);
}
int userId = UserHandle.getUserId(uid);
RestrictionBypass bypass = null;
boolean isAttributionTagValid = false;
+ int pkgUid = nonAppUid;
final long ident = Binder.clearCallingIdentity();
try {
PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
@@ -5594,7 +5613,7 @@
if (nonpackageUid != -1) {
packageName = null;
} else {
- packageUid = resolveUid(packageName);
+ packageUid = resolveNonAppUid(packageName);
if (packageUid < 0) {
packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -6694,7 +6713,13 @@
if (restricted && attrOp.isRunning()) {
attrOp.pause();
} else if (attrOp.isPaused()) {
- attrOp.resume();
+ RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag)
+ .bypass;
+ if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag,
+ Context.DEVICE_ID_DEFAULT, bypass, false)) {
+ // Only resume if there are no other restrictions remaining on this op
+ attrOp.resume();
+ }
}
}
}
@@ -7143,7 +7168,7 @@
}
}
- private static int resolveUid(String packageName) {
+ private static int resolveNonAppUid(String packageName) {
if (packageName == null) {
return Process.INVALID_UID;
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 93f512b..0bb3c6a 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -36,10 +36,7 @@
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.Person;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ShortcutInfo;
@@ -48,7 +45,6 @@
import android.media.AudioSystem;
import android.metrics.LogMaker;
import android.net.Uri;
-import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -1493,23 +1489,14 @@
final Notification notification = getNotification();
notification.visitUris((uri) -> {
- if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) {
- visitGrantableUri(uri, false, false);
- } else {
- oldVisitGrantableUri(uri, false, false);
- }
+ visitGrantableUri(uri, false, false);
});
if (notification.getChannelId() != null) {
NotificationChannel channel = getChannel();
if (channel != null) {
- if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) {
- visitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
- & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
- } else {
- oldVisitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
- & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
- }
+ visitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
+ & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
}
}
} finally {
@@ -1525,53 +1512,6 @@
* {@link #mGrantableUris}. Otherwise, this will either log or throw
* {@link SecurityException} depending on target SDK of enqueuing app.
*/
- private void oldVisitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) {
- if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
-
- if (mGrantableUris != null && mGrantableUris.contains(uri)) {
- return; // already verified this URI
- }
-
- final int sourceUid = getSbn().getUid();
- final long ident = Binder.clearCallingIdentity();
- try {
- // This will throw a SecurityException if the caller can't grant.
- mUgmInternal.checkGrantUriPermission(sourceUid, null,
- ContentProvider.getUriWithoutUserId(uri),
- Intent.FLAG_GRANT_READ_URI_PERMISSION,
- ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
-
- if (mGrantableUris == null) {
- mGrantableUris = new ArraySet<>();
- }
- mGrantableUris.add(uri);
- } catch (SecurityException e) {
- if (!userOverriddenUri) {
- if (isSound) {
- mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
- Log.w(TAG, "Replacing " + uri + " from " + sourceUid + ": " + e.getMessage());
- } else {
- if (mTargetSdkVersion >= Build.VERSION_CODES.P) {
- throw e;
- } else {
- Log.w(TAG,
- "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage());
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- /**
- * Note the presence of a {@link Uri} that should have permission granted to
- * whoever will be rendering it.
- * <p>
- * If the enqueuing app has the ability to grant access, it will be added to
- * {@link #mGrantableUris}. Otherwise, this will either log or throw
- * {@link SecurityException} depending on target SDK of enqueuing app.
- */
private void visitGrantableUri(Uri uri, boolean userOverriddenUri,
boolean isSound) {
if (mGrantableUris != null && mGrantableUris.contains(uri)) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 15377d6..f6acd6f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -1171,9 +1171,7 @@
// Verify that the app has permission to read the sound Uri
// Only check for new channels, as regular apps can only set sound
// before creating. See: {@link NotificationChannel#setSound}
- if (Flags.notificationVerifyChannelSoundUri()) {
- PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid);
- }
+ PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid);
channel.setImportanceLockedByCriticalDeviceFunction(
r.defaultAppLockedImportance || r.fixedImportance);
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index 65a38ae..76ebb47 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -172,16 +172,6 @@
}
flag {
- name: "notification_verify_channel_sound_uri"
- namespace: "systemui"
- description: "Verify Uri permission for sound when creating a notification channel"
- bug: "337775777"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "notification_vibration_in_sound_uri_for_channel"
namespace: "systemui"
description: "Enables sound uri with vibration source in notification channel"
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 2bc6d53..a108248 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -309,7 +309,8 @@
* in settings. So it is handled separately.
*/
private static final Set<String> DEFAULT_ENABLED_FOR_MANAGED_PROFILES = Sets.newArraySet(
- UserManager.DISALLOW_BLUETOOTH_SHARING
+ UserManager.DISALLOW_BLUETOOTH_SHARING,
+ UserManager.DISALLOW_DEBUGGING_FEATURES
);
/**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f1a4811..8052754 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3576,7 +3576,7 @@
}
break;
case KeyEvent.KEYCODE_I:
- if (firstDown && event.isMetaPressed()) {
+ if (firstDown && event.isMetaPressed() && isUserSetupComplete() && !keyguardOn) {
showSystemSettings();
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS);
@@ -4149,6 +4149,7 @@
int displayId = event.getDisplayId();
int modifierState = event.getModifierState();
boolean keyguardOn = keyguardOn();
+ boolean canLaunchApp = isUserSetupComplete() && !keyguardOn;
switch (gestureType) {
case KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS:
if (complete) {
@@ -4166,7 +4167,7 @@
return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT:
case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT:
- if (complete) {
+ if (complete && canLaunchApp) {
launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD,
deviceId, SystemClock.uptimeMillis(),
AssistUtils.INVOCATION_TYPE_UNKNOWN);
@@ -4179,7 +4180,7 @@
}
return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS:
- if (complete) {
+ if (complete && canLaunchApp) {
showSystemSettings();
}
return true;
@@ -4282,7 +4283,7 @@
}
return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH:
- if (complete) {
+ if (complete && canLaunchApp) {
launchTargetSearchActivity();
}
return true;
@@ -4363,8 +4364,8 @@
break;
case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION:
AppLaunchData data = event.getAppLaunchData();
- if (complete && isUserSetupComplete() && !keyguardOn
- && data != null && mModifierShortcutManager.launchApplication(data)) {
+ if (complete && canLaunchApp && data != null
+ && mModifierShortcutManager.launchApplication(data)) {
dismissKeyboardShortcutsMenu();
}
return true;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 1fc609b7..3e7fbf4 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1497,16 +1497,15 @@
}
// Update the input-sink (touch-blocking) state now that the animation is finished.
- SurfaceControl.Transaction inputSinkTransaction = null;
+ boolean scheduleAnimation = false;
for (int i = 0; i < mParticipants.size(); ++i) {
final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
if (ar == null || !ar.isVisible() || ar.getParent() == null) continue;
- if (inputSinkTransaction == null) {
- inputSinkTransaction = ar.mWmService.mTransactionFactory.get();
- }
- ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(inputSinkTransaction);
+ scheduleAnimation = true;
+ ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(ar.getPendingTransaction());
}
- if (inputSinkTransaction != null) inputSinkTransaction.apply();
+ // To apply pending transactions.
+ if (scheduleAnimation) mController.mAtm.mWindowManager.scheduleAnimationLocked();
// Always schedule stop processing when transition finishes because activities don't
// stop while they are in a transition thus their stop could still be pending.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2627895..62d6258 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2723,16 +2723,16 @@
}
}
- /**
- * Apply default restrictions that haven't been applied to a given admin yet.
- */
+ /** Apply default restrictions that haven't been applied to a given admin yet. */
private void maybeSetDefaultRestrictionsForAdminLocked(int userId, ActiveAdmin admin) {
- Set<String> defaultRestrictions =
- UserRestrictionsUtils.getDefaultEnabledForManagedProfiles();
- if (defaultRestrictions.equals(admin.defaultEnabledRestrictionsAlreadySet)) {
+ Set<String> newDefaultRestrictions = new HashSet(
+ UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
+ newDefaultRestrictions.removeAll(admin.defaultEnabledRestrictionsAlreadySet);
+ if (newDefaultRestrictions.isEmpty()) {
return; // The same set of default restrictions has been already applied.
}
- for (String restriction : defaultRestrictions) {
+
+ for (String restriction : newDefaultRestrictions) {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.getPolicyDefinitionForUserRestriction(restriction),
EnforcingAdmin.createEnterpriseEnforcingAdmin(
@@ -2740,10 +2740,9 @@
admin.getUserHandle().getIdentifier()),
new BooleanPolicyValue(true),
userId);
+ admin.defaultEnabledRestrictionsAlreadySet.add(restriction);
+ Slogf.i(LOG_TAG, "Enabled the following restriction by default: " + restriction);
}
- admin.defaultEnabledRestrictionsAlreadySet.addAll(defaultRestrictions);
- Slogf.i(LOG_TAG, "Enabled the following restrictions by default: "
- + defaultRestrictions);
}
private void maybeStartSecurityLogMonitorOnActivityManagerReady() {
@@ -10329,7 +10328,8 @@
return false;
}
- if (isAdb(caller)) {
+ boolean isAdb = isAdb(caller);
+ if (isAdb) {
// Log profile owner provisioning was started using adb.
MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_PROFILE_OWNER);
DevicePolicyEventLogger
@@ -10352,6 +10352,18 @@
ensureUnknownSourcesRestrictionForProfileOwnerLocked(userHandle, admin,
true /* newOwner */);
}
+ if(isAdb) {
+ // DISALLOW_DEBUGGING_FEATURES is being added to newly-created
+ // work profile by default due to b/382064697 . This would have
+ // impacted certain CTS test flows when they interact with the
+ // work profile via ADB (for example installing an app into the
+ // work profile). Remove DISALLOW_DEBUGGING_FEATURES here to
+ // reduce the potential impact.
+ setLocalUserRestrictionInternal(
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle),
+ UserManager.DISALLOW_DEBUGGING_FEATURES, false, userHandle);
+ }
+
sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
userHandle);
});
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index b015c8c..8975c8e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -66,7 +66,6 @@
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
-import static com.android.server.notification.Flags.FLAG_NOTIFICATION_VERIFY_CHANNEL_SOUND_URI;
import static com.android.server.notification.Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA;
import static com.android.server.notification.NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER;
import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE;
@@ -3190,7 +3189,6 @@
}
@Test
- @EnableFlags(FLAG_NOTIFICATION_VERIFY_CHANNEL_SOUND_URI)
public void testCreateChannel_noSoundUriPermission_contentSchemeVerified() {
final Uri sound = Uri.parse(SCHEME_CONTENT + "://media/test/sound/uri");
@@ -3210,7 +3208,6 @@
}
@Test
- @EnableFlags(FLAG_NOTIFICATION_VERIFY_CHANNEL_SOUND_URI)
public void testCreateChannel_noSoundUriPermission_fileSchemaIgnored() {
final Uri sound = Uri.parse(SCHEME_FILE + "://path/sound");
@@ -3229,7 +3226,6 @@
}
@Test
- @EnableFlags(FLAG_NOTIFICATION_VERIFY_CHANNEL_SOUND_URI)
public void testCreateChannel_noSoundUriPermission_resourceSchemaIgnored() {
final Uri sound = Uri.parse(SCHEME_ANDROID_RESOURCE + "://resId/sound");
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index 41865b20..6c8c826 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -808,4 +808,44 @@
sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS));
Assert.assertFalse(InputSettings.isAccessibilityBounceKeysEnabled(mContext));
}
+
+ @Test
+ public void testLaunchSettingsAndSearchDoesntOpenAnything_withKeyguardOn() {
+ mPhoneWindowManager.overrideKeyguardOn(true);
+
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS);
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH);
+
+ mPhoneWindowManager.assertNoActivityLaunched();
+ }
+
+ @Test
+ public void testLaunchSettingsAndSearchDoesntOpenAnything_withUserSetupIncomplete() {
+ mPhoneWindowManager.overrideIsUserSetupComplete(false);
+
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS);
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH);
+
+ mPhoneWindowManager.assertNoActivityLaunched();
+ }
+
+ @Test
+ public void testLaunchAssistantDoesntWork_withKeyguardOn() {
+ mPhoneWindowManager.overrideKeyguardOn(true);
+
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT);
+
+ mPhoneWindowManager.assertSearchManagerDoesntLaunchAssist();
+ }
+
+ @Test
+ public void testLaunchAssistantDoesntWork_withUserSetupIncomplete() {
+ mPhoneWindowManager.overrideIsUserSetupComplete(false);
+
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
+ sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT);
+
+ mPhoneWindowManager.assertSearchManagerDoesntLaunchAssist();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 9db76d4..8ea3a34 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -563,6 +563,10 @@
doNothing().when(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
}
+ void overrideKeyguardOn(boolean isKeyguardOn) {
+ doReturn(isKeyguardOn).when(mPhoneWindowManager).keyguardOn();
+ }
+
void overrideIsUserSetupComplete(boolean isCompleted) {
doReturn(isCompleted).when(mPhoneWindowManager).isUserSetupComplete();
}
@@ -725,6 +729,11 @@
verify(mSearchManager).launchAssist(any());
}
+ void assertSearchManagerDoesntLaunchAssist() {
+ mTestLooper.dispatchAll();
+ verify(mSearchManager, never()).launchAssist(any());
+ }
+
void assertLaunchSystemSettings() {
mTestLooper.dispatchAll();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -929,4 +938,10 @@
verify(mInputManagerInternal)
.handleKeyGestureInKeyGestureController(anyInt(), any(), anyInt(), eq(gestureType));
}
+
+ void assertNoActivityLaunched() {
+ mTestLooper.dispatchAll();
+ verify(mContext, never()).startActivityAsUser(any(), any(), any());
+ verify(mContext, never()).startActivityAsUser(any(), any());
+ }
}