diff --git a/core/api/system-current.txt b/core/api/system-current.txt index d3a655c9f7218..803ef22f2051d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3004,7 +3004,8 @@ package android.companion.virtual { public static interface VirtualDeviceManager.ActivityListener { method public void onDisplayEmpty(int); - method public void onTopActivityChanged(int, @NonNull android.content.ComponentName); + method @Deprecated public void onTopActivityChanged(int, @NonNull android.content.ComponentName); + method public default void onTopActivityChanged(int, @NonNull android.content.ComponentName, int); } public static interface VirtualDeviceManager.IntentInterceptorCallback { diff --git a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl index a46dc534da562..fc7f85cceefca 100644 --- a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl +++ b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl @@ -30,8 +30,9 @@ oneway interface IVirtualDeviceActivityListener { * * @param displayId The display ID on which the activity change happened. * @param topActivity The component name of the top activity. + * @param userId The user ID associated with the top activity. */ - void onTopActivityChanged(int displayId, in ComponentName topActivity); + void onTopActivityChanged(int displayId, in ComponentName topActivity, in int userId); /** * Called when the display becomes empty (e.g. if the user hits back on the last diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java index d585e8f8d38da..3e6b380be1f4d 100644 --- a/core/java/android/companion/virtual/VirtualDeviceManager.java +++ b/core/java/android/companion/virtual/VirtualDeviceManager.java @@ -27,6 +27,7 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.UserIdInt; import android.app.PendingIntent; import android.companion.AssociationInfo; import android.companion.virtual.audio.VirtualAudioDevice; @@ -378,13 +379,16 @@ public final class VirtualDeviceManager { new IVirtualDeviceActivityListener.Stub() { @Override - public void onTopActivityChanged(int displayId, ComponentName topActivity) { + public void onTopActivityChanged(int displayId, ComponentName topActivity, + @UserIdInt int userId) { final long token = Binder.clearCallingIdentity(); try { synchronized (mActivityListenersLock) { for (int i = 0; i < mActivityListeners.size(); i++) { mActivityListeners.valueAt(i) .onTopActivityChanged(displayId, topActivity); + mActivityListeners.valueAt(i) + .onTopActivityChanged(displayId, topActivity, userId); } } } finally { @@ -1087,9 +1091,24 @@ public final class VirtualDeviceManager { * * @param displayId The display ID on which the activity change happened. * @param topActivity The component name of the top activity. + * @deprecated Use {@link #onTopActivityChanged(int, ComponentName, int)} instead */ void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity); + /** + * Called when the top activity is changed. + * + *
Note: When there are no activities running on the virtual display, the
+ * {@link #onDisplayEmpty(int)} will be called. If the value topActivity is cached, it
+ * should be cleared when {@link #onDisplayEmpty(int)} is called.
+ *
+ * @param displayId The display ID on which the activity change happened.
+ * @param topActivity The component name of the top activity.
+ * @param userId The user ID associated with the top activity.
+ */
+ default void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity,
+ @UserIdInt int userId) {}
+
/**
* Called when the display becomes empty (e.g. if the user hits back on the last
* activity of the root task).
@@ -1115,6 +1134,12 @@ public final class VirtualDeviceManager {
mExecutor.execute(() -> mActivityListener.onTopActivityChanged(displayId, topActivity));
}
+ public void onTopActivityChanged(int displayId, ComponentName topActivity,
+ @UserIdInt int userId) {
+ mExecutor.execute(() ->
+ mActivityListener.onTopActivityChanged(displayId, topActivity, userId));
+ }
+
public void onDisplayEmpty(int displayId) {
mExecutor.execute(() -> mActivityListener.onDisplayEmpty(displayId));
}
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java
index 535dc4e78c89d..c2700536f8490 100644
--- a/core/java/android/window/DisplayWindowPolicyController.java
+++ b/core/java/android/window/DisplayWindowPolicyController.java
@@ -19,6 +19,7 @@ package android.window;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
@@ -137,7 +138,7 @@ public abstract class DisplayWindowPolicyController {
/**
* This is called when the top activity of the display is changed.
*/
- public void onTopActivityChanged(ComponentName topActivity, int uid) {}
+ public void onTopActivityChanged(ComponentName topActivity, int uid, @UserIdInt int userId) {}
/**
* This is called when the apps that contains running activities on the display has changed.
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 6b2e893a55c9d..e52f1d9c61db3 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
@@ -302,14 +303,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
@Override
- public void onTopActivityChanged(ComponentName topActivity, int uid) {
+ public void onTopActivityChanged(ComponentName topActivity, int uid, @UserIdInt int userId) {
// Don't send onTopActivityChanged() callback when topActivity is null because it's defined
// as @NonNull in ActivityListener interface. Sends onDisplayEmpty() callback instead when
// there is no activity running on virtual display.
if (mActivityListener != null && topActivity != null) {
// Post callback on the main thread so it doesn't block activity launching
mHandler.post(() ->
- mActivityListener.onTopActivityChanged(mDisplayId, topActivity));
+ mActivityListener.onTopActivityChanged(mDisplayId, topActivity, userId));
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 5985ce45e4d5b..366d0736b7aac 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -26,6 +26,7 @@ import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
+import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.PendingIntent;
@@ -138,7 +139,18 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@Override
public void onTopActivityChanged(int displayId, ComponentName topActivity) {
try {
- mActivityListener.onTopActivityChanged(displayId, topActivity);
+ mActivityListener.onTopActivityChanged(displayId, topActivity,
+ UserHandle.USER_NULL);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to call mActivityListener", e);
+ }
+ }
+
+ @Override
+ public void onTopActivityChanged(int displayId, ComponentName topActivity,
+ @UserIdInt int userId) {
+ try {
+ mActivityListener.onTopActivityChanged(displayId, topActivity, userId);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to call mActivityListener", e);
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 154fb0cecac32..1fb97f97f4216 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
@@ -138,10 +139,14 @@ class DisplayWindowPolicyControllerHelper {
true /* includeOverlays */);
if (topActivity != mTopRunningActivity) {
mTopRunningActivity = topActivity;
- mDisplayWindowPolicyController.onTopActivityChanged(
- topActivity == null ? null : topActivity.info.getComponentName(),
- topActivity == null
- ? UserHandle.USER_NULL : topActivity.info.applicationInfo.uid);
+ if (topActivity == null) {
+ mDisplayWindowPolicyController.onTopActivityChanged(null, Process.INVALID_UID,
+ UserHandle.USER_NULL);
+ } else {
+ mDisplayWindowPolicyController.onTopActivityChanged(
+ topActivity.info.getComponentName(), topActivity.info.applicationInfo.uid,
+ topActivity.mUserId);
+ }
}
// Update running uid.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index b2abd44254d95..19d1d83f5e737 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -33,7 +33,7 @@ import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.os.UserHandle;
+import android.os.Process;
import android.util.ArraySet;
import android.view.Display;
import android.window.DisplayWindowPolicyController;
@@ -101,7 +101,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
int uidAmount = (expectedUid0 && expectedUid1) ? 2 : (expectedUid0 || expectedUid1) ? 1 : 0;
assertEquals(expectedTopActivity == null ? null :
expectedTopActivity.info.getComponentName(), mDwpc.mTopActivity);
- assertEquals(expectedTopActivity == null ? UserHandle.USER_NULL :
+ assertEquals(expectedTopActivity == null ? Process.INVALID_UID :
expectedTopActivity.info.applicationInfo.uid, mDwpc.mTopActivityUid);
assertEquals(uidAmount, mDwpc.mRunningUids.size());
assertTrue(mDwpc.mRunningUids.contains(TEST_USER_0_ID) == expectedUid0);
@@ -224,7 +224,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
new ComponentName("fake.package", "DisallowedActivity");
ComponentName mTopActivity = null;
- int mTopActivityUid = UserHandle.USER_NULL;
+ int mTopActivityUid = Process.INVALID_UID;
ArraySet