From 81c9e23734a1bd4d0f4a4bd5986bfb97e59bba7e Mon Sep 17 00:00:00 2001 From: Piyush Mehrotra Date: Thu, 27 Jul 2023 19:35:14 +0000 Subject: [DO NOT MERGE] Check caller's uid in backupAgentCreated callback AM.backupAgentCreated() should enforce that caller belongs the package called in the API. Bug: 289549315 Test: atest android.security.cts.ActivityManagerTest#testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:859abb58cdc7d66dbd22e7d02994509c4bba0416) Merged-In: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d Change-Id: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d --- .../android/server/am/ActivityManagerService.java | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 476e1b4ef11e..8089dcfe7ebc 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3074,6 +3074,22 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Enforces that the uid of the caller matches the uid of the package. + * + * @param packageName the name of the package to match uid against. + * @param callingUid the uid of the caller. + * @throws SecurityException if the calling uid doesn't match uid of the package. + */ + private void enforceCallingPackage(String packageName, int callingUid) { + final int userId = UserHandle.getUserId(callingUid); + final int packageUid = getPackageManagerInternal().getPackageUid(packageName, + /*flags=*/ 0, userId); + if (packageUid != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } + @Override public void setPackageScreenCompatMode(String packageName, int mode) { mActivityTaskManager.setPackageScreenCompatMode(packageName, mode); @@ -13618,13 +13634,16 @@ public class ActivityManagerService extends IActivityManager.Stub // A backup agent has just come up @Override public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) { + final int callingUid = Binder.getCallingUid(); + enforceCallingPackage(agentPackageName, callingUid); + // Resolve the target user id and enforce permissions. - userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null); if (DEBUG_BACKUP) { Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent + " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId - + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid()); + + " callingUid = " + callingUid + " uid = " + Process.myUid()); } synchronized(this) { -- cgit v1.2.3 From da91003502e40c96e769a6076a6a7c4ad4a27f23 Mon Sep 17 00:00:00 2001 From: kumarashishg Date: Thu, 3 Aug 2023 12:01:29 +0000 Subject: Use type safe API of readParcelableArray Bug: 291299076 Test: Build and flash the device and check if it throws exception for non UsbInterface object Test: atest CtsUsbManagerTestCases (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2c9931533cf8f85de9feb1db0b9ad38b8837f3b8) Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 --- core/java/android/hardware/usb/UsbConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java index 66269cb772f8..b25f47b11532 100644 --- a/core/java/android/hardware/usb/UsbConfiguration.java +++ b/core/java/android/hardware/usb/UsbConfiguration.java @@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable { String name = in.readString(); int attributes = in.readInt(); int maxPower = in.readInt(); - Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader()); + Parcelable[] interfaces = in.readParcelableArray( + UsbInterface.class.getClassLoader(), UsbInterface.class); UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower); configuration.setInterfaces(interfaces); return configuration; -- cgit v1.2.3 From b63dfe98ae9160a706c663190aae5355409b4fac Mon Sep 17 00:00:00 2001 From: Nan Wu Date: Fri, 16 Jun 2023 14:42:24 +0000 Subject: Fix BAL via notification.publicVersion We stripped the token that allows app to retrieve their own notification and fire their own PI to launch activities from background. But we forgot to strip the token from notification.publicVersion Bug: 278558814 Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e79cbff7f85ea5497dcdb27b13535e4e3ac9913f) Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98 Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98 --- core/java/android/app/Notification.java | 7 +++++-- .../android/server/notification/NotificationManagerService.java | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 11dd30b82e78..54c8cb09d7ea 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3485,8 +3485,11 @@ public class Notification implements Parcelable * * @hide */ - public void setAllowlistToken(@Nullable IBinder token) { - mAllowlistToken = token; + public void clearAllowlistToken() { + mAllowlistToken = null; + if (publicVersion != null) { + publicVersion.clearAllowlistToken(); + } } /** diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 79559fdc34d6..647087de1c04 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -4444,7 +4444,7 @@ public class NotificationManagerService extends SystemService { // Remove background token before returning notification to untrusted app, this // ensures the app isn't able to perform background operations that are // associated with notification interactions. - notification.setAllowlistToken(null); + notification.clearAllowlistToken(); return new StatusBarNotification( sbn.getPackageName(), sbn.getOpPkg(), -- cgit v1.2.3 From 6bc31b2a95679f00f57ccb27cd385673c912ba6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Budnik?= Date: Wed, 16 Aug 2023 16:32:55 +0000 Subject: Prevent media button receivers targeting activities This enforcement prevents a bypass of background activity launches. For Android U, the enforcement just ignores the request and logs a warning. This change is a backport of ag/23810567. Test: Manually. Bug: 272737196 Bug: 272024837 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d455e21711c167223f7d0696809a4e411683182c) Merged-In: I2412633c0b3afda6776244c72043d0dd78a4c8a1 Change-Id: I2412633c0b3afda6776244c72043d0dd78a4c8a1 --- media/java/android/media/session/MediaSession.java | 23 +++++++++++++--------- .../android/server/media/MediaSessionRecord.java | 8 ++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 29e8716f08ac..6121b8837f4f 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -267,17 +267,22 @@ public final class MediaSession { } /** - * Set a pending intent for your media button receiver to allow restarting - * playback after the session has been stopped. If your app is started in - * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via - * the pending intent. - *

- * The pending intent is recommended to be explicit to follow the security recommendation of - * {@link PendingIntent#getActivity}. + * Set a pending intent for your media button receiver to allow restarting playback after the + * session has been stopped. + * + *

If your app is started in this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be + * sent via the pending intent. + * + *

The provided {@link PendingIntent} must not target an activity. Passing an activity + * pending intent will cause the call to be ignored. Refer to this guide + * for more information. + * + *

The pending intent is recommended to be explicit to follow the security recommendation of + * {@link PendingIntent#getService}. * * @param mbr The {@link PendingIntent} to send the media button event to. * @see PendingIntent#getActivity - * * @deprecated Use {@link #setMediaButtonBroadcastReceiver(ComponentName)} instead. */ @Deprecated @@ -285,7 +290,7 @@ public final class MediaSession { try { mBinder.setMediaButtonReceiver(mbr); } catch (RemoteException e) { - Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e); + e.rethrowFromSystemServer(); } } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 9185a00da570..4084462d3f28 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -1062,6 +1062,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR != 0) { return; } + + if (pi != null && pi.isActivity()) { + Log.w( + TAG, + "Ignoring invalid media button receiver targeting an activity: " + pi); + return; + } + mMediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mUserId, pi, mPackageName); mService.onMediaButtonReceiverChanged(MediaSessionRecord.this); -- cgit v1.2.3 From 8dbb7c389069202b021e2b1ce751529f89baa30c Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Mon, 14 Aug 2023 15:24:11 -0700 Subject: [SettingsProvider] verify ringtone URI before setting Similar to ag/24422287, but the same URI verification should be done in SettingsProvider as well, which can be called by apps via Settings.System API or ContentProvider APIs without using RingtoneManager. BUG: 227201030 Test: manual with a test app. Will add a CTS test. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed) Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b --- .../providers/settings/SettingsProvider.java | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index f60f8db5e773..765edd72cfbd 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1948,6 +1948,9 @@ public class SettingsProvider extends ContentProvider { cacheName = Settings.System.ALARM_ALERT_CACHE; } if (cacheName != null) { + if (!isValidAudioUri(name, value)) { + return false; + } final File cacheFile = new File( getRingtoneCacheDir(owningUserId), cacheName); cacheFile.delete(); @@ -1980,6 +1983,34 @@ public class SettingsProvider extends ContentProvider { } } + private boolean isValidAudioUri(String name, String uri) { + if (uri != null) { + Uri audioUri = Uri.parse(uri); + if (Settings.AUTHORITY.equals( + ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) { + // Don't accept setting the default uri to self-referential URIs like + // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this + // setting. + return false; + } + final String mimeType = getContext().getContentResolver().getType(audioUri); + if (mimeType == null) { + Slog.e(LOG_TAG, + "mutateSystemSetting for setting: " + name + " URI: " + audioUri + + " ignored: failure to find mimeType (no access from this context?)"); + return false; + } + if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg") + || mimeType.equals("application/x-flac"))) { + Slog.e(LOG_TAG, + "mutateSystemSetting for setting: " + name + " URI: " + audioUri + + " ignored: associated mimeType: " + mimeType + " is not an audio type"); + return false; + } + } + return true; + } + private boolean hasWriteSecureSettingsPermission() { // Write secure settings is a more protected permission. If caller has it we are good. return getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) -- cgit v1.2.3 From 8904b5361cff9ebd2f5641e61211112580a07a33 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Fri, 28 Jul 2023 22:48:08 +0000 Subject: Fixes update ownership preapproval flow This change sets the package name when computing commit preapproval reason. Previously, with the package name unavailable that path would not be able to look up the existing package and so wouldn't know the owner. Additionally, if the installer required user action, the wrong dialog would have been displayed when the update ownership dialog should have been. This fixes both issues. Add new change id to check whether the build includes the fix or not. If the change is disabled, it means the build includes the fix. If the build doesn't include the change id, when the caller checks the change, it is enabled. Bug: 293644536 Test: atest PreapprovalInstallTest UpdateOwnershipEnforcementTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:917f02221653e456d83bf58cdfd7f86a54789909) Merged-In: I210fe1bb13a2096eb7e087806298ed1d4fa4905d Change-Id: I210fe1bb13a2096eb7e087806298ed1d4fa4905d --- .../android/server/pm/PackageInstallerSession.java | 39 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index f0e38955f050..d662aaedb774 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -67,6 +67,7 @@ import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.Context; @@ -310,6 +311,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) private static final long SILENT_INSTALL_ALLOWED = 265131695L; + /** + * The system supports pre-approval and update ownership features from + * {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE API 34}. The change id is used to make sure + * the system includes the fix of pre-approval with update ownership case. When checking the + * change id, if it is disabled, it means the build includes the fix. The more detail is on + * b/293644536. + * See {@link PackageInstaller.SessionParams#setRequestUpdateOwnership(boolean)} and + * {@link #requestUserPreapproval(PreapprovalDetails, IntentSender)} for more details. + */ + @Disabled + @ChangeId + private static final long PRE_APPROVAL_WITH_UPDATE_OWNERSHIP_FIX = 293644536L; + /** * The default value of {@link #mValidatedTargetSdk} is {@link Integer#MAX_VALUE}. If {@link * #mValidatedTargetSdk} is compared with {@link Build.VERSION_CODES#S} before getting the @@ -893,16 +907,27 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (mPermissionsManuallyAccepted) { return USER_ACTION_NOT_NEEDED; } - packageName = mPackageName; + // For pre-pappvoal case, the mPackageName would be null. + if (mPackageName != null) { + packageName = mPackageName; + } else if (mPreapprovalRequested.get() && mPreapprovalDetails != null) { + packageName = mPreapprovalDetails.getPackageName(); + } else { + packageName = null; + } hasDeviceAdminReceiver = mHasDeviceAdminReceiver; } - final boolean forcePermissionPrompt = + // For the below cases, force user action prompt + // 1. installFlags includes INSTALL_FORCE_PERMISSION_PROMPT + // 2. params.requireUserAction is USER_ACTION_REQUIRED + final boolean forceUserActionPrompt = (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0 || params.requireUserAction == SessionParams.USER_ACTION_REQUIRED; - if (forcePermissionPrompt) { - return USER_ACTION_REQUIRED; - } + final int userActionNotTypicallyNeededResponse = forceUserActionPrompt + ? USER_ACTION_REQUIRED + : USER_ACTION_NOT_NEEDED; + // It is safe to access mInstallerUid and mInstallSource without lock // because they are immutable after sealing. final Computer snapshot = mPm.snapshotComputer(); @@ -956,7 +981,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { || isInstallerDeviceOwnerOrAffiliatedProfileOwner(); if (noUserActionNecessary) { - return USER_ACTION_NOT_NEEDED; + return userActionNotTypicallyNeededResponse; } if (isUpdateOwnershipEnforcementEnabled @@ -969,7 +994,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (isPermissionGranted) { - return USER_ACTION_NOT_NEEDED; + return userActionNotTypicallyNeededResponse; } if (snapshot.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, -- cgit v1.2.3 From ccf047772b46f8478a8f429bb94d0769967e4140 Mon Sep 17 00:00:00 2001 From: Justin Ghan Date: Fri, 18 Aug 2023 20:18:41 +0000 Subject: Update autoHandwritingEnabled documentation Since we are changing the default value to false in UDC QPR1, remove the default value specification from the documentation. Bug: 296586357 Test: N/A (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8ee1665bcfe83c9481ccf867742853e846f2e332) Merged-In: Iad6e5b858503617b4a38045fbf32984c0d03619a Change-Id: Iad6e5b858503617b4a38045fbf32984c0d03619a --- core/res/res/values/attrs.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 6f7bc53e891c..fb27df15048d 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3537,11 +3537,11 @@ + See {@link android.view.View#setAutoHandwritingEnabled}. +

The default value of this flag is configurable by the device manufacturer. --> true + + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 2d040bb66d83..2425d367e1db 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -5132,4 +5132,7 @@ + + + diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 1a06b0184bc5..18474e0af5b8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -469,6 +469,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, */ private final int mDreamOpenAnimationDuration; + /** + * Whether unlock and wake should be sequenced. + */ + private final boolean mOrderUnlockAndWake; + /** * The animation used for hiding keyguard. This is used to fetch the animation timings if * WindowManager is not providing us with them. @@ -1434,6 +1439,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mMainDispatcher = mainDispatcher; mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel; + + mOrderUnlockAndWake = context.getResources().getBoolean( + com.android.internal.R.bool.config_orderUnlockAndWake); } public void userActivity() { @@ -2781,6 +2789,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private void setUnlockAndWakeFromDream(boolean updatedValue, @WakeAndUnlockUpdateReason int reason) { + if (!mOrderUnlockAndWake) { + return; + } + if (updatedValue == mUnlockingAndWakingFromDream) { return; } @@ -2863,6 +2875,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, null /* nonApps */, null /* finishedCallback */); }); } + + // It's possible that the device was unlocked (via BOUNCER or Fingerprint) while + // dreaming. It's time to wake up. + if (mDreamOverlayShowing && !mOrderUnlockAndWake) { + mPM.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui:UNLOCK_DREAMING"); + } } Trace.endSection(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index ed11711f66c6..a0b72fa208e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -173,6 +173,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final VibratorHelper mVibratorHelper; private final BiometricUnlockLogger mLogger; private final SystemClock mSystemClock; + private final boolean mOrderUnlockAndWake; private long mLastFpFailureUptimeMillis; private int mNumConsecutiveFpFailures; @@ -308,6 +309,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mVibratorHelper = vibrator; mLogger = biometricUnlockLogger; mSystemClock = systemClock; + mOrderUnlockAndWake = resources.getBoolean( + com.android.internal.R.bool.config_orderUnlockAndWake); dumpManager.registerDumpable(getClass().getName(), this); } @@ -462,10 +465,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp Trace.endSection(); }; - final boolean wakingFromDream = mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM - && mPowerManager.isInteractive(); + final boolean wakeInKeyguard = mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM + && mPowerManager.isInteractive() && mOrderUnlockAndWake + && mOrderUnlockAndWake; - if (mMode != MODE_NONE && !wakingFromDream) { + if (mMode != MODE_NONE && !wakeInKeyguard) { wakeUp.run(); } switch (mMode) { @@ -501,7 +505,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp // later to awaken. } mNotificationShadeWindowController.setNotificationShadeFocusable(false); - mKeyguardViewMediator.onWakeAndUnlocking(wakingFromDream); + mKeyguardViewMediator.onWakeAndUnlocking(wakeInKeyguard); Trace.endSection(); break; case MODE_ONLY_WAKE: diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 34ea91b94414..1c8241433172 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -602,6 +602,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @Test public void testWakeAndUnlockingOverDream() { + // Ensure ordering unlock and wake is enabled. + createAndStartViewMediator(true); + // Send signal to wake mViewMediator.onWakeAndUnlocking(true); @@ -631,6 +634,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @Test public void testWakeAndUnlockingOverDream_signalAuthenticateIfStillShowing() { + // Ensure ordering unlock and wake is enabled. + createAndStartViewMediator(true); + // Send signal to wake mViewMediator.onWakeAndUnlocking(true); @@ -787,6 +793,15 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } private void createAndStartViewMediator() { + createAndStartViewMediator(false); + } + + private void createAndStartViewMediator(boolean orderUnlockAndWake) { + if (orderUnlockAndWake) { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_orderUnlockAndWake, orderUnlockAndWake); + } + mViewMediator = new KeyguardViewMediator( mContext, mUiEventLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 7acf398955fb..2131f9d55ca8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -124,7 +124,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - TestableResources res = getContext().getOrCreateTestableResources(); + when(mKeyguardStateController.isShowing()).thenReturn(true); when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true); when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true); @@ -134,7 +134,15 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { when(mAuthController.isUdfpsFingerDown()).thenReturn(false); when(mVibratorHelper.hasVibrator()).thenReturn(true); mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager); - mBiometricUnlockController = new BiometricUnlockController(mDozeScrimController, + mBiometricUnlockController = createController(false); + when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker); + } + + BiometricUnlockController createController(boolean orderUnlockAndWake) { + TestableResources res = getContext().getOrCreateTestableResources(); + res.addOverride(com.android.internal.R.bool.config_orderUnlockAndWake, orderUnlockAndWake); + BiometricUnlockController biometricUnlockController = new BiometricUnlockController( + mDozeScrimController, mKeyguardViewMediator, mNotificationShadeWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController, @@ -144,9 +152,10 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper, mSystemClock ); - mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); - mBiometricUnlockController.addListener(mBiometricUnlockEventsListener); - when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker); + biometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); + biometricUnlockController.addListener(mBiometricUnlockEventsListener); + + return biometricUnlockController; } @Test @@ -549,6 +558,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test public void onSideFingerprintSuccess_dreaming_unlockNoWake() { + mBiometricUnlockController = createController(true); when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true); when(mWakefulnessLifecycle.getLastWakeReason()) .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON); -- cgit v1.2.3 From f8d5e3701589c2c9fa37a0d60c8be8dec92f8846 Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Wed, 12 Jul 2023 20:09:41 -0400 Subject: Fix back gesture / keycode for the PlatLogoActivity By overriding onKeyUp on the Activity itself, without calling super, I broke legacy back handling. Fortunately, there is now a better way to handle back! (Also fix the theme to avoid wallpaper showing through display cutout insets.) Test: adb shell input keyevent --longpress KEYCODE_BACK Test: swipe from edge Fixes: 289648693 Fixes: 290989795 (cherry picked from commit 5bbab52e0062877e17579bec48031f06ded79963) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:eeacd7d3f11f204057da54a8229eab3b18a08a93) Merged-In: I4fd4975421d204f06dbd8acda1a0d2a5a99f3465 Change-Id: I4fd4975421d204f06dbd8acda1a0d2a5a99f3465 --- core/res/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 2f9f6ae3f3c4..4dbc54fa2481 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -7752,8 +7752,9 @@ android:process=":ui"> -- cgit v1.2.3 From 562084ac0a60e5777f2b29cb7e8e463d9b1b88b9 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 18 Aug 2023 12:14:55 +0200 Subject: AudioDeviceBroker: restore use of hearing aids by default for VoIP calls Remove the target SDK gating policy for the selection of hearing aids during VoIP calls: this could break legacy apps that did not adopt new APIs to manage hearing aids. Bug: 295220577 Test: Meets, Skype, Zoom and Celluar calls with hearing aids. (cherry picked from commit 97014effc039f44910f86a1151a3af375c944926) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6db4ead48e50356918e28594b13c31defdf009a1) Merged-In: I9e4abfe6d22ac48f50bdec362597a028359dcc9f Change-Id: I9e4abfe6d22ac48f50bdec362597a028359dcc9f --- .../android/server/audio/AudioDeviceBroker.java | 32 ++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 29a19417b8fd..32c033230a16 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -2305,27 +2305,37 @@ import java.util.concurrent.atomic.AtomicBoolean; } @GuardedBy("mDeviceStateLock") - private boolean communnicationDeviceCompatOn() { + // LE Audio: For system server (Telecom) and APKs targeting S and above, we let the audio + // policy routing rules select the default communication device. + // For older APKs, we force LE Audio headset when connected as those APKs cannot select a LE + // Audiodevice explicitly. + private boolean communnicationDeviceLeAudioCompatOn() { return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION && !(CompatChanges.isChangeEnabled( USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid) || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); } + @GuardedBy("mDeviceStateLock") + // Hearing Aid: For system server (Telecom) and IN_CALL mode we let the audio + // policy routing rules select the default communication device. + // For 3p apps and IN_COMMUNICATION mode we force Hearing aid when connected to maintain + // backwards compatibility + private boolean communnicationDeviceHaCompatOn() { + return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION + && !(mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); + } + @GuardedBy("mDeviceStateLock") AudioDeviceAttributes getDefaultCommunicationDevice() { - // For system server (Telecom) and APKs targeting S and above, we let the audio - // policy routing rules select the default communication device. - // For older APKs, we force Hearing Aid or LE Audio headset when connected as - // those APKs cannot select a LE Audio or Hearing Aid device explicitly. AudioDeviceAttributes device = null; - if (communnicationDeviceCompatOn()) { - // If both LE and Hearing Aid are active (thie should not happen), - // priority to Hearing Aid. + // If both LE and Hearing Aid are active (thie should not happen), + // priority to Hearing Aid. + if (communnicationDeviceHaCompatOn()) { device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID); - if (device == null) { - device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); - } + } + if (device == null && communnicationDeviceLeAudioCompatOn()) { + device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); } return device; } -- cgit v1.2.3 From d45fe1600110fd3653196483fed77b828daa3cf0 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Fri, 11 Aug 2023 19:49:05 +0000 Subject: Unregister mShowWeatherObserver when KeyguardClockSwitchController is detached Bug: 295143740 Bug: 293929945 Test: Manually checked codepath with secondary display (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dea88a049ba8eabe381b5a5318dd77b5aa1d186f) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c9c3e0f81a9c3037d06c7ffa8c66d08d74f0cf40) Merged-In: I8807d1d58b58f1e5c990c21cef6a810e8b13c1db Change-Id: I8807d1d58b58f1e5c990c21cef6a810e8b13c1db --- .../SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index a0261309d61a..70849b7e2acf 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -266,6 +266,7 @@ public class KeyguardClockSwitchController extends ViewController Date: Thu, 13 Jul 2023 16:59:29 +0200 Subject: Restore trimMemory behaviour from T When we moved trimming code to ResourceTrimmer in I84637049a106a94bf9f06c5261c2941b55db4ba0, we also moved trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) which happens after unlock from StatusBarKeyguardViewManager to the ResourceTrimmer behind a TRIM_FONT_CACHES_AT_UNLOCK flag. Now that we've disabled TRIM_FONT_CACHES_AT_UNLOCK, this also disabled the trimMemory call we were doing since way before Android U. To full restore pre-U trim font behaviour, this call should not be flag guarded behind the font caching flag. Bug: 275486055 Bug: 290898642 Bug: 293929945 Test: Updated unit tests (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4bc215c4101b9504c244356ad0264ea1f4912bbd) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:16a1cf9e654bcaf3618213df7b9e82db3bdb5d40) Merged-In: I677855fff144a53d212b65575111491c78803817 Change-Id: I677855fff144a53d212b65575111491c78803817 --- .../android/systemui/keyguard/ResourceTrimmer.kt | 54 ++++++++++------------ .../systemui/keyguard/ResourceTrimmerTest.kt | 6 ++- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt index 1978b3d048b7..039460d8fdae 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt @@ -61,28 +61,23 @@ constructor( override fun start() { Log.d(LOG_TAG, "Resource trimmer registered.") - if ( - !(featureFlags.isEnabled(Flags.TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK) || - featureFlags.isEnabled(Flags.TRIM_FONT_CACHES_AT_UNLOCK)) - ) { - return - } - - applicationScope.launch(bgDispatcher) { - // We need to wait for the AoD transition (and animation) to complete. - // This means we're waiting for isDreaming (== implies isDoze) and dozeAmount == 1f - // signal. This is to make sure we don't clear font caches during animation which - // would jank and leave stale data in memory. - val isDozingFully = - keyguardInteractor.dozeAmount.map { it == 1f }.distinctUntilChanged() - combine( - keyguardInteractor.wakefulnessModel.map { it.state }, - keyguardInteractor.isDreaming, - isDozingFully, - ::Triple - ) - .distinctUntilChanged() - .collect { onWakefulnessUpdated(it.first, it.second, it.third) } + if (featureFlags.isEnabled(Flags.TRIM_RESOURCES_WITH_BACKGROUND_TRIM_AT_LOCK)) { + applicationScope.launch(bgDispatcher) { + // We need to wait for the AoD transition (and animation) to complete. + // This means we're waiting for isDreaming (== implies isDoze) and dozeAmount == 1f + // signal. This is to make sure we don't clear font caches during animation which + // would jank and leave stale data in memory. + val isDozingFully = + keyguardInteractor.dozeAmount.map { it == 1f }.distinctUntilChanged() + combine( + keyguardInteractor.wakefulnessModel.map { it.state }, + keyguardInteractor.isDreaming, + isDozingFully, + ::Triple + ) + .distinctUntilChanged() + .collect { onWakefulnessUpdated(it.first, it.second, it.third) } + } } applicationScope.launch(bgDispatcher) { @@ -97,17 +92,16 @@ constructor( @WorkerThread private fun onKeyguardGone() { - if (!featureFlags.isEnabled(Flags.TRIM_FONT_CACHES_AT_UNLOCK)) { - return - } - - if (DEBUG) { - Log.d(LOG_TAG, "Trimming font caches since keyguard went away.") - } // We want to clear temporary caches we've created while rendering and animating // lockscreen elements, especially clocks. + Log.d(LOG_TAG, "Sending TRIM_MEMORY_UI_HIDDEN.") globalWindowManager.trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) - globalWindowManager.trimCaches(HardwareRenderer.CACHE_TRIM_FONT) + if (featureFlags.isEnabled(Flags.TRIM_FONT_CACHES_AT_UNLOCK)) { + if (DEBUG) { + Log.d(LOG_TAG, "Trimming font caches since keyguard went away.") + } + globalWindowManager.trimCaches(HardwareRenderer.CACHE_TRIM_FONT) + } } @WorkerThread diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt index 644736899b6c..c175ec3a96ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt @@ -18,6 +18,7 @@ import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.WakeSleepReason import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.keyguard.shared.model.WakefulnessState +import com.android.systemui.util.mockito.any import com.android.systemui.utils.GlobalWindowManager import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope @@ -227,6 +228,9 @@ class ResourceTrimmerTest : SysuiTestCase() { keyguardTransitionRepository.sendTransitionStep( TransitionStep(KeyguardState.LOCKSCREEN, KeyguardState.GONE) ) - verifyNoMoreInteractions(globalWindowManager) + // Memory hidden should still be called. + verify(globalWindowManager, times(1)) + .trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) + verify(globalWindowManager, times(0)).trimCaches(any()) } } -- cgit v1.2.3 From 50d69832b421413adea107d412a533f111bd62b9 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Mon, 14 Aug 2023 19:44:12 +0800 Subject: Do not register OnBackInvokedCallback for SoftInputWindow. By default Dialog#onStart will register onBackInvokedCallback, which should be necessary since InputMethodService will register CompatOnBackInvokedCallback for input method window. Bug: 294162707 Test: atest BackGestureInvokedTest Test: manual, launch Calendar then trigger back several times, verify the back gesture can close app normally. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:da6336c35396bbea2191cb0e6b4aa72272a8059a) Merged-In: Icacfef60666fba1522f9d0f4ddc47e74a4560a32 Change-Id: Icacfef60666fba1522f9d0f4ddc47e74a4560a32 --- core/java/android/app/Dialog.java | 15 ++++++++++++--- core/java/android/inputmethodservice/SoftInputWindow.java | 7 +++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 411d157fa927..0ffe44219788 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -454,12 +454,11 @@ public class Dialog implements DialogInterface, Window.Callback, */ protected void onStart() { if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true); - if (mContext != null + if (allowsRegisterDefaultOnBackInvokedCallback() && mContext != null && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { // Add onBackPressed as default back behavior. mDefaultBackCallback = this::onBackPressed; getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback); - mDefaultBackCallback = null; } } @@ -470,9 +469,18 @@ public class Dialog implements DialogInterface, Window.Callback, if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false); if (mDefaultBackCallback != null) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mDefaultBackCallback); + mDefaultBackCallback = null; } } + /** + * Whether this dialog allows to register the default onBackInvokedCallback. + * @hide + */ + protected boolean allowsRegisterDefaultOnBackInvokedCallback() { + return true; + } + private static final String DIALOG_SHOWING_TAG = "android:dialogShowing"; private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy"; @@ -697,7 +705,8 @@ public class Dialog implements DialogInterface, Window.Callback, if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) && event.isTracking() && !event.isCanceled() - && !WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { + && (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext) + || !allowsRegisterDefaultOnBackInvokedCallback())) { onBackPressed(); return true; } diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index 5704dac7a327..e4a09a651ae1 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -79,6 +79,13 @@ final class SoftInputWindow extends Dialog { @WindowState private int mWindowState = WindowState.TOKEN_PENDING; + @Override + protected boolean allowsRegisterDefaultOnBackInvokedCallback() { + // Do not register OnBackInvokedCallback from Dialog#onStart, InputMethodService will + // register CompatOnBackInvokedCallback for input method window. + return false; + } + /** * Set {@link IBinder} window token to the window. * -- cgit v1.2.3 From 79aabce061b0e661d3d9c1698f216966a97a574d Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Wed, 30 Aug 2023 17:07:44 -0700 Subject: Store trusted AttributionSources without token Storing them with token means that there is a strong reference to the token, preventing the WeakHashMap from properly purging values This CP also includes changeID I5731ceeab5b9d0c72ce0131e2c9ba2f74558218c Bug: 298253183 Test: manual (for WeakHashMap ejection) atest CtsAttributionSourceTestCases (cherry picked from commit ed57878c8e89d136264ed419590a0601bdfa18f6) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:c5127b478d0b1e72aa60783fcb4f1f1254d01075) Merged-In: Ie92b76ec83552cebb419318c214057f1ea8455d2 Change-Id: Ie92b76ec83552cebb419318c214057f1ea8455d2 --- core/java/android/content/AttributionSource.java | 31 +++++++++++++++++----- .../pm/permission/PermissionManagerService.java | 6 +++-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java index cd45f4df3d50..b4f4a7efad98 100644 --- a/core/java/android/content/AttributionSource.java +++ b/core/java/android/content/AttributionSource.java @@ -211,6 +211,11 @@ public final class AttributionSource implements Parcelable { token, mAttributionSourceState.renouncedPermissions, getNext()); } + /** @hide */ + public AttributionSource withDefaultToken() { + return withToken(sDefaultToken); + } + /** @hide */ public AttributionSource withPid(int pid) { return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(), @@ -520,16 +525,28 @@ public final class AttributionSource implements Parcelable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AttributionSource that = (AttributionSource) o; - return mAttributionSourceState.uid == that.mAttributionSourceState.uid + return equalsExceptToken(that) && Objects.equals( + mAttributionSourceState.token, that.mAttributionSourceState.token); + } + + /** + * We store trusted attribution sources without their token (the token is the key to the map) + * to avoid having a strong reference to the token. This means, when checking the equality of a + * supplied AttributionSource in PermissionManagerService.isTrustedAttributionSource, we want to + * compare everything except the token. + * + * @hide + */ + public boolean equalsExceptToken(@Nullable AttributionSource o) { + if (o == null) return false; + return mAttributionSourceState.uid == o.mAttributionSourceState.uid && Objects.equals(mAttributionSourceState.packageName, - that.mAttributionSourceState.packageName) + o.mAttributionSourceState.packageName) && Objects.equals(mAttributionSourceState.attributionTag, - that.mAttributionSourceState.attributionTag) - && Objects.equals(mAttributionSourceState.token, - that.mAttributionSourceState.token) + o.mAttributionSourceState.attributionTag) && Arrays.equals(mAttributionSourceState.renouncedPermissions, - that.mAttributionSourceState.renouncedPermissions) - && Objects.equals(getNext(), that.getNext()); + o.mAttributionSourceState.renouncedPermissions) + && Objects.equals(getNext(), o.getNext()); } @Override diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 297ad73e054b..c24d5236f4f7 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1001,7 +1001,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } synchronized (mLock) { - mAttributions.put(source.getToken(), source); + // Change the token for the AttributionSource we're storing, so that we don't store + // a strong reference to the original token inside the map itself. + mAttributions.put(source.getToken(), source.withDefaultToken()); } } @@ -1009,7 +1011,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { synchronized (mLock) { final AttributionSource cachedSource = mAttributions.get(source.getToken()); if (cachedSource != null) { - return cachedSource.equals(source); + return cachedSource.equalsExceptToken(source); } return false; } -- cgit v1.2.3 From 17fc586c25143984f6642ea8f25dd2e2d86a5e05 Mon Sep 17 00:00:00 2001 From: Felix Oghina Date: Wed, 15 Feb 2023 15:32:51 +0000 Subject: Fix NPE in TTS service if no engine string Test: added test in TextToSpeechServiceTest Bug: 232438498 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e5364f93d3208a66d599d7256d2e4cfaba989e0e) Merged-In: Ia587d34e2898930c0956024c56a1f19debb445e4 Change-Id: Ia587d34e2898930c0956024c56a1f19debb445e4 --- .../com/android/server/texttospeech/TextToSpeechManagerService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java index 9015563f439e..24114988d6ba 100644 --- a/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java +++ b/services/texttospeech/java/com/android/server/texttospeech/TextToSpeechManagerService.java @@ -63,6 +63,12 @@ public final class TextToSpeechManagerService extends public void createSession(String engine, ITextToSpeechSessionCallback sessionCallback) { synchronized (mLock) { + if (engine == null) { + runSessionCallbackMethod( + () -> sessionCallback.onError("Engine cannot be null")); + return; + } + TextToSpeechManagerPerUserService perUserService = getServiceForUserLocked( UserHandle.getCallingUserId()); if (perUserService != null) { -- cgit v1.2.3