From ba9e22dc771096536ac7a896d7387c430abe7d0f Mon Sep 17 00:00:00 2001 From: Tavi Date: Sun, 16 Jun 2024 15:55:36 -0400 Subject: [PATCH] Reconcile picks Signed-off-by: Tavi --- .../android_frameworks_base/394553.patch | 47 + .../android_frameworks_base/394554.patch | 46 + .../android_frameworks_base/394555.patch} | 32 +- .../android_frameworks_base/394556.patch | 270 ++++++ .../android_frameworks_base/394557.patch} | 12 +- .../android_frameworks_base/394558.patch} | 26 +- .../android_frameworks_base/394559.patch} | 8 +- .../android_frameworks_base/394560.patch} | 16 +- .../android_frameworks_base/394561.patch} | 12 +- .../android_frameworks_base/394562.patch} | 20 +- .../android_frameworks_base/394563.patch} | 48 +- .../LineageOS-20.0/ASB-2024-06/fwb-01.patch | 225 ----- .../LineageOS-20.0/ASB-2024-06/fwb-03.patch | 463 --------- .../LineageOS-20.0/ASB-2024-06/fwb-05.patch | 71 -- .../LineageOS-20.0/ASB-2024-06/fwb-11.patch | 912 ------------------ .../LineageOS-20.0/ASB-2024-06/fwb-13.patch | 274 ------ .../ASB-2024-06/libfmq-01.patch | 64 -- .../ASB-2024-06/statsd-01.patch | 87 -- PrebuiltApps | 2 +- Scripts/LineageOS-18.1/Patch.sh | 13 +- Scripts/LineageOS-19.1/Functions.sh | 3 +- Scripts/LineageOS-19.1/Patch.sh | 5 + Scripts/LineageOS-20.0/Functions.sh | 3 +- Scripts/LineageOS-20.0/Patch.sh | 8 +- 24 files changed, 474 insertions(+), 2193 deletions(-) create mode 100644 Patches/LineageOS-18.1/android_frameworks_base/394553.patch create mode 100644 Patches/LineageOS-18.1/android_frameworks_base/394554.patch rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-02.patch => LineageOS-18.1/android_frameworks_base/394555.patch} (88%) create mode 100644 Patches/LineageOS-18.1/android_frameworks_base/394556.patch rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-06.patch => LineageOS-18.1/android_frameworks_base/394557.patch} (90%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-04.patch => LineageOS-18.1/android_frameworks_base/394558.patch} (55%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-07.patch => LineageOS-18.1/android_frameworks_base/394559.patch} (89%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-08.patch => LineageOS-18.1/android_frameworks_base/394560.patch} (88%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-09.patch => LineageOS-18.1/android_frameworks_base/394561.patch} (82%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-12.patch => LineageOS-18.1/android_frameworks_base/394562.patch} (81%) rename Patches/{LineageOS-20.0/ASB-2024-06/fwb-10.patch => LineageOS-18.1/android_frameworks_base/394563.patch} (58%) delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/fwb-01.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/fwb-03.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/fwb-05.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/fwb-11.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/fwb-13.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/libfmq-01.patch delete mode 100644 Patches/LineageOS-20.0/ASB-2024-06/statsd-01.patch diff --git a/Patches/LineageOS-18.1/android_frameworks_base/394553.patch b/Patches/LineageOS-18.1/android_frameworks_base/394553.patch new file mode 100644 index 00000000..e70bea70 --- /dev/null +++ b/Patches/LineageOS-18.1/android_frameworks_base/394553.patch @@ -0,0 +1,47 @@ +From 00961ad29e26dde5d4f56de90ac333ceb2fc8d34 Mon Sep 17 00:00:00 2001 +From: Jing Ji +Date: Tue, 25 Oct 2022 22:39:52 -0700 +Subject: [PATCH] DO NOT MERGE: ActivityManager#killBackgroundProcesses can + kill caller's own app only + +unless it's a system app. + +Bug: 239423414 +Bug: 223376078 +Test: atest CtsAppTestCases:ActivityManagerTest +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d1c95670b248df945784b0f2830acf83b5682de3) +Merged-In: Iac6baa889965b8ffecd9a43179a4c96632ad1d02 +AOSP-Change-Id: Iac6baa889965b8ffecd9a43179a4c96632ad1d02 + +Change-Id: I41cd6fa1f71e950db18a9fd450355c4e6f80ec7d +--- + .../server/am/ActivityManagerService.java | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java +index 234b23a996267..815ddf63e565a 100644 +--- a/services/core/java/com/android/server/am/ActivityManagerService.java ++++ b/services/core/java/com/android/server/am/ActivityManagerService.java +@@ -4486,6 +4486,22 @@ void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) { + throw new SecurityException(msg); + } + ++ final int callingUid = Binder.getCallingUid(); ++ final int callingPid = Binder.getCallingPid(); ++ ++ ProcessRecord proc; ++ synchronized (mPidsSelfLocked) { ++ proc = mPidsSelfLocked.get(callingPid); ++ } ++ if (callingUid >= FIRST_APPLICATION_UID ++ && (proc == null || !proc.info.isSystemApp())) { ++ final String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" ++ + callingPid + ", uid=" + callingUid + " is not allowed"; ++ Slog.w(TAG, msg); ++ // Silently return to avoid existing apps from crashing. ++ return; ++ } ++ + final long callingId = Binder.clearCallingIdentity(); + try { + synchronized (this) { diff --git a/Patches/LineageOS-18.1/android_frameworks_base/394554.patch b/Patches/LineageOS-18.1/android_frameworks_base/394554.patch new file mode 100644 index 00000000..73255325 --- /dev/null +++ b/Patches/LineageOS-18.1/android_frameworks_base/394554.patch @@ -0,0 +1,46 @@ +From 14804676d97278009b746073e8339374b0cce927 Mon Sep 17 00:00:00 2001 +From: Jing Ji +Date: Thu, 19 Oct 2023 14:22:58 -0700 +Subject: [PATCH] DO NOT MERGE: Fix ActivityManager#killBackgroundProcesses + permissions + +In the pevious CL, we incorrectly added the permission check in the +killBackgroundProcessesExcept. Now fix this issue. + +Bug: 239423414 +Bug: 223376078 +Test: atest CtsAppTestCases:ActivityManagerTest +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:140fce861944419a375c669010c6c47cd7ff5b37) +Merged-In: I9471a77188ee63ec32cd0c81569193e4ccad885b +Change-Id: I9471a77188ee63ec32cd0c81569193e4ccad885b +--- + .../server/am/ActivityManagerService.java | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java +index 815ddf63e565a..234b23a996267 100644 +--- a/services/core/java/com/android/server/am/ActivityManagerService.java ++++ b/services/core/java/com/android/server/am/ActivityManagerService.java +@@ -4486,22 +4486,6 @@ void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) { + throw new SecurityException(msg); + } + +- final int callingUid = Binder.getCallingUid(); +- final int callingPid = Binder.getCallingPid(); +- +- ProcessRecord proc; +- synchronized (mPidsSelfLocked) { +- proc = mPidsSelfLocked.get(callingPid); +- } +- if (callingUid >= FIRST_APPLICATION_UID +- && (proc == null || !proc.info.isSystemApp())) { +- final String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" +- + callingPid + ", uid=" + callingUid + " is not allowed"; +- Slog.w(TAG, msg); +- // Silently return to avoid existing apps from crashing. +- return; +- } +- + final long callingId = Binder.clearCallingIdentity(); + try { + synchronized (this) { diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-02.patch b/Patches/LineageOS-18.1/android_frameworks_base/394555.patch similarity index 88% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-02.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394555.patch index 395bb88f..fcc9da32 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-02.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394555.patch @@ -1,4 +1,4 @@ -From c0c16283997bbca63edc79d820652587cbde15bb Mon Sep 17 00:00:00 2001 +From 179a5a7b48c4ec3ffebbf53b9833f6be6ef4e2b1 Mon Sep 17 00:00:00 2001 From: Valentin Iftime Date: Thu, 1 Feb 2024 13:58:49 +0100 Subject: [PATCH] Verify URI permission for channel sound update from @@ -10,19 +10,19 @@ Subject: [PATCH] Verify URI permission for channel sound update from Test: atest com.android.server.notification.NotificationManagerServiceTest#testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission Bug: 317357401 (cherry picked from commit 9b7bbbf5ad542ecf9ecbf8cd819b468791b443c0) -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2f26c0def503d3b8032c99adc8a11be87e35cdeb) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f090c0538a27d8658d8a860046d5c5e931302341) Merged-In: Ic7d2e96e43565e98d2aa29b8f2ba35c142387ba9 Change-Id: Ic7d2e96e43565e98d2aa29b8f2ba35c142387ba9 --- - .../NotificationManagerService.java | 22 +++++++ - .../NotificationManagerServiceTest.java | 63 +++++++++++++++++++ - 2 files changed, 85 insertions(+) + .../NotificationManagerService.java | 22 ++++++ + .../NotificationManagerServiceTest.java | 67 +++++++++++++++++++ + 2 files changed, 89 insertions(+) diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java -index ecd446519c09..4d1abc61aa73 100755 +index dfc9c135c7da7..40f6ed45174e2 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java -@@ -5705,6 +5705,10 @@ public void updateNotificationChannelFromPrivilegedListener(INotificationListene +@@ -5151,6 +5151,10 @@ public void updateNotificationChannelFromPrivilegedListener(INotificationListene Objects.requireNonNull(user); verifyPrivilegedListener(token, user, false); @@ -33,7 +33,7 @@ index ecd446519c09..4d1abc61aa73 100755 updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true); } -@@ -5796,6 +5800,24 @@ private void verifyPrivilegedListener(INotificationListener token, UserHandle us +@@ -5230,6 +5234,24 @@ private void verifyPrivilegedListener(INotificationListener token, UserHandle us } } @@ -56,13 +56,13 @@ index ecd446519c09..4d1abc61aa73 100755 + } + private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException { - int uid = INVALID_UID; - final long identity = Binder.clearCallingIdentity(); + int uid = 0; + long identity = Binder.clearCallingIdentity(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java -index 4f0a7ca0ad51..755bc1d35cf3 100755 +index 011c408492fa3..a1d6b56ff9cdb 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java -@@ -3319,6 +3319,69 @@ public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws +@@ -2664,6 +2664,73 @@ public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @@ -70,8 +70,10 @@ index 4f0a7ca0ad51..755bc1d35cf3 100755 + public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission() + throws Exception { + mService.setPreferencesHelper(mPreferencesHelper); ++ List associations = new ArrayList<>(); ++ associations.add("a"); + when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) -+ .thenReturn(singletonList(mock(AssociationInfo.class))); ++ .thenReturn(associations); + when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), + eq(mTestNotificationChannel.getId()), anyBoolean())) + .thenReturn(mTestNotificationChannel); @@ -102,8 +104,10 @@ index 4f0a7ca0ad51..755bc1d35cf3 100755 + public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound() + throws Exception { + mService.setPreferencesHelper(mPreferencesHelper); ++ List associations = new ArrayList<>(); ++ associations.add("a"); + when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid))) -+ .thenReturn(singletonList(mock(AssociationInfo.class))); ++ .thenReturn(associations); + when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), + eq(mTestNotificationChannel.getId()), anyBoolean())) + .thenReturn(mTestNotificationChannel); diff --git a/Patches/LineageOS-18.1/android_frameworks_base/394556.patch b/Patches/LineageOS-18.1/android_frameworks_base/394556.patch new file mode 100644 index 00000000..204335d0 --- /dev/null +++ b/Patches/LineageOS-18.1/android_frameworks_base/394556.patch @@ -0,0 +1,270 @@ +From 1ac8480b3163815253b07d5e2ffa5ae3d5065a07 Mon Sep 17 00:00:00 2001 +From: Valentin Iftime +Date: Thu, 22 Feb 2024 10:51:58 +0100 +Subject: [PATCH] Check for NLS bind permission when rebinding services + + Also, after updating packages with NLS components, check + the approved services and remove from approved list if missing permissions. + +Test: atest ManagedServicesTest +Bug: 321707289 + +(cherry picked from commit 24b13a64f9f5e5aa7f45a2132806d6c74e2c62dc) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0c15cdfdd4720efb72c3244a044bb27e2c286c4b) +Merged-In: I11901755ec430c6e3145def9d67e4e63cda00806 +Change-Id: I11901755ec430c6e3145def9d67e4e63cda00806 +--- + .../server/notification/ManagedServices.java | 108 ++++++++++++++---- + .../notification/ManagedServicesTest.java | 54 +++++++++ + 2 files changed, 139 insertions(+), 23 deletions(-) + +diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java +index a604625460a77..e5686dc3f0759 100644 +--- a/services/core/java/com/android/server/notification/ManagedServices.java ++++ b/services/core/java/com/android/server/notification/ManagedServices.java +@@ -150,7 +150,9 @@ abstract public class ManagedServices { + // List of approved packages or components (by user, then by primary/secondary) that are + // allowed to be bound as managed services. A package or component appearing in this list does + // not mean that we are currently bound to said package/component. +- private ArrayMap>> mApproved = new ArrayMap<>(); ++ ++ @GuardedBy("mApproved") ++ private final ArrayMap>> mApproved = new ArrayMap<>(); + + // True if approved services are stored in xml, not settings. + private boolean mUseXml; +@@ -761,6 +763,23 @@ protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) + return false; + } + ++ protected boolean isPackageOrComponentAllowedWithPermission(ComponentName component, ++ int userId) { ++ if (!(isPackageOrComponentAllowed(component.flattenToString(), userId) ++ || isPackageOrComponentAllowed(component.getPackageName(), userId))) { ++ return false; ++ } ++ return componentHasBindPermission(component, userId); ++ } ++ ++ private boolean componentHasBindPermission(ComponentName component, int userId) { ++ ServiceInfo info = getServiceInfo(component, userId); ++ if (info == null) { ++ return false; ++ } ++ return mConfig.bindPermission.equals(info.permission); ++ } ++ + protected boolean isPackageAllowed(String pkg, int userId) { + if (pkg == null) { + return false; +@@ -811,6 +830,7 @@ public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] u + for (int uid : uidList) { + if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) { + anyServicesInvolved = true; ++ trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid)); + } + } + } +@@ -938,8 +958,7 @@ protected void setComponentState(ComponentName component, boolean enabled) { + for (int i = 0; i < userIds.size(); i++) { + final int userId = userIds.get(i); + if (enabled) { +- if (isPackageOrComponentAllowed(component.flattenToString(), userId) +- || isPackageOrComponentAllowed(component.getPackageName(), userId)) { ++ if (isPackageOrComponentAllowedWithPermission(component, userId)) { + registerServiceLocked(component, userId); + } else { + Slog.d(TAG, component + " no longer has permission to be bound"); +@@ -1078,6 +1097,33 @@ private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, S + return removed; + } + ++ private void trimApprovedListsForInvalidServices(String packageName, int userId) { ++ synchronized (mApproved) { ++ final ArrayMap> approvedByType = mApproved.get(userId); ++ if (approvedByType == null) { ++ return; ++ } ++ for (int i = 0; i < approvedByType.size(); i++) { ++ final ArraySet approved = approvedByType.valueAt(i); ++ for (int j = approved.size() - 1; j >= 0; j--) { ++ final String approvedPackageOrComponent = approved.valueAt(j); ++ if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) { ++ final ComponentName component = ComponentName.unflattenFromString( ++ approvedPackageOrComponent); ++ if (component != null && !componentHasBindPermission(component, userId)) { ++ approved.removeAt(j); ++ if (DEBUG) { ++ Slog.v(TAG, "Removing " + approvedPackageOrComponent ++ + " from approved list; no bind permission found " ++ + mConfig.bindPermission); ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ + protected String getPackageName(String packageOrComponent) { + final ComponentName component = ComponentName.unflattenFromString(packageOrComponent); + if (component != null) { +@@ -1237,26 +1283,20 @@ private void bindToServices(SparseArray> componentsToBind) { + final int userId = componentsToBind.keyAt(i); + final Set add = componentsToBind.get(userId); + for (ComponentName component : add) { +- try { +- ServiceInfo info = mPm.getServiceInfo(component, +- PackageManager.MATCH_DIRECT_BOOT_AWARE +- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); +- if (info == null) { +- Slog.w(TAG, "Not binding " + getCaption() + " service " + component +- + ": service not found"); +- continue; +- } +- if (!mConfig.bindPermission.equals(info.permission)) { +- Slog.w(TAG, "Not binding " + getCaption() + " service " + component +- + ": it does not require the permission " + mConfig.bindPermission); +- continue; +- } +- Slog.v(TAG, +- "enabling " + getCaption() + " for " + userId + ": " + component); +- registerService(component, userId); +- } catch (RemoteException e) { +- e.rethrowFromSystemServer(); ++ ServiceInfo info = getServiceInfo(component, userId); ++ if (info == null) { ++ Slog.w(TAG, "Not binding " + getCaption() + " service " + component ++ + ": service not found"); ++ continue; + } ++ if (!mConfig.bindPermission.equals(info.permission)) { ++ Slog.w(TAG, "Not binding " + getCaption() + " service " + component ++ + ": it does not require the permission " + mConfig.bindPermission); ++ continue; ++ } ++ Slog.v(TAG, ++ "enabling " + getCaption() + " for " + userId + ": " + component); ++ registerService(component, userId); + } + } + } +@@ -1270,6 +1310,15 @@ private void registerService(final ComponentName name, final int userid) { + } + } + ++ @VisibleForTesting ++ void reregisterService(final ComponentName cn, final int userId) { ++ // If rebinding a package that died, ensure it still has permission ++ // after the rebind delay ++ if (isPackageOrComponentAllowedWithPermission(cn, userId)) { ++ registerService(cn, userId); ++ } ++ } ++ + /** + * Inject a system service into the management list. + */ +@@ -1370,7 +1419,7 @@ public void onBindingDied(ComponentName name) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { +- registerService(name, userid); ++ reregisterService(name, userid); + } + }, ON_BINDING_DIED_REBIND_DELAY_MS); + } else { +@@ -1502,6 +1551,19 @@ private void unbindService(ServiceConnection connection, ComponentName component + } + } + ++ private ServiceInfo getServiceInfo(ComponentName component, int userId) { ++ try { ++ return mPm.getServiceInfo(component, ++ PackageManager.GET_META_DATA ++ | PackageManager.MATCH_DIRECT_BOOT_AWARE ++ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, ++ userId); ++ } catch (RemoteException e) { ++ e.rethrowFromSystemServer(); ++ } ++ return null; ++ } ++ + public class ManagedServiceInfo implements IBinder.DeathRecipient { + public IInterface service; + public ComponentName component; +diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +index 99433a6603c91..e7187f393751d 100644 +--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java ++++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +@@ -27,8 +27,10 @@ + import static org.mockito.Matchers.any; + import static org.mockito.Matchers.anyInt; + import static org.mockito.Matchers.eq; ++import static org.mockito.Mockito.doReturn; + import static org.mockito.Mockito.mock; + import static org.mockito.Mockito.never; ++import static org.mockito.Mockito.spy; + import static org.mockito.Mockito.times; + import static org.mockito.Mockito.verify; + import static org.mockito.Mockito.when; +@@ -775,6 +777,58 @@ public void testUpgradeAppBindsNewServices() throws Exception { + } + } + ++ @Test ++ public void testUpgradeAppNoPermissionNoRebind() throws Exception { ++ Context context = spy(getContext()); ++ doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any()); ++ ++ ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, ++ mIpm, ++ APPROVAL_BY_COMPONENT); ++ ++ List packages = new ArrayList<>(); ++ packages.add("package"); ++ addExpectedServices(service, packages, 0); ++ ++ final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1"); ++ final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2"); ++ ++ // Both components are approved initially ++ mExpectedPrimaryComponentNames.clear(); ++ mExpectedPrimaryPackages.clear(); ++ mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2"); ++ mExpectedSecondaryComponentNames.clear(); ++ mExpectedSecondaryPackages.clear(); ++ ++ loadXml(service); ++ ++ //Component package/C1 loses bind permission ++ when(mIpm.getServiceInfo(any(), anyInt(), anyInt())).thenAnswer( ++ (Answer) invocation -> { ++ ComponentName invocationCn = invocation.getArgument(0); ++ if (invocationCn != null) { ++ ServiceInfo serviceInfo = new ServiceInfo(); ++ serviceInfo.packageName = invocationCn.getPackageName(); ++ serviceInfo.name = invocationCn.getClassName(); ++ if (invocationCn.equals(unapprovedComponent)) { ++ serviceInfo.permission = "none"; ++ } else { ++ serviceInfo.permission = service.getConfig().bindPermission; ++ } ++ serviceInfo.metaData = null; ++ return serviceInfo; ++ } ++ return null; ++ } ++ ); ++ ++ // Trigger package update ++ service.onPackagesChanged(false, new String[]{"package"}, new int[]{0}); ++ ++ assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent)); ++ assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent)); ++ } ++ + @Test + public void testSetPackageOrComponentEnabled() throws Exception { + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-06.patch b/Patches/LineageOS-18.1/android_frameworks_base/394557.patch similarity index 90% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-06.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394557.patch index a361be5b..fbaddc8f 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-06.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394557.patch @@ -1,4 +1,4 @@ -From b403e48e6aff45880c2970102555cc77cdcfe322 Mon Sep 17 00:00:00 2001 +From 47b5cdfc811916e1bfe36f98b83697a2027fc96c Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 6 Feb 2024 17:19:37 +0800 Subject: [PATCH] Hide window immediately if itself doesn't run hide animation @@ -21,10 +21,10 @@ Change-Id: Iafc2b2c2a24d8fc8d147354ef2f0b4afeeb510c5 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java -index 6d6e84f611cf..0ba2f2f2f418 100644 +index 7360e3677def6..319b7e88258db 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java -@@ -3296,8 +3296,10 @@ boolean hide(boolean doAnimation, boolean requestAnim) { +@@ -3009,8 +3009,10 @@ boolean hideLw(boolean doAnimation, boolean requestAnim) { return false; } if (doAnimation) { @@ -38,12 +38,12 @@ index 6d6e84f611cf..0ba2f2f2f418 100644 } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java -index 219f4415c623..44ae8dde9bde 100644 +index 360d73b5bd872..0bf95eca08f89 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java -@@ -227,6 +227,26 @@ public void testIsOnScreen_hiddenByPolicy() { +@@ -205,6 +205,26 @@ public void testIsOnScreen_hiddenByPolicy() { assertTrue(window.isOnScreen()); - window.hide(false /* doAnimation */, false /* requestAnim */); + window.hideLw(false /* doAnimation */); assertFalse(window.isOnScreen()); + + // Verifies that a window without animation can be hidden even if its parent is animating. diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-04.patch b/Patches/LineageOS-18.1/android_frameworks_base/394558.patch similarity index 55% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-04.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394558.patch index fcc305f8..f8a565a8 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-04.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394558.patch @@ -1,6 +1,6 @@ -From 88ea616cf95aff9169daec33a0a3d93a30b15727 Mon Sep 17 00:00:00 2001 +From 80a45f078fcf1b7157535dcbf07d210ac2c7cd82 Mon Sep 17 00:00:00 2001 From: Yi-an Chen -Date: Wed, 21 Feb 2024 01:56:22 +0000 +Date: Tue, 20 Feb 2024 04:34:57 +0000 Subject: [PATCH] Fix error handling for non-dynamic permissions We only allow removing dynamic permissions. When removePermission() is @@ -10,22 +10,22 @@ should also return early to avoid the removePermission() call. Test: manual Bug: 321555066 Fixes: 321711213 -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:528a87e90ff9354581d54fd37fbe9f95cccbcdb1) -Merged-In: Ie2f43663bc71a06ffadb868d2d0eea5ee78f76e5 -Change-Id: Ie2f43663bc71a06ffadb868d2d0eea5ee78f76e5 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2b5d63b64b2b8208ccc4f62eac3d8962f981dbf8) +Merged-In: I7336f2fc78804f26e4b2a329870ecdea776595d8 +Change-Id: I7336f2fc78804f26e4b2a329870ecdea776595d8 --- - .../server/pm/permission/PermissionManagerServiceImpl.java | 1 + + .../android/server/pm/permission/PermissionManagerService.java | 1 + 1 file changed, 1 insertion(+) -diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java -index 5dc7e23c01e2..1ec3403a9d46 100644 ---- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java -+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java -@@ -681,6 +681,7 @@ public void removePermission(String permName) { +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 f83c3d5145cc7..eb27a13523baf 100644 +--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java ++++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +@@ -645,6 +645,7 @@ public void removePermission(String permName) { // TODO: switch this back to SecurityException Slog.wtf(TAG, "Not allowed to modify non-dynamic permission " + permName); + return; } - mRegistry.removePermission(permName); - } + mSettings.removePermissionLocked(permName); + mPackageManagerInt.writeSettings(false); diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-07.patch b/Patches/LineageOS-18.1/android_frameworks_base/394559.patch similarity index 89% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-07.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394559.patch index c1834ee4..724fb031 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-07.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394559.patch @@ -1,4 +1,4 @@ -From ac134a1b6a0ace6bf43e83d414f6433f3cf40e53 Mon Sep 17 00:00:00 2001 +From 18d1359a28cee22491dbe2f8b814ab999348ebfa Mon Sep 17 00:00:00 2001 From: Dmitry Dementyev Date: Tue, 26 Mar 2024 10:31:44 -0700 Subject: [PATCH] Add more checkKeyIntent checks to AccountManagerService. @@ -14,10 +14,10 @@ Change-Id: I9e45d758a2320328da5664b6341eafe6f285f297 1 file changed, 10 insertions(+) diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java -index 1c3564bfdba2..bc13f106ce6e 100644 +index 8a9ddda50d63b..37a68d3eec76c 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java -@@ -3561,6 +3561,11 @@ public void onResult(Bundle result) { +@@ -3475,6 +3475,11 @@ public void onResult(Bundle result) { // Strip auth token from result. result.remove(AccountManager.KEY_AUTHTOKEN); @@ -29,7 +29,7 @@ index 1c3564bfdba2..bc13f106ce6e 100644 if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, -@@ -5146,6 +5151,11 @@ public void onResult(Bundle result) { +@@ -5052,6 +5057,11 @@ public void onResult(Bundle result) { } else { if (mStripAuthTokenFromResult) { result.remove(AccountManager.KEY_AUTHTOKEN); diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-08.patch b/Patches/LineageOS-18.1/android_frameworks_base/394560.patch similarity index 88% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-08.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394560.patch index c14de248..6ed7b5be 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-08.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394560.patch @@ -1,8 +1,7 @@ -From 5dd0b87bc501c83abbe2462d17fcc7f9f3dfab4d Mon Sep 17 00:00:00 2001 +From a0059406f6fa6fa600bd6d5fc488de1d3aa956af Mon Sep 17 00:00:00 2001 From: Haoran Zhang Date: Wed, 13 Mar 2024 17:08:00 +0000 -Subject: [PATCH] [DO NOT MERGE][Autofill Framework] Add in check for intent - filter when setting/updating service +Subject: [PATCH] Add in check for intent filter when setting/updating service For test, I registered two tests around on ABTD. CtsAutoFillServiceTestCases module is passing except three known failures: @@ -10,11 +9,10 @@ Test run link: - https://android-build.corp.google.com/builds/abtd/run/L33300030002610600 - https://android-build.corp.google.com/builds/abtd/run/L58100030002616607 - Bug: b/324874908 Test: atest CtsAutoFillServiceTestCases (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:141d9d050346bfc4673c429382deb1b3d210f6ad) -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ee20adb4b4b2065e040167a4354c4fabaf06e35d) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:51d64705ab70788a536c26d4df5e63f0952ec98f) Merged-In: I51c2e3788ac29ff4d6b86aa2a735ff2ea1463a77 Change-Id: I51c2e3788ac29ff4d6b86aa2a735ff2ea1463a77 --- @@ -22,12 +20,12 @@ Change-Id: I51c2e3788ac29ff4d6b86aa2a735ff2ea1463a77 1 file changed, 27 insertions(+) diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java -index 20b2a74f5be5..2cda39d4b065 100644 +index 57ffe0498a88e..309f78006d4b6 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -32,8 +32,10 @@ - import android.annotation.Nullable; - import android.app.ActivityManagerInternal; + import android.app.ActivityTaskManager; + import android.app.IActivityTaskManager; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.PackageManager; @@ -36,7 +34,7 @@ index 20b2a74f5be5..2cda39d4b065 100644 import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.metrics.LogMaker; -@@ -239,6 +241,31 @@ protected boolean updateLocked(boolean disabled) { +@@ -235,6 +237,31 @@ protected boolean updateLocked(boolean disabled) { @Override // from PerUserSystemService protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent) throws NameNotFoundException { diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-09.patch b/Patches/LineageOS-18.1/android_frameworks_base/394561.patch similarity index 82% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-09.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394561.patch index fe8e92c4..4e8eeb59 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-09.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394561.patch @@ -1,4 +1,4 @@ -From d0df12d2f498f441d87852580a89f8588380d902 Mon Sep 17 00:00:00 2001 +From a0d6c266c99cdcdba0ef4674cf6995619f13efa7 Mon Sep 17 00:00:00 2001 From: Hans Boehm Date: Tue, 2 Jan 2024 16:53:13 -0800 Subject: [PATCH] Check hidden API exemptions @@ -18,7 +18,7 @@ Change-Id: I83cd60e46407a4a082f9f3c80e937dbd522dbac4 1 file changed, 10 insertions(+) diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java -index bf2898137967..63bcf5f119e1 100644 +index 39038f555044e..4d69f217c5e6a 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -431,6 +431,8 @@ private Process.ProcessStartResult zygoteSendArgsAndGetResult( @@ -30,18 +30,18 @@ index bf2898137967..63bcf5f119e1 100644 } } -@@ -972,6 +974,14 @@ private boolean maybeSetApiDenylistExemptions(ZygoteState state, boolean sendIfE +@@ -980,6 +982,14 @@ private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIf return true; } -+ for (/* NonNull */ String s : mApiDenylistExemptions) { ++ for (/* NonNull */ String s : mApiBlacklistExemptions) { + // indexOf() is intrinsified and faster than contains(). + if (s.indexOf('\n') >= 0 || s.indexOf('\r') >= 0 || s.indexOf('\u0000') >= 0) { + Slog.e(LOG_TAG, "Failed to set API denylist exemptions: Bad character"); -+ mApiDenylistExemptions = Collections.emptyList(); ++ mApiBlacklistExemptions = Collections.emptyList(); + return false; + } + } try { - state.mZygoteOutputWriter.write(Integer.toString(mApiDenylistExemptions.size() + 1)); + state.mZygoteOutputWriter.write(Integer.toString(mApiBlacklistExemptions.size() + 1)); state.mZygoteOutputWriter.newLine(); diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-12.patch b/Patches/LineageOS-18.1/android_frameworks_base/394562.patch similarity index 81% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-12.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394562.patch index a54c402e..1572b67c 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-12.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394562.patch @@ -1,23 +1,23 @@ -From e3979baab5718a69f6d58040ba42f67b4fd73d35 Mon Sep 17 00:00:00 2001 +From 4e6cea9041b540298c7c0a326107532d19a0d997 Mon Sep 17 00:00:00 2001 From: Ameer Armaly Date: Fri, 8 Mar 2024 19:41:06 +0000 -Subject: [PATCH] [RESTRICT AUTOMERGE] AccessibilityManagerService: remove - uninstalled services from enabled list after service update. +Subject: [PATCH] AccessibilityManagerService: remove uninstalled services from + enabled list after service update. Bug: 326485767 Test: atest AccessibilityEndToEndTest#testUpdateServiceWithoutIntent_disablesService -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:766911c3312573196b33efd1c3c29ccece806846) -Merged-In: I958d58953b300c8093335a22e207baac471ae9f9 -Change-Id: I958d58953b300c8093335a22e207baac471ae9f9 +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5405514a23edcba0cf30e6ec78189e3f4e7d95cf) +Merged-In: I5e59296fcad68e62b34c74ee5fd80b6ad6b46fa1 +Change-Id: I5e59296fcad68e62b34c74ee5fd80b6ad6b46fa1 --- .../AccessibilityManagerService.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java -index 3818a884c94a..8271aed181c9 100644 +index f9fbda357075d..021ef5567f25a 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java -@@ -2161,10 +2161,13 @@ private void updateServicesLocked(AccessibilityUserState userState) { +@@ -1612,10 +1612,13 @@ private void updateServicesLocked(AccessibilityUserState userState) { boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class) .isUserUnlockingOrUnlocked(userState.mUserId); @@ -31,10 +31,10 @@ index 3818a884c94a..8271aed181c9 100644 AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName); -@@ -2215,6 +2218,25 @@ this, getTraceManager(), mWindowManagerService, +@@ -1664,6 +1667,25 @@ this, mWindowManagerService, getSystemActionPerformer(), + if (audioManager != null) { audioManager.setAccessibilityServiceUids(mTempIntArray); } - mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray); + // If any services have been removed, remove them from the enabled list and the touch + // exploration granted list. + boolean anyServiceRemoved = diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-10.patch b/Patches/LineageOS-18.1/android_frameworks_base/394563.patch similarity index 58% rename from Patches/LineageOS-20.0/ASB-2024-06/fwb-10.patch rename to Patches/LineageOS-18.1/android_frameworks_base/394563.patch index fa65bba2..ab2252ec 100644 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-10.patch +++ b/Patches/LineageOS-18.1/android_frameworks_base/394563.patch @@ -1,7 +1,7 @@ -From cbf4c6352bf85e4d8289d6bc1135d66c95f0e1e1 Mon Sep 17 00:00:00 2001 +From 42515cb6e3148d89efab6fd39537b874a3f29853 Mon Sep 17 00:00:00 2001 From: Guojing Yuan Date: Thu, 14 Dec 2023 19:30:04 +0000 -Subject: [PATCH] [CDM][CMD] Check permissions for CDM shell commands +Subject: [PATCH] Check permissions for CDM shell commands Override handleShellCommand instead of onShellCommand because Binder.onShellCommand checks the necessary permissions of the caller. @@ -10,52 +10,52 @@ Bug: 313428840 Test: manually tested CDM shell commands (cherry picked from commit 1761a0fee9c2cd9787bbb7fbdbe30b4c2b03396e) -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1ae3b43c248cdf5ee63311f06acd0ee19d93f0cd) +(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8d008c61451dba86aa9f14c6bcd661db2cea4856) Merged-In: I5539b3594feb5544c458c0fd1061b51a0a808900 Change-Id: I5539b3594feb5544c458c0fd1061b51a0a808900 --- - .../CompanionDeviceManagerService.java | 20 ++++++++----------- - 1 file changed, 8 insertions(+), 12 deletions(-) + .../companion/CompanionDeviceManagerService.java | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java -index 41546d2bdc38..05c29d7e446a 100644 +index 91c2abc024304..275f31f1b6eb0 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java -@@ -75,12 +75,11 @@ - import android.os.Handler; - import android.os.Message; +@@ -28,6 +28,7 @@ + import static java.util.concurrent.TimeUnit.MINUTES; + + import android.annotation.CheckResult; ++import android.annotation.NonNull; + import android.annotation.Nullable; + import android.app.AppOpsManager; + import android.app.PendingIntent; +@@ -52,11 +53,10 @@ + import android.os.IDeviceIdleController; + import android.os.IInterface; import android.os.Parcel; +import android.os.ParcelFileDescriptor; - import android.os.PowerWhitelistManager; - import android.os.RemoteCallbackList; + import android.os.Process; import android.os.RemoteException; -import android.os.ResultReceiver; import android.os.ServiceManager; -import android.os.ShellCallback; - import android.os.SystemProperties; + import android.os.ShellCommand; import android.os.UserHandle; - import android.os.UserManager; -@@ -827,16 +826,13 @@ public boolean canPairWithoutPrompt(String packageName, String macAddress, int u + import android.os.UserManagerInternal; +@@ -455,10 +455,12 @@ private void checkUsesFeature(String pkg, int userId) { } @Override - public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, - String[] args, ShellCallback callback, ResultReceiver resultReceiver) - throws RemoteException { -- enforceCallerCanManageCompanionDevice(getContext(), "onShellCommand"); -- -- final CompanionDeviceShellCommand cmd = new CompanionDeviceShellCommand( -- CompanionDeviceManagerService.this, -- mAssociationStore, -- mDevicePresenceMonitor); -- cmd.exec(this, in, out, err, args, callback, resultReceiver); +- new ShellCmd().exec(this, in, out, err, args, callback, resultReceiver); + public int handleShellCommand(@NonNull ParcelFileDescriptor in, + @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, + @NonNull String[] args) { -+ return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, -+ mAssociationStore, mDevicePresenceMonitor) ++ return new ShellCmd() + .exec(this, in.getFileDescriptor(), out.getFileDescriptor(), + err.getFileDescriptor(), args); } + } - @Override diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-01.patch b/Patches/LineageOS-20.0/ASB-2024-06/fwb-01.patch deleted file mode 100644 index 6b382b38..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-01.patch +++ /dev/null @@ -1,225 +0,0 @@ -From 42c9c06f9c0f8d7212284c6555e3ffd25bd4ddbf Mon Sep 17 00:00:00 2001 -From: Pinyao Ting -Date: Thu, 30 Nov 2023 23:12:39 +0000 -Subject: [PATCH] Added throttle when reporting shortcut usage - -Bug: 304290201 -Test: manual -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:bd88f35c6797b1795d1150af92760531ff73f14f) -Merged-In: I96370cbd4f6a55f894c1a93307e5f82dfd394652 -Change-Id: I96370cbd4f6a55f894c1a93307e5f82dfd394652 ---- - .../android/server/pm/ShortcutPackage.java | 32 +++++++++++ - .../android/server/pm/ShortcutService.java | 18 ++---- - .../server/pm/ShortcutManagerTest1.java | 55 ++++++++++++++++++- - .../server/pm/ShortcutManagerTest2.java | 2 + - 4 files changed, 92 insertions(+), 15 deletions(-) - -diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java -index 5a662d9f3139..3b3c11e1209d 100644 ---- a/services/core/java/com/android/server/pm/ShortcutPackage.java -+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java -@@ -33,6 +33,7 @@ - import android.app.appsearch.SearchResults; - import android.app.appsearch.SearchSpec; - import android.app.appsearch.SetSchemaRequest; -+import android.app.usage.UsageStatsManagerInternal; - import android.content.ComponentName; - import android.content.Intent; - import android.content.IntentFilter; -@@ -47,6 +48,7 @@ - import android.os.Binder; - import android.os.PersistableBundle; - import android.os.StrictMode; -+import android.os.SystemClock; - import android.text.format.Formatter; - import android.util.ArrayMap; - import android.util.ArraySet; -@@ -160,6 +162,9 @@ class ShortcutPackage extends ShortcutPackageItem { - private static final String KEY_BITMAPS = "bitmaps"; - private static final String KEY_BITMAP_BYTES = "bitmapBytes"; - -+ @VisibleForTesting -+ public static final int REPORT_USAGE_BUFFER_SIZE = 3; -+ - private final Executor mExecutor; - - /** -@@ -195,6 +200,9 @@ class ShortcutPackage extends ShortcutPackageItem { - - private long mLastKnownForegroundElapsedTime; - -+ @GuardedBy("mLock") -+ private List mLastReportedTime = new ArrayList<>(); -+ - @GuardedBy("mLock") - private boolean mIsAppSearchSchemaUpToDate; - -@@ -1677,6 +1685,30 @@ public boolean hasNonManifestShortcuts() { - return condition[0]; - } - -+ void reportShortcutUsed(@NonNull final UsageStatsManagerInternal usageStatsManagerInternal, -+ @NonNull final String shortcutId) { -+ synchronized (mLock) { -+ final long currentTS = SystemClock.elapsedRealtime(); -+ final ShortcutService s = mShortcutUser.mService; -+ if (mLastReportedTime.isEmpty() -+ || mLastReportedTime.size() < REPORT_USAGE_BUFFER_SIZE) { -+ mLastReportedTime.add(currentTS); -+ } else if (currentTS - mLastReportedTime.get(0) > s.mSaveDelayMillis) { -+ mLastReportedTime.remove(0); -+ mLastReportedTime.add(currentTS); -+ } else { -+ return; -+ } -+ final long token = s.injectClearCallingIdentity(); -+ try { -+ usageStatsManagerInternal.reportShortcutUsage(getPackageName(), shortcutId, -+ getUser().getUserId()); -+ } finally { -+ s.injectRestoreCallingIdentity(token); -+ } -+ } -+ } -+ - public void dump(@NonNull PrintWriter pw, @NonNull String prefix, DumpFilter filter) { - pw.println(); - -diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java -index 7fd32d2a6b1b..84eb799e31ff 100644 ---- a/services/core/java/com/android/server/pm/ShortcutService.java -+++ b/services/core/java/com/android/server/pm/ShortcutService.java -@@ -365,7 +365,7 @@ public boolean test(PackageInfo pi) { - private CompressFormat mIconPersistFormat; - private int mIconPersistQuality; - -- private int mSaveDelayMillis; -+ int mSaveDelayMillis; - - private final IPackageManager mIPackageManager; - private final PackageManagerInternal mPackageManagerInternal; -@@ -2269,7 +2269,7 @@ public void pushDynamicShortcut(String packageName, ShortcutInfo shortcut, - - packageShortcutsChanged(ps, changedShortcuts, removedShortcuts); - -- reportShortcutUsedInternal(packageName, shortcut.getId(), userId); -+ ps.reportShortcutUsed(mUsageStatsManagerInternal, shortcut.getId()); - - verifyStates(); - } -@@ -2676,25 +2676,17 @@ public void reportShortcutUsed(String packageName, String shortcutId, int userId - Slog.d(TAG, String.format("reportShortcutUsed: Shortcut %s package %s used on user %d", - shortcutId, packageName, userId)); - } -+ final ShortcutPackage ps; - synchronized (mLock) { - throwIfUserLockedL(userId); -- final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); -+ ps = getPackageShortcutsForPublisherLocked(packageName, userId); - if (ps.findShortcutById(shortcutId) == null) { - Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s", - packageName, shortcutId)); - return; - } - } -- reportShortcutUsedInternal(packageName, shortcutId, userId); -- } -- -- private void reportShortcutUsedInternal(String packageName, String shortcutId, int userId) { -- final long token = injectClearCallingIdentity(); -- try { -- mUsageStatsManagerInternal.reportShortcutUsage(packageName, shortcutId, userId); -- } finally { -- injectRestoreCallingIdentity(token); -- } -+ ps.reportShortcutUsed(mUsageStatsManagerInternal, shortcutId); - } - - @Override -diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java -index 867890f938ba..0f00fb877afe 100644 ---- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java -+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java -@@ -402,8 +402,8 @@ public void testAddDynamicShortcuts() { - - public void testPushDynamicShortcut() { - // Change the max number of shortcuts. -- mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=5"); -- -+ mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=5," -+ + ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=1"); - setCaller(CALLING_PACKAGE_1, USER_0); - - final ShortcutInfo s1 = makeShortcut("s1"); -@@ -541,6 +541,57 @@ public void testPushDynamicShortcut() { - eq(CALLING_PACKAGE_1), eq("s9"), eq(USER_0)); - } - -+ public void testPushDynamicShortcut_CallsToUsageStatsManagerAreThrottled() -+ throws InterruptedException { -+ mService.updateConfigurationLocked( -+ ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=500"); -+ -+ // Verify calls to UsageStatsManagerInternal#reportShortcutUsage are throttled. -+ setCaller(CALLING_PACKAGE_1, USER_0); -+ for (int i = 0; i < ShortcutPackage.REPORT_USAGE_BUFFER_SIZE; i++) { -+ final ShortcutInfo si = makeShortcut("s" + i); -+ mManager.pushDynamicShortcut(si); -+ } -+ verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( -+ eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_0)); -+ Mockito.reset(mMockUsageStatsManagerInternal); -+ for (int i = ShortcutPackage.REPORT_USAGE_BUFFER_SIZE; i <= 10; i++) { -+ final ShortcutInfo si = makeShortcut("s" + i); -+ mManager.pushDynamicShortcut(si); -+ } -+ verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( -+ any(), any(), anyInt()); -+ -+ // Verify pkg2 isn't blocked by pkg1, but consecutive calls from pkg2 are throttled as well. -+ setCaller(CALLING_PACKAGE_2, USER_0); -+ for (int i = 0; i < ShortcutPackage.REPORT_USAGE_BUFFER_SIZE; i++) { -+ final ShortcutInfo si = makeShortcut("s" + i); -+ mManager.pushDynamicShortcut(si); -+ } -+ verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( -+ eq(CALLING_PACKAGE_2), eq("s1"), eq(USER_0)); -+ Mockito.reset(mMockUsageStatsManagerInternal); -+ for (int i = ShortcutPackage.REPORT_USAGE_BUFFER_SIZE; i <= 10; i++) { -+ final ShortcutInfo si = makeShortcut("s" + i); -+ mManager.pushDynamicShortcut(si); -+ } -+ verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage( -+ any(), any(), anyInt()); -+ -+ Mockito.reset(mMockUsageStatsManagerInternal); -+ // Let time passes which resets the throttle -+ Thread.sleep(505); -+ // Verify UsageStatsManagerInternal#reportShortcutUsed can be called again -+ setCaller(CALLING_PACKAGE_1, USER_0); -+ mManager.pushDynamicShortcut(makeShortcut("s10")); -+ setCaller(CALLING_PACKAGE_2, USER_0); -+ mManager.pushDynamicShortcut(makeShortcut("s10")); -+ verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( -+ eq(CALLING_PACKAGE_1), any(), eq(USER_0)); -+ verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage( -+ eq(CALLING_PACKAGE_2), any(), eq(USER_0)); -+ } -+ - public void testUnlimitedCalls() { - setCaller(CALLING_PACKAGE_1, USER_0); - -diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java -index 86d4655e9d3a..ea134dc66e3f 100644 ---- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java -+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java -@@ -2175,6 +2175,8 @@ public void testThrottling_resetByInternalCall() throws Exception { - - public void testReportShortcutUsed() { - mRunningUsers.put(USER_10, true); -+ mService.updateConfigurationLocked( -+ ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=1"); - - runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { - reset(mMockUsageStatsManagerInternal); diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-03.patch b/Patches/LineageOS-20.0/ASB-2024-06/fwb-03.patch deleted file mode 100644 index f178622b..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-03.patch +++ /dev/null @@ -1,463 +0,0 @@ -From fcb02396749ec9318803887febffea13f726dfc2 Mon Sep 17 00:00:00 2001 -From: Valentin Iftime -Date: Thu, 22 Feb 2024 10:51:58 +0100 -Subject: [PATCH] Check for NLS bind permission when rebinding services - - Also, after updating packages with NLS components, check - the approved services and remove from approved list if missing permissions. - -Test: atest ManagedServicesTest -Bug: 321707289 - -(cherry picked from commit 24b13a64f9f5e5aa7f45a2132806d6c74e2c62dc) -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f126be35f4b9f179dbb957ec56ca80b12f47abdc) -Merged-In: I11901755ec430c6e3145def9d67e4e63cda00806 -Change-Id: I11901755ec430c6e3145def9d67e4e63cda00806 ---- - .../server/notification/ManagedServices.java | 193 ++++++++++-------- - .../notification/ManagedServicesTest.java | 54 +++++ - 2 files changed, 164 insertions(+), 83 deletions(-) - -diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java -index d0cfa164b5af..c3691e717e9b 100644 ---- a/services/core/java/com/android/server/notification/ManagedServices.java -+++ b/services/core/java/com/android/server/notification/ManagedServices.java -@@ -132,7 +132,6 @@ abstract public class ManagedServices { - - // contains connections to all connected services, including app services - // and system services -- @GuardedBy("mMutex") - private final ArrayList mServices = new ArrayList<>(); - /** - * The services that have been bound by us. If the service is also connected, it will also -@@ -151,15 +150,13 @@ abstract public class ManagedServices { - = new ArraySet<>(); - // Just the packages from mEnabledServicesForCurrentProfiles - private ArraySet mEnabledServicesPackageNames = new ArraySet<>(); -- // Per user id, list of enabled packages that have nevertheless asked not to be run -- private final android.util.SparseSetArray mSnoozing = -- new android.util.SparseSetArray<>(); -+ // List of enabled packages that have nevertheless asked not to be run -+ private ArraySet mSnoozingForCurrentProfiles = new ArraySet<>(); - - // List of approved packages or components (by user, then by primary/secondary) that are - // allowed to be bound as managed services. A package or component appearing in this list does - // not mean that we are currently bound to said package/component. -- protected final ArrayMap>> mApproved = -- new ArrayMap<>(); -+ protected ArrayMap>> mApproved = new ArrayMap<>(); - - // List of packages or components (by user) that are configured to be enabled/disabled - // explicitly by the user -@@ -318,7 +315,6 @@ ArrayMap> resetComponents(String packageName, - return changes; - } - -- @GuardedBy("mApproved") - private boolean clearUserSetFlagLocked(ComponentName component, int userId) { - String approvedValue = getApprovedValue(component.flattenToString()); - ArraySet userSet = mUserSetServices.get(userId); -@@ -379,8 +375,8 @@ public void dump(PrintWriter pw, DumpFilter filter) { - pw.println(" " + cmpt); - } - -+ pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):"); - synchronized (mMutex) { -- pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):"); - for (ManagedServiceInfo info : mServices) { - if (filter != null && !filter.matches(info.component)) continue; - pw.println(" " + info.component -@@ -390,15 +386,10 @@ public void dump(PrintWriter pw, DumpFilter filter) { - } - } - -- synchronized (mSnoozing) { -- pw.println(" Snoozed " + getCaption() + "s (" -- + mSnoozing.size() + "):"); -- for (int i = 0; i < mSnoozing.size(); i++) { -- pw.println(" User: " + mSnoozing.keyAt(i)); -- for (ComponentName name : mSnoozing.valuesAt(i)) { -- pw.println(" " + name.flattenToShortString()); -- } -- } -+ pw.println(" Snoozed " + getCaption() + "s (" + -+ mSnoozingForCurrentProfiles.size() + "):"); -+ for (ComponentName name : mSnoozingForCurrentProfiles) { -+ pw.println(" " + name.flattenToShortString()); - } - } - -@@ -440,16 +431,8 @@ public void dump(ProtoOutputStream proto, DumpFilter filter) { - } - } - -- synchronized (mSnoozing) { -- for (int i = 0; i < mSnoozing.size(); i++) { -- long token = proto.start(ManagedServicesProto.SNOOZED); -- proto.write(ManagedServicesProto.SnoozedServices.USER_ID, -- mSnoozing.keyAt(i)); -- for (ComponentName name : mSnoozing.valuesAt(i)) { -- name.dumpDebug(proto, ManagedServicesProto.SnoozedServices.SNOOZED); -- } -- proto.end(token); -- } -+ for (ComponentName name : mSnoozingForCurrentProfiles) { -+ name.dumpDebug(proto, ManagedServicesProto.SNOOZED); - } - } - -@@ -918,6 +901,23 @@ protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) - return false; - } - -+ protected boolean isPackageOrComponentAllowedWithPermission(ComponentName component, -+ int userId) { -+ if (!(isPackageOrComponentAllowed(component.flattenToString(), userId) -+ || isPackageOrComponentAllowed(component.getPackageName(), userId))) { -+ return false; -+ } -+ return componentHasBindPermission(component, userId); -+ } -+ -+ private boolean componentHasBindPermission(ComponentName component, int userId) { -+ ServiceInfo info = getServiceInfo(component, userId); -+ if (info == null) { -+ return false; -+ } -+ return mConfig.bindPermission.equals(info.permission); -+ } -+ - boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) { - synchronized (mApproved) { - ArraySet services = mUserSetServices.get(userId); -@@ -975,6 +975,7 @@ public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] u - for (int uid : uidList) { - if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) { - anyServicesInvolved = true; -+ trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid)); - } - } - } -@@ -992,9 +993,6 @@ public void onUserRemoved(int user) { - synchronized (mApproved) { - mApproved.remove(user); - } -- synchronized (mSnoozing) { -- mSnoozing.remove(user); -- } - rebindServices(true, user); - } - -@@ -1014,12 +1012,10 @@ private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) { - return null; - } - final IBinder token = service.asBinder(); -- synchronized (mMutex) { -- final int nServices = mServices.size(); -- for (int i = 0; i < nServices; i++) { -- final ManagedServiceInfo info = mServices.get(i); -- if (info.service.asBinder() == token) return info; -- } -+ final int N = mServices.size(); -+ for (int i = 0; i < N; i++) { -+ final ManagedServiceInfo info = mServices.get(i); -+ if (info.service.asBinder() == token) return info; - } - return null; - } -@@ -1094,17 +1090,15 @@ protected void registerGuestService(ManagedServiceInfo guest) { - } - - protected void setComponentState(ComponentName component, int userId, boolean enabled) { -- synchronized (mSnoozing) { -- boolean previous = !mSnoozing.contains(userId, component); -- if (previous == enabled) { -- return; -- } -+ boolean previous = !mSnoozingForCurrentProfiles.contains(component); -+ if (previous == enabled) { -+ return; -+ } - -- if (enabled) { -- mSnoozing.remove(userId, component); -- } else { -- mSnoozing.add(userId, component); -- } -+ if (enabled) { -+ mSnoozingForCurrentProfiles.remove(component); -+ } else { -+ mSnoozingForCurrentProfiles.add(component); - } - - // State changed -@@ -1113,8 +1107,7 @@ protected void setComponentState(ComponentName component, int userId, boolean en - - synchronized (mMutex) { - if (enabled) { -- if (isPackageOrComponentAllowed(component.flattenToString(), userId) -- || isPackageOrComponentAllowed(component.getPackageName(), userId)) { -+ if (isPackageOrComponentAllowedWithPermission(component, userId)) { - registerServiceLocked(component, userId); - } else { - Slog.d(TAG, component + " no longer has permission to be bound"); -@@ -1252,6 +1245,33 @@ private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, S - return removed; - } - -+ private void trimApprovedListsForInvalidServices(String packageName, int userId) { -+ synchronized (mApproved) { -+ final ArrayMap> approvedByType = mApproved.get(userId); -+ if (approvedByType == null) { -+ return; -+ } -+ for (int i = 0; i < approvedByType.size(); i++) { -+ final ArraySet approved = approvedByType.valueAt(i); -+ for (int j = approved.size() - 1; j >= 0; j--) { -+ final String approvedPackageOrComponent = approved.valueAt(j); -+ if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) { -+ final ComponentName component = ComponentName.unflattenFromString( -+ approvedPackageOrComponent); -+ if (component != null && !componentHasBindPermission(component, userId)) { -+ approved.removeAt(j); -+ if (DEBUG) { -+ Slog.v(TAG, "Removing " + approvedPackageOrComponent -+ + " from approved list; no bind permission found " -+ + mConfig.bindPermission); -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ - protected String getPackageName(String packageOrComponent) { - final ComponentName component = ComponentName.unflattenFromString(packageOrComponent); - if (component != null) { -@@ -1317,10 +1337,7 @@ protected void populateComponentsToBind(SparseArray> componen - } - - final Set add = new HashSet<>(userComponents); -- ArraySet snoozed = mSnoozing.get(userId); -- if (snoozed != null) { -- add.removeAll(snoozed); -- } -+ add.removeAll(mSnoozingForCurrentProfiles); - - componentsToBind.put(userId, add); - -@@ -1438,28 +1455,20 @@ private void bindToServices(SparseArray> componentsToBind) { - final int userId = componentsToBind.keyAt(i); - final Set add = componentsToBind.get(userId); - for (ComponentName component : add) { -- try { -- ServiceInfo info = mPm.getServiceInfo(component, -- PackageManager.GET_META_DATA -- | PackageManager.MATCH_DIRECT_BOOT_AWARE -- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, -- userId); -- if (info == null) { -- Slog.w(TAG, "Not binding " + getCaption() + " service " + component -- + ": service not found"); -- continue; -- } -- if (!mConfig.bindPermission.equals(info.permission)) { -- Slog.w(TAG, "Not binding " + getCaption() + " service " + component -- + ": it does not require the permission " + mConfig.bindPermission); -- continue; -- } -- Slog.v(TAG, -- "enabling " + getCaption() + " for " + userId + ": " + component); -- registerService(info, userId); -- } catch (RemoteException e) { -- e.rethrowFromSystemServer(); -+ ServiceInfo info = getServiceInfo(component, userId); -+ if (info == null) { -+ Slog.w(TAG, "Not binding " + getCaption() + " service " + component -+ + ": service not found"); -+ continue; - } -+ if (!mConfig.bindPermission.equals(info.permission)) { -+ Slog.w(TAG, "Not binding " + getCaption() + " service " + component -+ + ": it does not require the permission " + mConfig.bindPermission); -+ continue; -+ } -+ Slog.v(TAG, -+ "enabling " + getCaption() + " for " + userId + ": " + component); -+ registerService(info, userId); - } - } - } -@@ -1484,8 +1493,7 @@ void registerService(final ComponentName cn, final int userId) { - void reregisterService(final ComponentName cn, final int userId) { - // If rebinding a package that died, ensure it still has permission - // after the rebind delay -- if (isPackageOrComponentAllowed(cn.getPackageName(), userId) -- || isPackageOrComponentAllowed(cn.flattenToString(), userId)) { -+ if (isPackageOrComponentAllowedWithPermission(cn, userId)) { - registerService(cn, userId); - } - } -@@ -1499,12 +1507,10 @@ public void registerSystemService(final ComponentName name, final int userid) { - } - } - -- @GuardedBy("mMutex") - private void registerServiceLocked(final ComponentName name, final int userid) { - registerServiceLocked(name, userid, false /* isSystem */); - } - -- @GuardedBy("mMutex") - private void registerServiceLocked(final ComponentName name, final int userid, - final boolean isSystem) { - if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid); -@@ -1590,9 +1596,12 @@ public void onBindingDied(ComponentName name) { - unbindService(this, name, userid); - if (!mServicesRebinding.contains(servicesBindingTag)) { - mServicesRebinding.add(servicesBindingTag); -- mHandler.postDelayed(() -> -- reregisterService(name, userid), -- ON_BINDING_DIED_REBIND_DELAY_MS); -+ mHandler.postDelayed(new Runnable() { -+ @Override -+ public void run() { -+ reregisterService(name, userid); -+ } -+ }, ON_BINDING_DIED_REBIND_DELAY_MS); - } else { - Slog.v(TAG, getCaption() + " not rebinding in user " + userid - + " as a previous rebind attempt was made: " + name); -@@ -1635,7 +1644,6 @@ private void unregisterService(ComponentName name, int userid) { - } - } - -- @GuardedBy("mMutex") - private void unregisterServiceLocked(ComponentName name, int userid) { - final int N = mServices.size(); - for (int i = N - 1; i >= 0; i--) { -@@ -1670,7 +1678,6 @@ private ManagedServiceInfo removeServiceImpl(IInterface service, final int useri - return serviceInfo; - } - -- @GuardedBy("mMutex") - private ManagedServiceInfo removeServiceLocked(int i) { - final ManagedServiceInfo info = mServices.remove(i); - onServiceRemovedLocked(info); -@@ -1724,6 +1731,19 @@ private void unbindService(ServiceConnection connection, ComponentName component - } - } - -+ private ServiceInfo getServiceInfo(ComponentName component, int userId) { -+ try { -+ return mPm.getServiceInfo(component, -+ PackageManager.GET_META_DATA -+ | PackageManager.MATCH_DIRECT_BOOT_AWARE -+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, -+ userId); -+ } catch (RemoteException e) { -+ e.rethrowFromSystemServer(); -+ } -+ return null; -+ } -+ - public class ManagedServiceInfo implements IBinder.DeathRecipient { - public IInterface service; - public ComponentName component; -@@ -1823,7 +1843,7 @@ public boolean isEnabledForCurrentProfiles() { - * from receiving events from the profile. - */ - public boolean isPermittedForProfile(int userId) { -- if (!mUserProfiles.isProfileUser(userId)) { -+ if (!mUserProfiles.isManagedProfile(userId)) { - return true; - } - DevicePolicyManager dpm = -@@ -1899,6 +1919,13 @@ public boolean isCurrentProfile(int userId) { - } - } - -+ public boolean isManagedProfile(int userId) { -+ synchronized (mCurrentProfiles) { -+ UserInfo user = mCurrentProfiles.get(userId); -+ return user != null && user.isManagedProfile(); -+ } -+ } -+ - public boolean isProfileUser(int userId) { - synchronized (mCurrentProfiles) { - UserInfo user = mCurrentProfiles.get(userId); -diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java -index 8b1384ed894f..7c7bb509ebb4 100644 ---- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java -+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java -@@ -33,8 +33,10 @@ - import static org.mockito.Matchers.anyInt; - import static org.mockito.Matchers.anyLong; - import static org.mockito.Matchers.eq; -+import static org.mockito.Mockito.doReturn; - import static org.mockito.Mockito.mock; - import static org.mockito.Mockito.never; -+import static org.mockito.Mockito.spy; - import static org.mockito.Mockito.times; - import static org.mockito.Mockito.verify; - import static org.mockito.Mockito.when; -@@ -1117,6 +1119,58 @@ public void testUpgradeAppBindsNewServices() throws Exception { - } - } - -+ @Test -+ public void testUpgradeAppNoPermissionNoRebind() throws Exception { -+ Context context = spy(getContext()); -+ doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any()); -+ -+ ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, -+ mIpm, -+ APPROVAL_BY_COMPONENT); -+ -+ List packages = new ArrayList<>(); -+ packages.add("package"); -+ addExpectedServices(service, packages, 0); -+ -+ final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1"); -+ final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2"); -+ -+ // Both components are approved initially -+ mExpectedPrimaryComponentNames.clear(); -+ mExpectedPrimaryPackages.clear(); -+ mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2"); -+ mExpectedSecondaryComponentNames.clear(); -+ mExpectedSecondaryPackages.clear(); -+ -+ loadXml(service); -+ -+ //Component package/C1 loses bind permission -+ when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer( -+ (Answer) invocation -> { -+ ComponentName invocationCn = invocation.getArgument(0); -+ if (invocationCn != null) { -+ ServiceInfo serviceInfo = new ServiceInfo(); -+ serviceInfo.packageName = invocationCn.getPackageName(); -+ serviceInfo.name = invocationCn.getClassName(); -+ if (invocationCn.equals(unapprovedComponent)) { -+ serviceInfo.permission = "none"; -+ } else { -+ serviceInfo.permission = service.getConfig().bindPermission; -+ } -+ serviceInfo.metaData = null; -+ return serviceInfo; -+ } -+ return null; -+ } -+ ); -+ -+ // Trigger package update -+ service.onPackagesChanged(false, new String[]{"package"}, new int[]{0}); -+ -+ assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent)); -+ assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent)); -+ } -+ - @Test - public void testSetPackageOrComponentEnabled() throws Exception { - for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-05.patch b/Patches/LineageOS-20.0/ASB-2024-06/fwb-05.patch deleted file mode 100644 index 53b6e0b1..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-05.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 091715c8307fed95ba63870f0c54e74208a78332 Mon Sep 17 00:00:00 2001 -From: Lokesh Kumar Goel -Date: Tue, 27 Feb 2024 23:05:05 +0000 -Subject: [PATCH] Fix vulnerability in AttributionSource due to incorrect - Binder call - -AttributionSource uses Binder.getCallingUid to verify the UID of the -caller from another process. However, getCallingUid does not always -behave as expected. If the AttributionSource is unparceled outside a -transaction thread, which is quite possible, getCallingUid will return -the UID of the current process instead. If this is a system process, -the UID check gets bypassed entirely, meaning any uid can be provided. - -This patch fixes the vulnerability by emptying out the state of the -AttributionSource, so that the service checking its credentials will -fail to give permission to the app. - -Bug: 267231571 -Test: v2/android-virtual-infra/test_mapping/presubmit-avd -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5d79e535b9a802680062545e15fc1faaf779c0bf) -Merged-In: I3f228064fbd62e1c907f1ebe870cb61102f788f0 -Change-Id: I3f228064fbd62e1c907f1ebe870cb61102f788f0 ---- - .../android/content/AttributionSource.java | 20 ++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java -index 3f2fa2188d24..16b18c85e790 100644 ---- a/core/java/android/content/AttributionSource.java -+++ b/core/java/android/content/AttributionSource.java -@@ -31,6 +31,7 @@ - import android.os.Process; - import android.permission.PermissionManager; - import android.util.ArraySet; -+import android.util.Log; - - import com.android.internal.annotations.Immutable; - -@@ -87,6 +88,8 @@ - */ - @Immutable - public final class AttributionSource implements Parcelable { -+ private static final String TAG = "AttributionSource"; -+ - private static final String DESCRIPTOR = "android.content.AttributionSource"; - - private static final Binder sDefaultToken = new Binder(DESCRIPTOR); -@@ -154,9 +157,20 @@ public AttributionSource(@NonNull AttributionSource current, @Nullable Attributi - AttributionSource(@NonNull Parcel in) { - this(AttributionSourceState.CREATOR.createFromParcel(in)); - -- // Since we just unpacked this object as part of it transiting a Binder -- // call, this is the perfect time to enforce that its UID and PID can be trusted -- enforceCallingUidAndPid(); -+ if (!Binder.isDirectlyHandlingTransaction()) { -+ Log.e(TAG, "Unable to verify calling UID #" + mAttributionSourceState.uid + " PID #" -+ + mAttributionSourceState.pid + " when not handling Binder transaction; " -+ + "clearing."); -+ mAttributionSourceState.pid = -1; -+ mAttributionSourceState.uid = -1; -+ mAttributionSourceState.packageName = null; -+ mAttributionSourceState.attributionTag = null; -+ mAttributionSourceState.next = null; -+ } else { -+ // Since we just unpacked this object as part of it transiting a Binder -+ // call, this is the perfect time to enforce that its UID and PID can be trusted -+ enforceCallingUidAndPid(); -+ } - } - - /** @hide */ diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-11.patch b/Patches/LineageOS-20.0/ASB-2024-06/fwb-11.patch deleted file mode 100644 index 9b2fe592..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-11.patch +++ /dev/null @@ -1,912 +0,0 @@ -From d444b292de11e14d41a5ce1897cd32360d065671 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= -Date: Fri, 22 Mar 2024 14:26:23 +0100 -Subject: [PATCH] Resolve message/conversation image Uris with the correct user - id - -Bug: 317503801 -Test: atest ExpandableNotificationRowTest -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:83975c515773d345c64cadac1cd639ae5c4a8397) -Merged-In: I11c5b39f2d9d8f0788acab43640a6d4abcd5a179 -Change-Id: I11c5b39f2d9d8f0788acab43640a6d4abcd5a179 ---- - .../row/ExpandableNotificationRow.java | 13 +- - .../row/NotificationInlineImageResolver.java | 7 +- - .../row/ExpandableNotificationRowTest.java | 554 +++++------------- - .../systemui/SysuiTestableContext.java | 22 + - 4 files changed, 194 insertions(+), 402 deletions(-) - -diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java -index 11598e0c1f51..1cec84a5b02d 100644 ---- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java -+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java -@@ -45,6 +45,7 @@ - import android.os.RemoteException; - import android.os.ServiceManager; - import android.os.Trace; -+import android.os.UserHandle; - import android.service.notification.StatusBarNotification; - import android.util.ArraySet; - import android.util.AttributeSet; -@@ -1669,8 +1670,6 @@ void logSkipAttachingKeepInParentChild( - */ - public ExpandableNotificationRow(Context context, AttributeSet attrs) { - super(context, attrs); -- mImageResolver = new NotificationInlineImageResolver(context, -- new NotificationInlineImageCache()); - float radius = getResources().getDimension(R.dimen.notification_corner_radius_small); - mSmallRoundness = radius / getMaxRadius(); - initDimens(); -@@ -1706,6 +1705,8 @@ public void initialize( - FeatureFlags featureFlags, - IStatusBarService statusBarService) { - mEntry = entry; -+ mImageResolver = new NotificationInlineImageResolver(userContextForEntry(mContext, entry), -+ new NotificationInlineImageCache()); - mAppName = appName; - if (mMenuRow == null) { - mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier); -@@ -1743,6 +1744,14 @@ public void initialize( - mFeatureFlags = featureFlags; - } - -+ private static Context userContextForEntry(Context base, NotificationEntry entry) { -+ if (base.getUserId() == entry.getSbn().getNormalizedUserId()) { -+ return base; -+ } -+ return base.createContextAsUser( -+ UserHandle.of(entry.getSbn().getNormalizedUserId()), /* flags= */ 0); -+ } -+ - private void initDimens() { - mMaxSmallHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext, - R.dimen.notification_min_height_legacy); -diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java -index c620f448b3b7..3e932aa616b8 100644 ---- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java -+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java -@@ -66,7 +66,7 @@ public class NotificationInlineImageResolver implements ImageResolver { - * @param imageCache The implementation of internal cache. - */ - public NotificationInlineImageResolver(Context context, ImageCache imageCache) { -- mContext = context.getApplicationContext(); -+ mContext = context; - mImageCache = imageCache; - - if (mImageCache != null) { -@@ -76,6 +76,11 @@ public NotificationInlineImageResolver(Context context, ImageCache imageCache) { - updateMaxImageSizes(); - } - -+ @VisibleForTesting -+ public Context getContext() { -+ return mContext; -+ } -+ - /** - * Check if this resolver has its internal cache implementation. - * @return True if has its internal cache, false otherwise. -diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java -index 957b0f10ec1f..67aae77eee36 100644 ---- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java -+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java -@@ -23,11 +23,14 @@ - import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; - import static com.android.systemui.statusbar.NotificationEntryHelper.modifySbn; - import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; -+import static com.android.systemui.statusbar.notification.row.NotificationTestHelper.PKG; -+import static com.android.systemui.statusbar.notification.row.NotificationTestHelper.USER_HANDLE; - - import static com.google.common.truth.Truth.assertThat; - - import static org.junit.Assert.assertEquals; - import static org.junit.Assert.assertFalse; -+import static org.junit.Assert.assertNull; - import static org.junit.Assert.assertTrue; - import static org.mockito.ArgumentMatchers.any; - import static org.mockito.ArgumentMatchers.anyInt; -@@ -38,37 +41,29 @@ - import static org.mockito.Mockito.spy; - import static org.mockito.Mockito.times; - import static org.mockito.Mockito.verify; --import static org.mockito.Mockito.verifyNoMoreInteractions; - import static org.mockito.Mockito.when; - - import android.app.Notification; - import android.app.NotificationChannel; --import android.graphics.Color; --import android.graphics.drawable.AnimatedVectorDrawable; --import android.graphics.drawable.AnimationDrawable; --import android.graphics.drawable.Drawable; -+import android.content.Context; -+import android.os.UserHandle; - import android.testing.AndroidTestingRunner; - import android.testing.TestableLooper; - import android.testing.TestableLooper.RunWithLooper; - import android.util.DisplayMetrics; - import android.view.View; --import android.widget.ImageView; - - import androidx.test.filters.SmallTest; - - import com.android.internal.R; --import com.android.internal.widget.CachingIconView; - import com.android.systemui.SysuiTestCase; --import com.android.systemui.flags.FakeFeatureFlags; --import com.android.systemui.flags.Flags; -+import com.android.systemui.SysuiTestableContext; - import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; - import com.android.systemui.plugins.statusbar.StatusBarStateController; - import com.android.systemui.statusbar.notification.AboveShelfChangedListener; - import com.android.systemui.statusbar.notification.FeedbackIcon; --import com.android.systemui.statusbar.notification.SourceType; --import com.android.systemui.statusbar.notification.collection.NotificationEntry; - import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener; --import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; -+import com.android.systemui.statusbar.notification.collection.NotificationEntry; - import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer; - - import org.junit.Assert; -@@ -80,16 +75,20 @@ - import org.mockito.junit.MockitoJUnit; - import org.mockito.junit.MockitoRule; - --import java.util.Arrays; - import java.util.List; --import java.util.function.Consumer; - - @SmallTest - @RunWith(AndroidTestingRunner.class) - @RunWithLooper - public class ExpandableNotificationRowTest extends SysuiTestCase { - -+ private ExpandableNotificationRow mGroupRow; -+ private ExpandableNotificationRow mNotifRow; -+ private ExpandableNotificationRow mPublicRow; -+ - private NotificationTestHelper mNotificationTestHelper; -+ boolean mHeadsUpAnimatingAway = false; -+ - @Rule public MockitoRule mockito = MockitoJUnit.rule(); - - @Before -@@ -100,109 +99,87 @@ public void setUp() throws Exception { - mDependency, - TestableLooper.get(this)); - mNotificationTestHelper.setDefaultInflationFlags(FLAG_CONTENT_VIEW_ALL); -+ // create a standard private notification row -+ Notification normalNotif = mNotificationTestHelper.createNotification(); -+ normalNotif.publicVersion = null; -+ mNotifRow = mNotificationTestHelper.createRow(normalNotif); -+ // create a notification row whose public version is identical -+ Notification publicNotif = mNotificationTestHelper.createNotification(); -+ publicNotif.publicVersion = mNotificationTestHelper.createNotification(); -+ mPublicRow = mNotificationTestHelper.createRow(publicNotif); -+ // create a group row -+ mGroupRow = mNotificationTestHelper.createGroup(); -+ mGroupRow.setHeadsUpAnimatingAwayListener( -+ animatingAway -> mHeadsUpAnimatingAway = animatingAway); - -- FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags(); -- fakeFeatureFlags.set(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE, true); -- fakeFeatureFlags.set(Flags.SENSITIVE_REVEAL_ANIM, false); -- mNotificationTestHelper.setFeatureFlags(fakeFeatureFlags); -- } -- -- @Test -- public void testUpdateBackgroundColors_isRecursive() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- group.setTintColor(Color.RED); -- group.getChildNotificationAt(0).setTintColor(Color.GREEN); -- group.getChildNotificationAt(1).setTintColor(Color.BLUE); -- -- assertThat(group.getCurrentBackgroundTint()).isEqualTo(Color.RED); -- assertThat(group.getChildNotificationAt(0).getCurrentBackgroundTint()) -- .isEqualTo(Color.GREEN); -- assertThat(group.getChildNotificationAt(1).getCurrentBackgroundTint()) -- .isEqualTo(Color.BLUE); -- -- group.updateBackgroundColors(); -- -- int resetTint = group.getCurrentBackgroundTint(); -- assertThat(resetTint).isNotEqualTo(Color.RED); -- assertThat(group.getChildNotificationAt(0).getCurrentBackgroundTint()) -- .isEqualTo(resetTint); -- assertThat(group.getChildNotificationAt(1).getCurrentBackgroundTint()) -- .isEqualTo(resetTint); - } - - @Test -- public void testSetSensitiveOnNotifRowNotifiesOfHeightChange() throws Exception { -+ public void testSetSensitiveOnNotifRowNotifiesOfHeightChange() throws InterruptedException { - // GIVEN a sensitive notification row that's currently redacted -- ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -- measureAndLayout(row); -- row.setHideSensitiveForIntrinsicHeight(true); -- row.setSensitive(true, true); -- assertThat(row.getShowingLayout()).isSameInstanceAs(row.getPublicLayout()); -- assertThat(row.getIntrinsicHeight()).isGreaterThan(0); -+ measureAndLayout(mNotifRow); -+ mNotifRow.setHideSensitiveForIntrinsicHeight(true); -+ mNotifRow.setSensitive(true, true); -+ assertThat(mNotifRow.getShowingLayout()).isSameInstanceAs(mNotifRow.getPublicLayout()); -+ assertThat(mNotifRow.getIntrinsicHeight()).isGreaterThan(0); - - // GIVEN that the row has a height change listener - OnHeightChangedListener listener = mock(OnHeightChangedListener.class); -- row.setOnHeightChangedListener(listener); -+ mNotifRow.setOnHeightChangedListener(listener); - - // WHEN the row is set to no longer be sensitive -- row.setSensitive(false, true); -+ mNotifRow.setSensitive(false, true); - - // VERIFY that the height change listener is invoked -- assertThat(row.getShowingLayout()).isSameInstanceAs(row.getPrivateLayout()); -- assertThat(row.getIntrinsicHeight()).isGreaterThan(0); -- verify(listener).onHeightChanged(eq(row), eq(false)); -+ assertThat(mNotifRow.getShowingLayout()).isSameInstanceAs(mNotifRow.getPrivateLayout()); -+ assertThat(mNotifRow.getIntrinsicHeight()).isGreaterThan(0); -+ verify(listener).onHeightChanged(eq(mNotifRow), eq(false)); - } - - @Test -- public void testSetSensitiveOnGroupRowNotifiesOfHeightChange() throws Exception { -+ public void testSetSensitiveOnGroupRowNotifiesOfHeightChange() { - // GIVEN a sensitive group row that's currently redacted -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- measureAndLayout(group); -- group.setHideSensitiveForIntrinsicHeight(true); -- group.setSensitive(true, true); -- assertThat(group.getShowingLayout()).isSameInstanceAs(group.getPublicLayout()); -- assertThat(group.getIntrinsicHeight()).isGreaterThan(0); -+ measureAndLayout(mGroupRow); -+ mGroupRow.setHideSensitiveForIntrinsicHeight(true); -+ mGroupRow.setSensitive(true, true); -+ assertThat(mGroupRow.getShowingLayout()).isSameInstanceAs(mGroupRow.getPublicLayout()); -+ assertThat(mGroupRow.getIntrinsicHeight()).isGreaterThan(0); - - // GIVEN that the row has a height change listener - OnHeightChangedListener listener = mock(OnHeightChangedListener.class); -- group.setOnHeightChangedListener(listener); -+ mGroupRow.setOnHeightChangedListener(listener); - - // WHEN the row is set to no longer be sensitive -- group.setSensitive(false, true); -+ mGroupRow.setSensitive(false, true); - - // VERIFY that the height change listener is invoked -- assertThat(group.getShowingLayout()).isSameInstanceAs(group.getPrivateLayout()); -- assertThat(group.getIntrinsicHeight()).isGreaterThan(0); -- verify(listener).onHeightChanged(eq(group), eq(false)); -+ assertThat(mGroupRow.getShowingLayout()).isSameInstanceAs(mGroupRow.getPrivateLayout()); -+ assertThat(mGroupRow.getIntrinsicHeight()).isGreaterThan(0); -+ verify(listener).onHeightChanged(eq(mGroupRow), eq(false)); - } - - @Test -- public void testSetSensitiveOnPublicRowDoesNotNotifyOfHeightChange() throws Exception { -- // create a notification row whose public version is identical -- Notification publicNotif = mNotificationTestHelper.createNotification(); -- publicNotif.publicVersion = mNotificationTestHelper.createNotification(); -- ExpandableNotificationRow publicRow = mNotificationTestHelper.createRow(publicNotif); -- -+ public void testSetSensitiveOnPublicRowDoesNotNotifyOfHeightChange() { - // GIVEN a sensitive public row that's currently redacted -- measureAndLayout(publicRow); -- publicRow.setHideSensitiveForIntrinsicHeight(true); -- publicRow.setSensitive(true, true); -- assertThat(publicRow.getShowingLayout()).isSameInstanceAs(publicRow.getPublicLayout()); -- assertThat(publicRow.getIntrinsicHeight()).isGreaterThan(0); -+ measureAndLayout(mPublicRow); -+ mPublicRow.setHideSensitiveForIntrinsicHeight(true); -+ mPublicRow.setSensitive(true, true); -+ assertThat(mPublicRow.getShowingLayout()).isSameInstanceAs(mPublicRow.getPublicLayout()); -+ assertThat(mPublicRow.getIntrinsicHeight()).isGreaterThan(0); - - // GIVEN that the row has a height change listener - OnHeightChangedListener listener = mock(OnHeightChangedListener.class); -- publicRow.setOnHeightChangedListener(listener); -+ mPublicRow.setOnHeightChangedListener(listener); - - // WHEN the row is set to no longer be sensitive -- publicRow.setSensitive(false, true); -+ mPublicRow.setSensitive(false, true); - - // VERIFY that the height change listener is not invoked, because the height didn't change -- assertThat(publicRow.getShowingLayout()).isSameInstanceAs(publicRow.getPrivateLayout()); -- assertThat(publicRow.getIntrinsicHeight()).isGreaterThan(0); -- assertThat(publicRow.getPrivateLayout().getMinHeight()) -- .isEqualTo(publicRow.getPublicLayout().getMinHeight()); -- verify(listener, never()).onHeightChanged(eq(publicRow), eq(false)); -+ assertThat(mPublicRow.getShowingLayout()).isSameInstanceAs(mPublicRow.getPrivateLayout()); -+ assertThat(mPublicRow.getIntrinsicHeight()).isGreaterThan(0); -+ assertThat(mPublicRow.getPrivateLayout().getMinHeight()) -+ .isEqualTo(mPublicRow.getPublicLayout().getMinHeight()); -+ verify(listener, never()).onHeightChanged(eq(mPublicRow), eq(false)); - } - - private void measureAndLayout(ExpandableNotificationRow row) { -@@ -219,44 +196,39 @@ private void measureAndLayout(ExpandableNotificationRow row) { - } - - @Test -- public void testGroupSummaryNotShowingIconWhenPublic() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- group.setSensitive(true, true); -- group.setHideSensitiveForIntrinsicHeight(true); -- assertTrue(group.isSummaryWithChildren()); -- assertFalse(group.isShowingIcon()); -+ public void testGroupSummaryNotShowingIconWhenPublic() { -+ mGroupRow.setSensitive(true, true); -+ mGroupRow.setHideSensitiveForIntrinsicHeight(true); -+ assertTrue(mGroupRow.isSummaryWithChildren()); -+ assertFalse(mGroupRow.isShowingIcon()); - } - - @Test -- public void testNotificationHeaderVisibleWhenAnimating() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- group.setSensitive(true, true); -- group.setHideSensitive(true, false, 0, 0); -- group.setHideSensitive(false, true, 0, 0); -- assertEquals(View.VISIBLE, group.getChildrenContainer().getVisibleWrapper() -+ public void testNotificationHeaderVisibleWhenAnimating() { -+ mGroupRow.setSensitive(true, true); -+ mGroupRow.setHideSensitive(true, false, 0, 0); -+ mGroupRow.setHideSensitive(false, true, 0, 0); -+ assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper() - .getNotificationHeader().getVisibility()); - } - - @Test -- public void testUserLockedResetEvenWhenNoChildren() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- group.setUserLocked(true); -- group.setUserLocked(false); -+ public void testUserLockedResetEvenWhenNoChildren() { -+ mGroupRow.setUserLocked(true); -+ mGroupRow.removeAllChildren(); -+ mGroupRow.setUserLocked(false); - assertFalse("The childrencontainer should not be userlocked but is, the state " -- + "seems out of sync.", group.getChildrenContainer().isUserLocked()); -+ + "seems out of sync.", mGroupRow.getChildrenContainer().isUserLocked()); - } - - @Test -- public void testReinflatedOnDensityChange() throws Exception { -- ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -+ public void testReinflatedOnDensityChange() { -+ mGroupRow.setUserLocked(true); -+ mGroupRow.removeAllChildren(); -+ mGroupRow.setUserLocked(false); - NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); -- row.setChildrenContainer(mockContainer); -- -- row.onDensityOrFontScaleChanged(); -- -+ mGroupRow.setChildrenContainer(mockContainer); -+ mGroupRow.onDensityOrFontScaleChanged(); - verify(mockContainer).reInflateViews(any(), any()); - } - -@@ -269,6 +241,17 @@ public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception { - verify(row).updateShelfIconColor(); - } - -+ @Test -+ public void setNeedsRedactionFreesViewWhenFalse() throws Exception { -+ ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL); -+ row.setNeedsRedaction(true); -+ row.getPublicLayout().setVisibility(View.GONE); -+ -+ row.setNeedsRedaction(false); -+ TestableLooper.get(this).processAllMessages(); -+ assertNull(row.getPublicLayout().getContractedChild()); -+ } -+ - @Test - public void testAboveShelfChangedListenerCalled() throws Exception { - ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -@@ -298,73 +281,64 @@ public void testAboveShelfChangedListenerCalledHeadsUpGoingAway() throws Excepti - @Test - public void testAboveShelfChangedListenerCalledWhenGoingBelow() throws Exception { - ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -+ row.setHeadsUp(true); - AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class); - row.setAboveShelfChangedListener(listener); -- Mockito.reset(listener); -- row.setHeadsUp(true); - row.setAboveShelf(false); - verify(listener).onAboveShelfStateChanged(false); - } - - @Test - public void testClickSound() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- assertTrue("Should play sounds by default.", group.isSoundEffectsEnabled()); -+ assertTrue("Should play sounds by default.", mGroupRow.isSoundEffectsEnabled()); - StatusBarStateController mock = mNotificationTestHelper.getStatusBarStateController(); - when(mock.isDozing()).thenReturn(true); -- group.setSecureStateProvider(()-> false); -+ mGroupRow.setSecureStateProvider(()-> false); - assertFalse("Shouldn't play sounds when dark and trusted.", -- group.isSoundEffectsEnabled()); -- group.setSecureStateProvider(()-> true); -+ mGroupRow.isSoundEffectsEnabled()); -+ mGroupRow.setSecureStateProvider(()-> true); - assertTrue("Should always play sounds when not trusted.", -- group.isSoundEffectsEnabled()); -+ mGroupRow.isSoundEffectsEnabled()); - } - - @Test -- public void testSetDismissed_longPressListenerRemoved() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -+ public void testSetDismissed_longPressListenerRemoved() { - ExpandableNotificationRow.LongPressListener listener = - mock(ExpandableNotificationRow.LongPressListener.class); -- group.setLongPressListener(listener); -- group.doLongClickCallback(0, 0); -- verify(listener, times(1)).onLongPress(eq(group), eq(0), eq(0), -+ mGroupRow.setLongPressListener(listener); -+ mGroupRow.doLongClickCallback(0,0); -+ verify(listener, times(1)).onLongPress(eq(mGroupRow), eq(0), eq(0), - any(NotificationMenuRowPlugin.MenuItem.class)); - reset(listener); - -- group.dismiss(true); -- group.doLongClickCallback(0, 0); -- verify(listener, times(0)).onLongPress(eq(group), eq(0), eq(0), -+ mGroupRow.dismiss(true); -+ mGroupRow.doLongClickCallback(0,0); -+ verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0), - any(NotificationMenuRowPlugin.MenuItem.class)); - } - - @Test -- public void testFeedback_noHeader() throws Exception { -- ExpandableNotificationRow groupRow = mNotificationTestHelper.createGroup(); -- -+ public void testFeedback_noHeader() { - // public notification is custom layout - no header -- groupRow.setSensitive(true, true); -- groupRow.setOnFeedbackClickListener(null); -- groupRow.setFeedbackIcon(null); -+ mGroupRow.setSensitive(true, true); -+ mGroupRow.setOnFeedbackClickListener(null); -+ mGroupRow.setFeedbackIcon(null); - } - - @Test -- public void testFeedback_header() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -+ public void testFeedback_header() { - NotificationContentView publicLayout = mock(NotificationContentView.class); -- group.setPublicLayout(publicLayout); -+ mGroupRow.setPublicLayout(publicLayout); - NotificationContentView privateLayout = mock(NotificationContentView.class); -- group.setPrivateLayout(privateLayout); -+ mGroupRow.setPrivateLayout(privateLayout); - NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); - when(mockContainer.getNotificationChildCount()).thenReturn(1); -- group.setChildrenContainer(mockContainer); -+ mGroupRow.setChildrenContainer(mockContainer); - - final boolean show = true; - final FeedbackIcon icon = new FeedbackIcon( - R.drawable.ic_feedback_alerted, R.string.notification_feedback_indicator_alerted); -- group.setFeedbackIcon(icon); -+ mGroupRow.setFeedbackIcon(icon); - - verify(mockContainer, times(1)).setFeedbackIcon(icon); - verify(privateLayout, times(1)).setFeedbackIcon(icon); -@@ -372,49 +346,43 @@ public void testFeedback_header() throws Exception { - } - - @Test -- public void testFeedbackOnClick() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -+ public void testFeedbackOnClick() { - ExpandableNotificationRow.CoordinateOnClickListener l = mock( - ExpandableNotificationRow.CoordinateOnClickListener.class); - View view = mock(View.class); - -- group.setOnFeedbackClickListener(l); -+ mGroupRow.setOnFeedbackClickListener(l); - -- group.getFeedbackOnClickListener().onClick(view); -+ mGroupRow.getFeedbackOnClickListener().onClick(view); - verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any()); - } - - @Test -- public void testHeadsUpAnimatingAwayListener() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- Consumer headsUpListener = mock(Consumer.class); -- AboveShelfChangedListener aboveShelfChangedListener = mock(AboveShelfChangedListener.class); -- group.setHeadsUpAnimatingAwayListener(headsUpListener); -- group.setAboveShelfChangedListener(aboveShelfChangedListener); -- -- group.setHeadsUpAnimatingAway(true); -- verify(headsUpListener).accept(true); -- verify(aboveShelfChangedListener).onAboveShelfStateChanged(true); -- -- group.setHeadsUpAnimatingAway(false); -- verify(headsUpListener).accept(false); -- verify(aboveShelfChangedListener).onAboveShelfStateChanged(false); -+ public void testHeadsUpAnimatingAwayListener() { -+ mGroupRow.setHeadsUpAnimatingAway(true); -+ Assert.assertEquals(true, mHeadsUpAnimatingAway); -+ mGroupRow.setHeadsUpAnimatingAway(false); -+ Assert.assertEquals(false, mHeadsUpAnimatingAway); - } - - @Test -- public void testGetNumUniqueChildren_defaultChannel() throws Exception { -- ExpandableNotificationRow groupRow = mNotificationTestHelper.createGroup(); -+ public void testIsBlockingHelperShowing_isCorrectlyUpdated() { -+ mGroupRow.setBlockingHelperShowing(true); -+ assertTrue(mGroupRow.isBlockingHelperShowing()); - -- assertEquals(1, groupRow.getNumUniqueChannels()); -+ mGroupRow.setBlockingHelperShowing(false); -+ assertFalse(mGroupRow.isBlockingHelperShowing()); - } - - @Test -- public void testGetNumUniqueChildren_multiChannel() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -+ public void testGetNumUniqueChildren_defaultChannel() { -+ assertEquals(1, mGroupRow.getNumUniqueChannels()); -+ } - -+ @Test -+ public void testGetNumUniqueChildren_multiChannel() { - List childRows = -- group.getChildrenContainer().getAttachedChildren(); -+ mGroupRow.getChildrenContainer().getAttachedChildren(); - // Give each child a unique channel id/name. - int i = 0; - for (ExpandableNotificationRow childRow : childRows) { -@@ -426,29 +394,25 @@ public void testGetNumUniqueChildren_multiChannel() throws Exception { - i++; - } - -- assertEquals(3, group.getNumUniqueChannels()); -+ assertEquals(3, mGroupRow.getNumUniqueChannels()); - } - - @Test - public void testIconScrollXAfterTranslationAndReset() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- group.setDismissUsingRowTranslationX(false); -- group.setTranslation(50); -- assertEquals(50, -group.getEntry().getIcons().getShelfIcon().getScrollX()); -+ mGroupRow.setDismissUsingRowTranslationX(false); -+ mGroupRow.setTranslation(50); -+ assertEquals(50, -mGroupRow.getEntry().getIcons().getShelfIcon().getScrollX()); - -- group.resetTranslation(); -- assertEquals(0, group.getEntry().getIcons().getShelfIcon().getScrollX()); -+ mGroupRow.resetTranslation(); -+ assertEquals(0, mGroupRow.getEntry().getIcons().getShelfIcon().getScrollX()); - } - - @Test -- public void testIsExpanded_userExpanded() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- -- group.setExpandable(true); -- Assert.assertFalse(group.isExpanded()); -- group.setUserExpanded(true); -- Assert.assertTrue(group.isExpanded()); -+ public void testIsExpanded_userExpanded() { -+ mGroupRow.setExpandable(true); -+ Assert.assertFalse(mGroupRow.isExpanded()); -+ mGroupRow.setUserExpanded(true); -+ Assert.assertTrue(mGroupRow.isExpanded()); - } - - @Test -@@ -492,230 +456,22 @@ public void testCannotDismissOngoing() throws Exception { - } - - @Test -- public void testAddChildNotification() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(0); -- ExpandableNotificationRow child = mNotificationTestHelper.createRow(); -+ public void imageResolver_sameNotificationUser_usesContext() throws Exception { -+ ExpandableNotificationRow row = mNotificationTestHelper.createRow(PKG, -+ USER_HANDLE.getUid(1234), USER_HANDLE); - -- group.addChildNotification(child); -- -- Assert.assertEquals(child, group.getChildNotificationAt(0)); -- Assert.assertEquals(group, child.getNotificationParent()); -- Assert.assertTrue(child.isChildInGroup()); -+ assertThat(row.getImageResolver().getContext()).isSameInstanceAs(mContext); - } - - @Test -- public void testAddChildNotification_childSkipped() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(0); -- ExpandableNotificationRow child = mNotificationTestHelper.createRow(); -- child.setKeepInParentForDismissAnimation(true); -- -- group.addChildNotification(child); -- -- Assert.assertTrue(group.getAttachedChildren().isEmpty()); -- Assert.assertNotEquals(group, child.getNotificationParent()); -- verify(mNotificationTestHelper.getMockLogger()).logSkipAttachingKeepInParentChild( -- /*child=*/ child.getEntry(), -- /*newParent=*/ group.getEntry() -- ); -- } -+ public void imageResolver_differentNotificationUser_createsUserContext() throws Exception { -+ UserHandle user = new UserHandle(33); -+ Context userContext = new SysuiTestableContext(mContext); -+ mContext.prepareCreateContextAsUser(user, userContext); - -- @Test -- public void testRemoveChildNotification() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(1); -- ExpandableNotificationRow child = group.getAttachedChildren().get(0); -- child.setKeepInParentForDismissAnimation(true); -- -- group.removeChildNotification(child); -+ ExpandableNotificationRow row = mNotificationTestHelper.createRow(PKG, -+ user.getUid(1234), user); - -- Assert.assertNull(child.getParent()); -- Assert.assertNull(child.getNotificationParent()); -- Assert.assertFalse(child.keepInParentForDismissAnimation()); -- verifyNoMoreInteractions(mNotificationTestHelper.getMockLogger()); -- } -- -- @Test -- public void testRemoveChildrenWithKeepInParent_removesChildWithKeepInParent() throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(1); -- ExpandableNotificationRow child = group.getAttachedChildren().get(0); -- child.setKeepInParentForDismissAnimation(true); -- -- group.removeChildrenWithKeepInParent(); -- -- Assert.assertNull(child.getParent()); -- Assert.assertNull(child.getNotificationParent()); -- Assert.assertFalse(child.keepInParentForDismissAnimation()); -- verify(mNotificationTestHelper.getMockLogger()).logKeepInParentChildDetached( -- /*child=*/ child.getEntry(), -- /*oldParent=*/ group.getEntry() -- ); -- } -- -- @Test -- public void testRemoveChildrenWithKeepInParent_skipsChildrenWithoutKeepInParent() -- throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(1); -- ExpandableNotificationRow child = group.getAttachedChildren().get(0); -- -- group.removeChildrenWithKeepInParent(); -- -- Assert.assertEquals(group, child.getNotificationParent()); -- Assert.assertFalse(child.keepInParentForDismissAnimation()); -- verify(mNotificationTestHelper.getMockLogger(), never()).logKeepInParentChildDetached( -- /*child=*/ any(), -- /*oldParent=*/ any() -- ); -- } -- -- @Test -- public void applyRoundnessAndInv_should_be_immediately_applied_on_childrenContainer_legacy() -- throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- group.useRoundnessSourceTypes(false); -- Assert.assertEquals(0f, group.getBottomRoundness(), 0.001f); -- Assert.assertEquals(0f, group.getChildrenContainer().getBottomRoundness(), 0.001f); -- -- group.requestBottomRoundness(1f, SourceType.from(""), false); -- -- Assert.assertEquals(1f, group.getBottomRoundness(), 0.001f); -- Assert.assertEquals(1f, group.getChildrenContainer().getBottomRoundness(), 0.001f); -- } -- -- @Test -- public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_childrenContainer() -- throws Exception { -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- group.useRoundnessSourceTypes(true); -- Assert.assertEquals(0f, group.getBottomRoundness(), 0.001f); -- Assert.assertEquals(0f, group.getChildrenContainer().getBottomRoundness(), 0.001f); -- -- group.requestBottomRoundness(1f, SourceType.from(""), false); -- -- Assert.assertEquals(1f, group.getBottomRoundness(), 0.001f); -- Assert.assertEquals(1f, group.getChildrenContainer().getBottomRoundness(), 0.001f); -- } -- -- @Test -- public void testSetContentAnimationRunning_Run() throws Exception { -- // Create views for the notification row. -- ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -- NotificationContentView publicLayout = mock(NotificationContentView.class); -- row.setPublicLayout(publicLayout); -- NotificationContentView privateLayout = mock(NotificationContentView.class); -- row.setPrivateLayout(privateLayout); -- -- row.setAnimationRunning(true); -- verify(publicLayout, times(1)).setContentAnimationRunning(true); -- verify(privateLayout, times(1)).setContentAnimationRunning(true); -- } -- -- @Test -- public void testSetContentAnimationRunning_Stop() throws Exception { -- // Create views for the notification row. -- ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -- NotificationContentView publicLayout = mock(NotificationContentView.class); -- row.setPublicLayout(publicLayout); -- NotificationContentView privateLayout = mock(NotificationContentView.class); -- row.setPrivateLayout(privateLayout); -- -- row.setAnimationRunning(false); -- verify(publicLayout, times(1)).setContentAnimationRunning(false); -- verify(privateLayout, times(1)).setContentAnimationRunning(false); -- } -- -- @Test -- public void testSetContentAnimationRunningInGroupChild_Run() throws Exception { -- // Creates parent views on groupRow. -- ExpandableNotificationRow groupRow = mNotificationTestHelper.createGroup(); -- NotificationContentView publicParentLayout = mock(NotificationContentView.class); -- groupRow.setPublicLayout(publicParentLayout); -- NotificationContentView privateParentLayout = mock(NotificationContentView.class); -- groupRow.setPrivateLayout(privateParentLayout); -- -- // Create child views on row. -- ExpandableNotificationRow row = mNotificationTestHelper.createRow(); -- NotificationContentView publicChildLayout = mock(NotificationContentView.class); -- row.setPublicLayout(publicChildLayout); -- NotificationContentView privateChildLayout = mock(NotificationContentView.class); -- row.setPrivateLayout(privateChildLayout); -- when(row.isGroupExpanded()).thenReturn(true); -- setMockChildrenContainer(groupRow, row); -- -- groupRow.setAnimationRunning(true); -- verify(publicParentLayout, times(1)).setContentAnimationRunning(true); -- verify(privateParentLayout, times(1)).setContentAnimationRunning(true); -- // The child layouts should be started too. -- verify(publicChildLayout, times(1)).setContentAnimationRunning(true); -- verify(privateChildLayout, times(1)).setContentAnimationRunning(true); -- } -- -- -- @Test -- public void testSetIconAnimationRunningGroup_Run() throws Exception { -- // Create views for a group row. -- ExpandableNotificationRow group = mNotificationTestHelper.createGroup(); -- ExpandableNotificationRow child = mNotificationTestHelper.createRow(); -- NotificationContentView publicParentLayout = mock(NotificationContentView.class); -- group.setPublicLayout(publicParentLayout); -- NotificationContentView privateParentLayout = mock(NotificationContentView.class); -- group.setPrivateLayout(privateParentLayout); -- when(group.isGroupExpanded()).thenReturn(true); -- -- // Add the child to the group. -- NotificationContentView publicChildLayout = mock(NotificationContentView.class); -- child.setPublicLayout(publicChildLayout); -- NotificationContentView privateChildLayout = mock(NotificationContentView.class); -- child.setPrivateLayout(privateChildLayout); -- when(child.isGroupExpanded()).thenReturn(true); -- -- NotificationChildrenContainer mockContainer = -- setMockChildrenContainer(group, child); -- -- // Mock the children view wrappers, and give them each an icon. -- NotificationViewWrapper mockViewWrapper = mock(NotificationViewWrapper.class); -- when(mockContainer.getNotificationViewWrapper()).thenReturn(mockViewWrapper); -- CachingIconView mockIcon = mock(CachingIconView.class); -- when(mockViewWrapper.getIcon()).thenReturn(mockIcon); -- -- NotificationViewWrapper mockLowPriorityViewWrapper = mock(NotificationViewWrapper.class); -- when(mockContainer.getLowPriorityViewWrapper()).thenReturn(mockLowPriorityViewWrapper); -- CachingIconView mockLowPriorityIcon = mock(CachingIconView.class); -- when(mockLowPriorityViewWrapper.getIcon()).thenReturn(mockLowPriorityIcon); -- -- // Give the icon image views drawables, so we can make sure they animate. -- // We use both AnimationDrawables and AnimatedVectorDrawables to ensure both work. -- AnimationDrawable drawable = mock(AnimationDrawable.class); -- AnimatedVectorDrawable vectorDrawable = mock(AnimatedVectorDrawable.class); -- setDrawableIconsInImageView(mockIcon, drawable, vectorDrawable); -- -- AnimationDrawable lowPriDrawable = mock(AnimationDrawable.class); -- AnimatedVectorDrawable lowPriVectorDrawable = mock(AnimatedVectorDrawable.class); -- setDrawableIconsInImageView(mockLowPriorityIcon, lowPriDrawable, lowPriVectorDrawable); -- -- group.setAnimationRunning(true); -- verify(drawable, times(1)).start(); -- verify(vectorDrawable, times(1)).start(); -- verify(lowPriDrawable, times(1)).start(); -- verify(lowPriVectorDrawable, times(1)).start(); -- } -- -- private void setDrawableIconsInImageView(CachingIconView icon, Drawable iconDrawable, -- Drawable rightIconDrawable) { -- ImageView iconView = mock(ImageView.class); -- when(icon.findViewById(com.android.internal.R.id.icon)).thenReturn(iconView); -- when(iconView.getDrawable()).thenReturn(iconDrawable); -- -- ImageView rightIconView = mock(ImageView.class); -- when(icon.findViewById(com.android.internal.R.id.right_icon)).thenReturn(rightIconView); -- when(rightIconView.getDrawable()).thenReturn(rightIconDrawable); -- } -- -- private NotificationChildrenContainer setMockChildrenContainer( -- ExpandableNotificationRow parentRow, ExpandableNotificationRow childRow) { -- List rowList = Arrays.asList(childRow); -- NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); -- when(mockContainer.getNotificationChildCount()).thenReturn(1); -- when(mockContainer.getAttachedChildren()).thenReturn(rowList); -- parentRow.setChildrenContainer(mockContainer); -- return mockContainer; -+ assertThat(row.getImageResolver().getContext()).isSameInstanceAs(userContext); - } - } -diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java -index 0674ea855d7f..fd2914e02a76 100644 ---- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java -+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java -@@ -14,6 +14,7 @@ - - package com.android.systemui; - -+import android.annotation.NonNull; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; -@@ -28,12 +29,15 @@ - - import com.android.internal.annotations.GuardedBy; - -+import java.util.HashMap; -+import java.util.Map; - import java.util.Set; - - public class SysuiTestableContext extends TestableContext { - - @GuardedBy("mRegisteredReceivers") - private final Set mRegisteredReceivers = new ArraySet<>(); -+ private final Map mContextForUser = new HashMap<>(); - - public SysuiTestableContext(Context base) { - super(base); -@@ -146,4 +150,22 @@ public void unregisterReceiver(BroadcastReceiver receiver) { - } - super.unregisterReceiver(receiver); - } -+ -+ /** -+ * Sets a Context object that will be returned as the result of {@link #createContextAsUser} -+ * for a specific {@code user}. -+ */ -+ public void prepareCreateContextAsUser(UserHandle user, Context context) { -+ mContextForUser.put(user, context); -+ } -+ -+ @Override -+ @NonNull -+ public Context createContextAsUser(UserHandle user, int flags) { -+ Context userContext = mContextForUser.get(user); -+ if (userContext != null) { -+ return userContext; -+ } -+ return super.createContextAsUser(user, flags); -+ } - } diff --git a/Patches/LineageOS-20.0/ASB-2024-06/fwb-13.patch b/Patches/LineageOS-20.0/ASB-2024-06/fwb-13.patch deleted file mode 100644 index 7c1c1c29..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/fwb-13.patch +++ /dev/null @@ -1,274 +0,0 @@ -From 56ef52af608d4c74da25da50023b63fb3680159f Mon Sep 17 00:00:00 2001 -From: Beth Thibodeau -Date: Tue, 19 Mar 2024 16:49:51 -0500 -Subject: [PATCH] Update media_controls_lock_screen setting behavior - -When the setting is disabled, hide the media carousel everywhere when -the device is on lockscreen, not just in the keyguard layout - -Bug: 314333719 -Test: manual -Test: atest MediaHierarchyManagerTest -Flag: NONE -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a441f4acd62cce1059818ce8e9b7ab93b0079e50) -Merged-In: I4f618e4013db894291e6fca9d49bceb1cb7e4bd9 -Change-Id: I4f618e4013db894291e6fca9d49bceb1cb7e4bd9 ---- - .../controls/ui/KeyguardMediaController.kt | 40 ------------------- - .../controls/ui/MediaHierarchyManager.kt | 27 +++++++++---- - .../systemui/media/controls/ui/MediaHost.kt | 4 +- - .../ui/KeyguardMediaControllerTest.kt | 28 ------------- - 4 files changed, 22 insertions(+), 77 deletions(-) - -diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt -index 30ee147e302a..2a2882cf7108 100644 ---- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt -+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt -@@ -18,16 +18,10 @@ package com.android.systemui.media.controls.ui - - import android.content.Context - import android.content.res.Configuration --import android.database.ContentObserver --import android.net.Uri --import android.os.Handler --import android.os.UserHandle --import android.provider.Settings - import android.view.View - import android.view.ViewGroup - import androidx.annotation.VisibleForTesting - import com.android.systemui.dagger.SysUISingleton --import com.android.systemui.dagger.qualifiers.Main - import com.android.systemui.media.dagger.MediaModule.KEYGUARD - import com.android.systemui.plugins.statusbar.StatusBarStateController - import com.android.systemui.statusbar.StatusBarState -@@ -36,7 +30,6 @@ import com.android.systemui.statusbar.notification.stack.MediaContainerView - import com.android.systemui.statusbar.phone.KeyguardBypassController - import com.android.systemui.statusbar.policy.ConfigurationController - import com.android.systemui.util.LargeScreenUtils --import com.android.systemui.util.settings.SecureSettings - import javax.inject.Inject - import javax.inject.Named - -@@ -52,8 +45,6 @@ constructor( - private val bypassController: KeyguardBypassController, - private val statusBarStateController: SysuiStatusBarStateController, - private val context: Context, -- private val secureSettings: SecureSettings, -- @Main private val handler: Handler, - configurationController: ConfigurationController, - ) { - -@@ -77,26 +68,6 @@ constructor( - } - ) - -- val settingsObserver: ContentObserver = -- object : ContentObserver(handler) { -- override fun onChange(selfChange: Boolean, uri: Uri?) { -- if (uri == lockScreenMediaPlayerUri) { -- allowMediaPlayerOnLockScreen = -- secureSettings.getBoolForUser( -- Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, -- true, -- UserHandle.USER_CURRENT -- ) -- refreshMediaPosition() -- } -- } -- } -- secureSettings.registerContentObserverForUser( -- Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, -- settingsObserver, -- UserHandle.USER_ALL -- ) -- - // First let's set the desired state that we want for this host - mediaHost.expansion = MediaHostState.EXPANDED - mediaHost.showsOnlyActiveMedia = true -@@ -133,16 +104,6 @@ constructor( - private set - private var splitShadeContainer: ViewGroup? = null - -- /** Track the media player setting status on lock screen. */ -- private var allowMediaPlayerOnLockScreen: Boolean = -- secureSettings.getBoolForUser( -- Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, -- true, -- UserHandle.USER_CURRENT -- ) -- private val lockScreenMediaPlayerUri = -- secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN) -- - /** - * Attaches media container in single pane mode, situated at the top of the notifications list - */ -@@ -202,7 +163,6 @@ constructor( - mediaHost.visible && - !bypassController.bypassEnabled && - keyguardOrUserSwitcher && -- allowMediaPlayerOnLockScreen && - shouldBeVisibleForSplitShade() - if (visible) { - showMediaPlayer() -diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt -index 54237ce7cf25..f0ff1292311d 100644 ---- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt -+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt -@@ -104,7 +104,7 @@ constructor( - ) { - - /** Track the media player setting status on lock screen. */ -- private var allowMediaPlayerOnLockScreen: Boolean = true -+ private var allowMediaPlayerOnLockScreen: Boolean = getMediaLockScreenSetting() - private val lockScreenMediaPlayerUri = - secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN) - -@@ -462,6 +462,7 @@ constructor( - } - mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = - isVisibleToUser() -+ mediaCarouselController.updateHostVisibility() - } - - override fun onDozeAmountChanged(linear: Float, eased: Float) { -@@ -538,7 +539,6 @@ constructor( - mediaCarouselController.updateHostVisibility = { - mediaHosts.forEach { it?.updateViewVisibility() } - } -- - panelEventsEvents.addShadeStateEventsListener( - object : ShadeStateEventsListener { - override fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) { -@@ -552,12 +552,8 @@ constructor( - object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - if (uri == lockScreenMediaPlayerUri) { -- allowMediaPlayerOnLockScreen = -- secureSettings.getBoolForUser( -- Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, -- true, -- UserHandle.USER_CURRENT -- ) -+ allowMediaPlayerOnLockScreen = getMediaLockScreenSetting() -+ mediaCarouselController.updateHostVisibility() - } - } - } -@@ -568,6 +564,14 @@ constructor( - ) - } - -+ private fun getMediaLockScreenSetting(): Boolean { -+ return secureSettings.getBoolForUser( -+ Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, -+ true, -+ UserHandle.USER_CURRENT -+ ) -+ } -+ - private fun updateConfiguration() { - distanceForFullShadeTransition = - context.resources.getDimensionPixelSize( -@@ -607,6 +611,13 @@ constructor( - mediaCarouselController.closeGuts() - } - -+ /** Return true if the carousel should be hidden because lockscreen is currently visible */ -+ fun isLockedAndHidden(): Boolean { -+ return !allowMediaPlayerOnLockScreen && -+ (statusbarState == StatusBarState.SHADE_LOCKED || -+ statusbarState == StatusBarState.KEYGUARD) -+ } -+ - private fun createUniqueObjectHost(): UniqueObjectHostView { - val viewHost = UniqueObjectHostView(context) - viewHost.addOnAttachStateChangeListener( -diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt -index be570b4a1119..26580e54cd62 100644 ---- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt -+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt -@@ -199,7 +199,9 @@ constructor( - */ - fun updateViewVisibility() { - state.visible = -- if (showsOnlyActiveMedia) { -+ if (mediaHierarchyManager.isLockedAndHidden()) { -+ false -+ } else if (showsOnlyActiveMedia) { - mediaDataManager.hasActiveMediaOrRecommendation() - } else { - mediaDataManager.hasAnyMediaOrRecommendation() -diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt -index b40ebc9bb156..41b3fe65599f 100644 ---- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt -+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt -@@ -16,7 +16,6 @@ - - package com.android.systemui.media.controls.ui - --import android.provider.Settings - import android.test.suitebuilder.annotation.SmallTest - import android.testing.AndroidTestingRunner - import android.testing.TestableLooper -@@ -32,8 +31,6 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController - import com.android.systemui.statusbar.policy.ConfigurationController - import com.android.systemui.util.animation.UniqueObjectHostView - import com.android.systemui.util.mockito.whenever --import com.android.systemui.util.settings.FakeSettings --import com.android.systemui.utils.os.FakeHandler - import com.google.common.truth.Truth.assertThat - import junit.framework.Assert.assertTrue - import org.junit.Before -@@ -60,10 +57,7 @@ class KeyguardMediaControllerTest : SysuiTestCase() { - - private val mediaContainerView: MediaContainerView = MediaContainerView(context, null) - private val hostView = UniqueObjectHostView(context) -- private val settings = FakeSettings() - private lateinit var keyguardMediaController: KeyguardMediaController -- private lateinit var testableLooper: TestableLooper -- private lateinit var fakeHandler: FakeHandler - private lateinit var statusBarStateListener: StatusBarStateController.StateListener - - @Before -@@ -79,16 +73,12 @@ class KeyguardMediaControllerTest : SysuiTestCase() { - whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) - whenever(mediaHost.hostView).thenReturn(hostView) - hostView.layoutParams = FrameLayout.LayoutParams(100, 100) -- testableLooper = TestableLooper.get(this) -- fakeHandler = FakeHandler(testableLooper.looper) - keyguardMediaController = - KeyguardMediaController( - mediaHost, - bypassController, - statusBarStateController, - context, -- settings, -- fakeHandler, - configurationController, - ) - keyguardMediaController.attachSinglePaneContainer(mediaContainerView) -@@ -117,24 +107,6 @@ class KeyguardMediaControllerTest : SysuiTestCase() { - assertThat(mediaContainerView.visibility).isEqualTo(visibility) - } - -- @Test -- fun testHiddenOnKeyguard_whenMediaOnLockScreenDisabled() { -- settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 0) -- -- keyguardMediaController.refreshMediaPosition() -- -- assertThat(mediaContainerView.visibility).isEqualTo(GONE) -- } -- -- @Test -- fun testAvailableOnKeyguard_whenMediaOnLockScreenEnabled() { -- settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 1) -- -- keyguardMediaController.refreshMediaPosition() -- -- assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE) -- } -- - @Test - fun testActivatesSplitShadeContainerInSplitShadeMode() { - val splitShadeContainer = FrameLayout(context) diff --git a/Patches/LineageOS-20.0/ASB-2024-06/libfmq-01.patch b/Patches/LineageOS-20.0/ASB-2024-06/libfmq-01.patch deleted file mode 100644 index 4f92baaf..00000000 --- a/Patches/LineageOS-20.0/ASB-2024-06/libfmq-01.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 9a005ebebfa638ed42415301fec30b16bef30299 Mon Sep 17 00:00:00 2001 -From: Devin Moore -Date: Mon, 22 Jan 2024 17:52:16 +0000 -Subject: [PATCH] Use the values of the ptrs that we check - -Test: fmq_fuzzer -Bug: 321326147 -Bug: 321341508 -Bug: 321383085 -(cherry picked from https://android-review.googlesource.com/q/commit:38963310ad5789b625ca0bca9f9c2c8e24666651) -(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:050952bf5f9bd035e469ce005300115d563e524a) -Merged-In: I56fe4fe72180e39ecef066353969c1ae9fbcd44e -Change-Id: I56fe4fe72180e39ecef066353969c1ae9fbcd44e ---- - include/fmq/MessageQueueBase.h | 24 ++++++++++++++++++++---- - 1 file changed, 20 insertions(+), 4 deletions(-) - -diff --git a/include/fmq/MessageQueueBase.h b/include/fmq/MessageQueueBase.h -index f4bf7e2..0bf0bb2 100644 ---- a/include/fmq/MessageQueueBase.h -+++ b/include/fmq/MessageQueueBase.h -@@ -1034,8 +1034,16 @@ bool MessageQueueBase::readBlocking(T* data, size_t - } - - template