Adds userId to onTopActivityChanged callback in VirtualDeviceManager
Adding the userId will allow onTopActivityChanged to be associated with a userId when the top activity changes in a stream via using the VirtualDeviceManager and allows the API user to know which profile is active. While the userId can be found through other means, the indirect path can cause a race condition with poor user experience. Bug: 264474826 Test: atest CtsVirtualDevicesTestCases Change-Id: Ib00e1589a2c7b545d499d65e1d7ff9c12f0b4654
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>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));
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<Integer> mRunningUids = new ArraySet<>();
|
||||
|
||||
@Override
|
||||
@@ -254,8 +254,8 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTopActivityChanged(ComponentName topActivity, int uid) {
|
||||
super.onTopActivityChanged(topActivity, uid);
|
||||
public void onTopActivityChanged(ComponentName topActivity, int uid, int userId) {
|
||||
super.onTopActivityChanged(topActivity, uid, userId);
|
||||
mTopActivity = topActivity;
|
||||
mTopActivityUid = uid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user