Merge cherrypicks of [16565827, 16572034, 16531386, 16600886, 16602652] into security-aosp-rvc-release.
Change-Id: I0e600593cbdaabde0c558cc314cf9e2285a6e9e2
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index ec8bfc6..a32ab73 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -130,6 +130,12 @@
wrapper = null
bindService(false)
}
+
+ override fun onNullBinding(name: ComponentName?) {
+ if (DEBUG) Log.d(TAG, "onNullBinding $name")
+ wrapper = null
+ context.unbindService(this)
+ }
}
private fun handlePendingServiceMethods() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index 2d3757c..12096bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -17,6 +17,9 @@
package com.android.systemui.controls.controller
import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
import android.os.UserHandle
import android.service.controls.IControlsActionCallback
import android.service.controls.IControlsProvider
@@ -43,6 +46,8 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -57,8 +62,6 @@
private lateinit var subscriberService: IControlsSubscriber.Stub
@Mock
private lateinit var service: IControlsProvider.Stub
- @Mock
- private lateinit var loadCallback: ControlsBindingController.LoadCallback
@Captor
private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
@@ -75,7 +78,7 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
- mContext.addMockService(componentName, service)
+ context.addMockService(componentName, service)
executor = FakeExecutor(FakeSystemClock())
`when`(service.asBinder()).thenCallRealMethod()
`when`(service.queryLocalInterface(ArgumentMatchers.anyString())).thenReturn(service)
@@ -98,7 +101,36 @@
fun testBindService() {
manager.bindService()
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
+ }
+
+ @Test
+ fun testNullBinding() {
+ val mockContext = mock(Context::class.java)
+ lateinit var serviceConnection: ServiceConnection
+ `when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer {
+ val component = (it.arguments[0] as Intent).component
+ if (component == componentName) {
+ serviceConnection = it.arguments[1] as ServiceConnection
+ serviceConnection.onNullBinding(component)
+ true
+ } else {
+ false
+ }
+ }
+
+ val nullManager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ UserHandle.of(0),
+ componentName
+ )
+
+ nullManager.bindService()
+ executor.runAllReady()
+
+ verify(mockContext).unbindService(serviceConnection)
}
@Test
@@ -109,7 +141,7 @@
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -119,7 +151,7 @@
verify(service).load(subscriberService)
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
}
@Test
@@ -129,7 +161,7 @@
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -162,7 +194,7 @@
manager.maybeBindAndSubscribe(list, subscriberService)
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
verify(service).subscribe(list, subscriberService)
}
@@ -173,7 +205,7 @@
manager.maybeBindAndSendAction(controlId, action)
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
verify(service).action(eq(controlId), capture(wrapperCaptor),
eq(actionCallbackService))
assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6b43d99..0833d26 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2470,7 +2470,7 @@
}
}
- private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+ void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromApp, boolean fromListener) {
Objects.requireNonNull(group);
Objects.requireNonNull(pkg);
@@ -3488,7 +3488,8 @@
final int callingUid = Binder.getCallingUid();
NotificationChannelGroup groupToDelete =
- mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
+ mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ pkg, callingUid, groupId, false);
if (groupToDelete != null) {
// Preflight for allowability
final int userId = UserHandle.getUserId(callingUid);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 94312b0..557c417 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -344,7 +344,11 @@
if (age >= MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS) {
// Aggressively close old sessions because we are running low on storage
// Their staging dirs will be removed too
- session.abandon();
+ PackageInstallerSession root = !session.hasParentSessionId()
+ ? session : mSessions.get(session.getParentSessionId());
+ if (!root.isDestroyed()) {
+ root.abandon();
+ }
} else {
// Session is new enough, so it deserves to be kept even on low storage
unclaimedStagingDirsOnVolume.remove(session.stageDir);
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 5e04171..354f5b9 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -409,6 +409,8 @@
}
if (bp.perm != null && Objects.equals(bp.perm.getPackageName(), p.getPackageName())
&& Objects.equals(bp.perm.getName(), p.getName())) {
+ bp.perm.setFlags(bp.perm.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
+ bp.perm = p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
bp.protectionLevel = p.getProtectionLevel();
}
if (bp.isRuntime() && (ownerChanged || wasNonRuntime)) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
old mode 100755
new mode 100644
index 67b7a79..9394eb8
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -178,6 +178,8 @@
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import com.google.common.collect.ImmutableList;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -201,6 +203,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@@ -244,6 +247,8 @@
@Mock
Resources mResources;
@Mock
+ ActivityManagerInternal mAmi;
+ @Mock
RankingHandler mRankingHandler;
private static final int MAX_POST_DELAY = 1000;
@@ -415,7 +420,6 @@
DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
- ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
@@ -426,7 +430,7 @@
LocalServices.removeServiceForTest(DeviceIdleInternal.class);
LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
- LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
+ LocalServices.addService(ActivityManagerInternal.class, mAmi);
mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
@@ -503,7 +507,7 @@
mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
mAppOpsManager, mUm, mHistoryManager, mStatsManager,
mock(TelephonyManager.class),
- mock(ActivityManagerInternal.class));
+ mAmi);
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.setAudioManager(mAudioManager);
@@ -2450,7 +2454,8 @@
.thenReturn(associations);
NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
+ when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
.thenReturn(ncg);
reset(mListeners);
mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
@@ -2460,6 +2465,56 @@
}
@Test
+ public void testDeleteChannelGroupChecksForFgses() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
+ .thenReturn(associations);
+ CountDownLatch latch = new CountDownLatch(2);
+ mService.createNotificationChannelGroup(
+ PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
+ new Thread(() -> {
+ NotificationChannel notificationChannel = new NotificationChannel("id", "id",
+ NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("group");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ latch.countDown();
+ }).start();
+ new Thread(() -> {
+ try {
+ synchronized (this) {
+ wait(5000);
+ }
+ mService.createNotificationChannelGroup(PKG, mUid,
+ new NotificationChannelGroup("new", "new group"), true, false);
+ NotificationChannel notificationChannel =
+ new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("new");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ mBinderService.deleteNotificationChannelGroup(PKG, "group");
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ latch.countDown();
+ }).start();
+
+ latch.await();
+ verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
+ }
+
+ @Test
public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
List<String> associations = new ArrayList<>();