summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt50
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java1
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java39
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java24
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java52
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java9
12 files changed, 220 insertions, 32 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cd6af189a04a..9ad8dfa70562 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5662,6 +5662,10 @@
<!-- Allows input events to be monitored. Very dangerous! @hide -->
<permission android:name="android.permission.MONITOR_INPUT"
android:protectionLevel="signature|recents" />
+ <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
+ window to the window where the touch currently is on top of. @hide -->
+ <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
+ android:protectionLevel="signature|recents" />
<!-- Allows the caller to change the associations between input devices and displays.
Very dangerous! @hide -->
<permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9de1c5ea1a3d..3d1bd24807c4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -121,6 +121,7 @@
<uses-permission android:name="android.permission.SET_ORIENTATION" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.MONITOR_INPUT" />
+ <uses-permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES" />
<uses-permission android:name="android.permission.INPUT_CONSUMER" />
<!-- DreamManager -->
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 977e46ac3b44..d2ded71487dc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -131,6 +131,12 @@ class ControlsProviderLifecycleManager(
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 2d3757c29ebf..12096bc06748 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.ArgumentMatchers.eq
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 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
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 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
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 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
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 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -119,7 +151,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
verify(service).load(subscriberService)
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
}
@Test
@@ -129,7 +161,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -162,7 +194,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.maybeBindAndSubscribe(list, subscriberService)
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
verify(service).subscribe(list, subscriberService)
}
@@ -173,7 +205,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
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/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 64b9bd98a2fc..6d29c379d1b1 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1314,6 +1314,7 @@ public class AppOpsService extends IAppOpsService.Stub {
event.getAttributionFlags(), event.getAttributionChainId());
}
+ events = isRunning ? mInProgressEvents : mPausedInProgressEvents;
InProgressStartOpEvent newEvent = events.get(binders.get(i));
if (newEvent != null) {
newEvent.numUnfinishedStarts += numPreviousUnfinishedStarts - 1;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7ba0f04a435f..73e7c9c15d54 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2803,7 +2803,7 @@ public class NotificationManagerService extends SystemService {
}
}
- 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);
@@ -3851,7 +3851,8 @@ public class NotificationManagerService extends SystemService {
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 7fdeb27203bd..2f1fa2221e98 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -388,7 +388,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
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/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c068fd1a5f6e..96f18bd1b4c3 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -194,6 +194,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -385,6 +386,11 @@ class Task extends WindowContainer<WindowContainer> {
*/
boolean mInResumeTopActivity = false;
+ /**
+ * Used to identify if the activity that is installed from device's system image.
+ */
+ boolean mIsEffectivelySystemApp;
+
int mCurrentUser;
String affinity; // The affinity name for this task, or null; may change identity.
@@ -785,11 +791,24 @@ class Task extends WindowContainer<WindowContainer> {
if (r.finishing) return false;
- // Set this as the candidate root since it isn't finishing.
- mRoot = r;
+ if (mRoot == null || mRoot.finishing) {
+ // Set this as the candidate root since it isn't finishing.
+ mRoot = r;
+ }
- // Only end search if we are ignore relinquishing identity or we are not relinquishing.
- return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+ final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid;
+ if (ignoreRelinquishIdentity
+ || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+ || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID
+ && !mRoot.info.applicationInfo.isSystemApp()
+ && mRoot.info.applicationInfo.uid != uid)) {
+ // No need to relinquish identity, end search.
+ return true;
+ }
+
+ // Relinquish to next activity
+ mRoot = r;
+ return false;
}
}
@@ -1241,12 +1260,19 @@ class Task extends WindowContainer<WindowContainer> {
* @param info The activity info which could be different from {@code r.info} if set.
*/
void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
- if (this.intent == null || !mNeverRelinquishIdentity) {
+ boolean updateIdentity = false;
+ if (this.intent == null) {
+ updateIdentity = true;
+ } else if (!mNeverRelinquishIdentity) {
+ final ActivityInfo activityInfo = info != null ? info : r.info;
+ updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp
+ || effectiveUid == activityInfo.applicationInfo.uid);
+ }
+ if (updateIdentity) {
mCallingUid = r.launchedFromUid;
mCallingPackage = r.launchedFromPackage;
mCallingFeatureId = r.launchedFromFeatureId;
setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
- return;
}
setLockTaskAuth(r);
}
@@ -1264,6 +1290,7 @@ class Task extends WindowContainer<WindowContainer> {
rootAffinity = affinity;
}
effectiveUid = info.applicationInfo.uid;
+ mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
stringName = null;
if (info.targetActivity == null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e3ff9e75dbd8..b2fe033a1e13 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -56,6 +56,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
@@ -1677,6 +1678,7 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
+ attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), callingUid, callingPid);
win.updateRequestedVisibility(requestedVisibility);
res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
@@ -2239,6 +2241,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (attrs != null) {
displayPolicy.adjustWindowParamsLw(win, attrs);
win.mToken.adjustWindowParams(win, attrs);
+ attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), uid, pid);
int disableFlags =
(attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK;
if (disableFlags != 0 && !hasStatusBarPermission(pid, uid)) {
@@ -8186,6 +8189,23 @@ public class WindowManagerService extends IWindowManager.Stub
}
/**
+ * You need ALLOW_SLIPPERY_TOUCHES permission to be able to set FLAG_SLIPPERY.
+ */
+ private int sanitizeFlagSlippery(int flags, String windowName, int callingUid, int callingPid) {
+ if ((flags & FLAG_SLIPPERY) == 0) {
+ return flags;
+ }
+ final int permissionResult = mContext.checkPermission(
+ android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES, callingPid, callingUid);
+ if (permissionResult != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Removing FLAG_SLIPPERY from '" + windowName
+ + "' because it doesn't have ALLOW_SLIPPERY_TOUCHES permission");
+ return flags & ~FLAG_SLIPPERY;
+ }
+ return flags;
+ }
+
+ /**
* Assigns an InputChannel to a SurfaceControl and configures it to receive
* touch input according to it's on-screen geometry.
*
@@ -8223,8 +8243,10 @@ public class WindowManagerService extends IWindowManager.Stub
h.token = channelToken;
h.name = name;
+ flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid);
+
final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
- | LayoutParams.FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
+ | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
h.layoutParamsType = type;
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
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 1ae219db7726..3555865dc6a3 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -225,6 +225,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@@ -2460,7 +2462,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.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());
@@ -2470,6 +2473,56 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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<>();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 0ebff1d253ef..d27058060407 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -895,10 +895,10 @@ public class TaskTests extends WindowTestsBase {
*/
@Test
public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() {
- final Task task = getTestTask();
+ final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = activity0.getTask();
// Add extra two activities. Mark the one on the bottom with "relinquishTaskIdentity" and
// one above as finishing.
- final ActivityRecord activity0 = task.getBottomMostActivity();
activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
activity1.finishing = true;
@@ -930,9 +930,9 @@ public class TaskTests extends WindowTestsBase {
*/
@Test
public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
- final Task task = getTestTask();
+ final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = activity0.getTask();
// Set relinquishTaskIdentity for all activities in the task
- final ActivityRecord activity0 = task.getBottomMostActivity();
activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
@@ -1082,9 +1082,9 @@ public class TaskTests extends WindowTestsBase {
*/
@Test
public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
- final Task task = getTestTask();
+ final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = activity0.getTask();
// Make the current root activity relinquish task identity
- final ActivityRecord activity0 = task.getBottomMostActivity();
activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
// Add an extra activity on top - this will be the new root
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
@@ -1180,6 +1180,46 @@ public class TaskTests extends WindowTestsBase {
verify(task).setIntent(eq(activity0));
}
+ /**
+ * Test {@link Task#updateEffectiveIntent()} when activity with relinquishTaskIdentity but
+ * another with different uid. This should make the task use the root activity when updating the
+ * intent.
+ */
+ @Test
+ public void testUpdateEffectiveIntent_relinquishingWithDifferentUid() {
+ final ActivityRecord activity0 = new ActivityBuilder(mAtm)
+ .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build();
+ final Task task = activity0.getTask();
+
+ // Add an extra activity on top
+ new ActivityBuilder(mAtm).setUid(11).setTask(task).build();
+
+ spyOn(task);
+ task.updateEffectiveIntent();
+ verify(task).setIntent(eq(activity0));
+ }
+
+ /**
+ * Test {@link Task#updateEffectiveIntent()} with activities set as relinquishTaskIdentity.
+ * This should make the task use the topmost activity when updating the intent.
+ */
+ @Test
+ public void testUpdateEffectiveIntent_relinquishingMultipleActivities() {
+ final ActivityRecord activity0 = new ActivityBuilder(mAtm)
+ .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build();
+ final Task task = activity0.getTask();
+ // Add an extra activity on top
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
+ activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
+
+ // Add an extra activity on top
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build();
+
+ spyOn(task);
+ task.updateEffectiveIntent();
+ verify(task).setIntent(eq(activity2));
+ }
+
@Test
public void testSaveLaunchingStateWhenConfigurationChanged() {
LaunchParamsPersister persister = mAtm.mTaskSupervisor.mLaunchParamsPersister;
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 85f16eb00987..661dcbb7f489 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -175,10 +175,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
// Delay for debouncing USB disconnects.
// We often get rapid connect/disconnect events when enabling USB functions,
// which need debouncing.
- private static final int DEVICE_STATE_UPDATE_DELAY = 3000;
-
- // Delay for debouncing USB disconnects on Type-C ports in host mode
- private static final int HOST_STATE_UPDATE_DELAY = 1000;
+ private static final int UPDATE_DELAY = 1000;
// Timeout for entering USB request mode.
// Request is cancelled if host does not configure device within 10 seconds.
@@ -639,7 +636,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
msg.arg1 = connected;
msg.arg2 = configured;
// debounce disconnects to avoid problems bringing up USB tethering
- sendMessageDelayed(msg, (connected == 0) ? DEVICE_STATE_UPDATE_DELAY : 0);
+ sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
}
public void updateHostState(UsbPort port, UsbPortStatus status) {
@@ -654,7 +651,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
removeMessages(MSG_UPDATE_PORT_STATE);
Message msg = obtainMessage(MSG_UPDATE_PORT_STATE, args);
// debounce rapid transitions of connect/disconnect on type-c ports
- sendMessageDelayed(msg, HOST_STATE_UPDATE_DELAY);
+ sendMessageDelayed(msg, UPDATE_DELAY);
}
private void setAdbEnabled(boolean enable) {