Support addWindow as other user
Support addWindow with the other userId which can be different from Uid. This can be used when client want to addView for secondary user. Example: 1. Create context with createContextAsUser or similar method. 2. Get WindowManager with this context. 3. WindowManager#addView Bug: 151414297 Test: atest WmTests WindowAddRemovePerfTest AddWindowAsUserTest Change-Id: I13e58d76b1f056f3829bc984c2b61496c8f8d535
This commit is contained in:
@@ -48,6 +48,11 @@ interface IWindowSession {
|
||||
out Rect outContentInsets, out Rect outStableInsets,
|
||||
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
|
||||
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
|
||||
int addToDisplayAsUser(IWindow window, int seq, in WindowManager.LayoutParams attrs,
|
||||
in int viewVisibility, in int layerStackId, in int userId,
|
||||
out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
|
||||
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
|
||||
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
|
||||
int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
|
||||
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
|
||||
out Rect outStableInsets, out InsetsState insetsState);
|
||||
|
||||
@@ -111,6 +111,7 @@ import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.sysprop.DisplayProperties;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.DisplayMetrics;
|
||||
@@ -893,6 +894,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
* We have one child
|
||||
*/
|
||||
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
|
||||
setView(view, attrs, panelParentView, UserHandle.myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* We have one child
|
||||
*/
|
||||
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
|
||||
int userId) {
|
||||
synchronized (this) {
|
||||
if (mView == null) {
|
||||
mView = view;
|
||||
@@ -1001,8 +1010,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mAttachInfo.mRecomputeGlobalAttributes = true;
|
||||
collectViewAttributes();
|
||||
adjustLayoutParamsForCompatibility(mWindowAttributes);
|
||||
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
|
||||
getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
|
||||
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
|
||||
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
|
||||
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
|
||||
mAttachInfo.mDisplayCutout, inputChannel,
|
||||
mTempInsets, mTempControls);
|
||||
@@ -1075,6 +1084,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
throw new WindowManager.InvalidDisplayException("Unable to add window "
|
||||
+ mWindow + " -- the specified window type "
|
||||
+ mWindowAttributes.type + " is not valid");
|
||||
case WindowManagerGlobal.ADD_INVALID_USER:
|
||||
throw new WindowManager.BadTokenException("Unable to add Window "
|
||||
+ mWindow + " -- requested userId is not valid");
|
||||
}
|
||||
throw new RuntimeException(
|
||||
"Unable to add window -- unknown error code " + res);
|
||||
|
||||
@@ -136,6 +136,7 @@ public final class WindowManagerGlobal {
|
||||
public static final int ADD_PERMISSION_DENIED = -8;
|
||||
public static final int ADD_INVALID_DISPLAY = -9;
|
||||
public static final int ADD_INVALID_TYPE = -10;
|
||||
public static final int ADD_INVALID_USER = -11;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private static WindowManagerGlobal sDefaultWindowManager;
|
||||
@@ -317,7 +318,7 @@ public final class WindowManagerGlobal {
|
||||
}
|
||||
|
||||
public void addView(View view, ViewGroup.LayoutParams params,
|
||||
Display display, Window parentWindow) {
|
||||
Display display, Window parentWindow, int userId) {
|
||||
if (view == null) {
|
||||
throw new IllegalArgumentException("view must not be null");
|
||||
}
|
||||
@@ -394,7 +395,7 @@ public final class WindowManagerGlobal {
|
||||
|
||||
// do this last because it fires off messages to start doing things
|
||||
try {
|
||||
root.setView(view, wparams, panelParentView);
|
||||
root.setView(view, wparams, panelParentView, userId);
|
||||
} catch (RuntimeException e) {
|
||||
// BadTokenException or InvalidDisplayException, clean up.
|
||||
if (index >= 0) {
|
||||
|
||||
@@ -104,7 +104,8 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
@Override
|
||||
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
|
||||
applyDefaultToken(params);
|
||||
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow);
|
||||
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
|
||||
mContext.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -130,6 +130,20 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
return WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* IWindowSession implementation. Currently this class doesn't need to support for multi-user.
|
||||
*/
|
||||
@Override
|
||||
public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs,
|
||||
int viewVisibility, int displayId, int userId, Rect outFrame,
|
||||
Rect outContentInsets, Rect outStableInsets,
|
||||
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
|
||||
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
|
||||
return addToDisplay(window, seq, attrs, viewVisibility, displayId,
|
||||
outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
|
||||
outInsetsState, outActiveControls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addToDisplayWithoutInputChannel(android.view.IWindow window, int seq,
|
||||
android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId,
|
||||
|
||||
@@ -1201,6 +1201,12 @@
|
||||
"group": "WM_SHOW_TRANSACTIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
|
||||
},
|
||||
"315395835": {
|
||||
"message": "Trying to add window with invalid user=%d",
|
||||
"level": "WARN",
|
||||
"group": "WM_ERROR",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"342460966": {
|
||||
"message": "DRAG %s: pos=(%d,%d)",
|
||||
"level": "INFO",
|
||||
|
||||
@@ -664,7 +664,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
|
||||
void setSecureSurfaceState(int userId, boolean disabled) {
|
||||
forAllWindows((w) -> {
|
||||
if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
|
||||
if (w.mHasSurface && userId == w.mShowUserId) {
|
||||
w.mWinAnimator.setSecureLocked(disabled);
|
||||
}
|
||||
}, true /* traverseTopToBottom */);
|
||||
|
||||
@@ -162,7 +162,19 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
|
||||
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
|
||||
outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
|
||||
outInsetsState, outActiveControls);
|
||||
outInsetsState, outActiveControls, UserHandle.getUserId(mUid));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int addToDisplayAsUser(IWindow window, int seq, WindowManager.LayoutParams attrs,
|
||||
int viewVisibility, int displayId, int userId, Rect outFrame,
|
||||
Rect outContentInsets, Rect outStableInsets,
|
||||
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
|
||||
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
|
||||
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
|
||||
outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
|
||||
outInsetsState, outActiveControls, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,7 +184,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
|
||||
new Rect() /* outFrame */, outContentInsets, outStableInsets,
|
||||
new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
|
||||
outInsetsState, null);
|
||||
outInsetsState, null, UserHandle.getUserId(mUid));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
|
||||
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
|
||||
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
|
||||
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
|
||||
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
|
||||
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
|
||||
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
|
||||
import static android.app.StatusBarManager.DISABLE_MASK;
|
||||
@@ -1357,7 +1358,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
|
||||
Rect outContentInsets, Rect outStableInsets,
|
||||
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
|
||||
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
|
||||
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
|
||||
int requestUserId) {
|
||||
int[] appOp = new int[1];
|
||||
final boolean isRoundedCornerOverlay = (attrs.privateFlags
|
||||
& PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
|
||||
@@ -1426,6 +1428,20 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
|
||||
}
|
||||
|
||||
int userId = UserHandle.getUserId(session.mUid);
|
||||
if (requestUserId != userId) {
|
||||
try {
|
||||
mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId,
|
||||
false /*allowAll*/, ALLOW_NON_FULL, null, null);
|
||||
} catch (Exception exp) {
|
||||
ProtoLog.w(WM_ERROR, "Trying to add window with invalid user=%d",
|
||||
requestUserId);
|
||||
return WindowManagerGlobal.ADD_INVALID_USER;
|
||||
}
|
||||
// It's fine to use this userId
|
||||
userId = requestUserId;
|
||||
}
|
||||
|
||||
ActivityRecord activity = null;
|
||||
final boolean hasParent = parentWindow != null;
|
||||
// Use existing parent window token for child windows since they go in the same token
|
||||
@@ -1514,7 +1530,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
final WindowState win = new WindowState(this, session, client, token, parentWindow,
|
||||
appOp[0], seq, attrs, viewVisibility, session.mUid,
|
||||
appOp[0], seq, attrs, viewVisibility, session.mUid, userId,
|
||||
session.mCanAddInternalSystemWindow);
|
||||
if (win.mDeathRecipient == null) {
|
||||
// Client has apparently died, so there is no reason to
|
||||
@@ -1834,8 +1850,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
|
||||
return true;
|
||||
}
|
||||
if (DevicePolicyCache.getInstance().getScreenCaptureDisabled(
|
||||
UserHandle.getUserId(w.mOwnerUid))) {
|
||||
if (DevicePolicyCache.getInstance().getScreenCaptureDisabled(w.mShowUserId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -7389,7 +7404,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
synchronized (mGlobalLock) {
|
||||
WindowState window = mWindowMap.get(token);
|
||||
if (window != null) {
|
||||
return UserHandle.getUserId(window.mOwnerUid);
|
||||
return window.mShowUserId;
|
||||
}
|
||||
return UserHandle.USER_NULL;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,6 @@ import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
@@ -269,6 +268,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
final int mAppOp;
|
||||
// UserId and appId of the owner. Don't display windows of non-current user.
|
||||
final int mOwnerUid;
|
||||
/**
|
||||
* Requested userId, if this is not equals with the userId from mOwnerUid, then this window is
|
||||
* created for secondary user.
|
||||
* Use this member instead of get userId from mOwnerUid while query for visibility.
|
||||
*/
|
||||
final int mShowUserId;
|
||||
/** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
|
||||
final boolean mOwnerCanAddInternalSystemWindow;
|
||||
final WindowId mWindowId;
|
||||
@@ -806,8 +811,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
|
||||
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
|
||||
WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
|
||||
int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
|
||||
this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
|
||||
int viewVisibility, int ownerId, int showUserId,
|
||||
boolean ownerCanAddInternalSystemWindow) {
|
||||
this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId, showUserId,
|
||||
ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
|
||||
@Override
|
||||
public void wakeUp(long time, @WakeReason int reason, String details) {
|
||||
@@ -823,8 +829,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
|
||||
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
|
||||
WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
|
||||
int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
|
||||
PowerManagerWrapper powerManagerWrapper) {
|
||||
int viewVisibility, int ownerId, int showUserId,
|
||||
boolean ownerCanAddInternalSystemWindow, PowerManagerWrapper powerManagerWrapper) {
|
||||
super(service);
|
||||
mSession = s;
|
||||
mClient = c;
|
||||
@@ -832,6 +838,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mToken = token;
|
||||
mActivityRecord = mToken.asActivityRecord();
|
||||
mOwnerUid = ownerId;
|
||||
mShowUserId = showUserId;
|
||||
mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
|
||||
mWindowId = new WindowId(this);
|
||||
mAttrs.copyFrom(a);
|
||||
@@ -3275,7 +3282,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
return win.showForAllUsers()
|
||||
|| mWmService.isCurrentProfile(UserHandle.getUserId(win.mOwnerUid));
|
||||
|| mWmService.isCurrentProfile(win.mShowUserId);
|
||||
}
|
||||
|
||||
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
|
||||
@@ -3795,7 +3802,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
|
||||
final long token = proto.start(fieldId);
|
||||
proto.write(HASH_CODE, System.identityHashCode(this));
|
||||
proto.write(USER_ID, UserHandle.getUserId(mOwnerUid));
|
||||
proto.write(USER_ID, mShowUserId);
|
||||
final CharSequence title = getWindowTag();
|
||||
if (title != null) {
|
||||
proto.write(TITLE, title.toString());
|
||||
@@ -3979,7 +3986,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mLastTitle = title;
|
||||
mWasExiting = mAnimatingExit;
|
||||
mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
|
||||
+ " u" + UserHandle.getUserId(mOwnerUid)
|
||||
+ " u" + mShowUserId
|
||||
+ " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
|
||||
}
|
||||
return mStringNameCache;
|
||||
|
||||
@@ -120,8 +120,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
IWindow iWindow = mock(IWindow.class);
|
||||
doReturn(mock(IBinder.class)).when(iWindow).asBinder();
|
||||
window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, activity,
|
||||
"Starting window", 0 /* ownerId */, false /* internalWindows */, wm,
|
||||
mock(Session.class), iWindow, mPowerManagerWrapper);
|
||||
"Starting window", 0 /* ownerId */, 0 /* userId*/, false /* internalWindows */,
|
||||
wm, mock(Session.class), iWindow, mPowerManagerWrapper);
|
||||
activity.startingWindow = window;
|
||||
}
|
||||
if (mRunnableWhenAddingSplashScreen != null) {
|
||||
|
||||
@@ -112,7 +112,7 @@ class WindowTestUtils {
|
||||
|
||||
TestWindowState(WindowManagerService service, Session session, IWindow window,
|
||||
WindowManager.LayoutParams attrs, WindowToken token) {
|
||||
super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
|
||||
super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, 0,
|
||||
false /* ownerCanAddInternalSystemWindow */);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
@@ -296,12 +297,13 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
|
||||
WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
|
||||
int ownerId, boolean ownerCanAddInternalSystemWindow) {
|
||||
return createWindow(parent, type, token, name, ownerId, ownerCanAddInternalSystemWindow,
|
||||
mWm, mMockSession, mIWindow, mSystemServicesTestRule.getPowerManagerWrapper());
|
||||
return createWindow(parent, type, token, name, ownerId, UserHandle.getUserId(ownerId),
|
||||
ownerCanAddInternalSystemWindow, mWm, mMockSession, mIWindow,
|
||||
mSystemServicesTestRule.getPowerManagerWrapper());
|
||||
}
|
||||
|
||||
static WindowState createWindow(WindowState parent, int type, WindowToken token,
|
||||
String name, int ownerId, boolean ownerCanAddInternalSystemWindow,
|
||||
String name, int ownerId, int userId, boolean ownerCanAddInternalSystemWindow,
|
||||
WindowManagerService service, Session session, IWindow iWindow,
|
||||
WindowState.PowerManagerWrapper powerManagerWrapper) {
|
||||
synchronized (service.mGlobalLock) {
|
||||
@@ -309,8 +311,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
attrs.setTitle(name);
|
||||
|
||||
final WindowState w = new WindowState(service, session, iWindow, token, parent,
|
||||
OP_NONE,
|
||||
0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow,
|
||||
OP_NONE, 0, attrs, VISIBLE, ownerId, userId,
|
||||
ownerCanAddInternalSystemWindow,
|
||||
powerManagerWrapper);
|
||||
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
|
||||
// adding it to the token...
|
||||
|
||||
Reference in New Issue
Block a user