Merge "Introduce WM#LayoutParams mWindowContextToken"
This commit is contained in:
@@ -93,6 +93,7 @@ import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
@@ -2843,6 +2844,16 @@ public interface WindowManager extends ViewManager {
|
||||
*/
|
||||
public IBinder token = null;
|
||||
|
||||
/**
|
||||
* The token of {@link android.app.WindowContext}. It is usually a
|
||||
* {@link android.app.WindowTokenClient} and is used for updating
|
||||
* {@link android.content.res.Resources} from {@link Configuration} propagated from the
|
||||
* server side.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public IBinder mWindowContextToken = null;
|
||||
|
||||
/**
|
||||
* Name of the package owning this window.
|
||||
*/
|
||||
@@ -3552,6 +3563,7 @@ public interface WindowManager extends ViewManager {
|
||||
out.writeFloat(buttonBrightness);
|
||||
out.writeInt(rotationAnimation);
|
||||
out.writeStrongBinder(token);
|
||||
out.writeStrongBinder(mWindowContextToken);
|
||||
out.writeString(packageName);
|
||||
TextUtils.writeToParcel(mTitle, out, parcelableFlags);
|
||||
out.writeInt(screenOrientation);
|
||||
@@ -3620,6 +3632,7 @@ public interface WindowManager extends ViewManager {
|
||||
buttonBrightness = in.readFloat();
|
||||
rotationAnimation = in.readInt();
|
||||
token = in.readStrongBinder();
|
||||
mWindowContextToken = in.readStrongBinder();
|
||||
packageName = in.readString();
|
||||
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
screenOrientation = in.readInt();
|
||||
@@ -3781,6 +3794,11 @@ public interface WindowManager extends ViewManager {
|
||||
// already have one.
|
||||
token = o.token;
|
||||
}
|
||||
if (mWindowContextToken == null) {
|
||||
// NOTE: token only copied if the recipient doesn't
|
||||
// already have one.
|
||||
mWindowContextToken = o.mWindowContextToken;
|
||||
}
|
||||
if (packageName == null) {
|
||||
// NOTE: packageName only copied if the recipient doesn't
|
||||
// already have one.
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UiContext;
|
||||
import android.app.ResourcesManager;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
@@ -74,23 +75,42 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
public final Context mContext;
|
||||
private final Window mParentWindow;
|
||||
|
||||
/**
|
||||
* If {@link LayoutParams#token} is {@code null} and no parent window is specified, the value
|
||||
* of {@link LayoutParams#token} will be overridden to {@code mDefaultToken}.
|
||||
*/
|
||||
private IBinder mDefaultToken;
|
||||
|
||||
/**
|
||||
* This token will be set to {@link LayoutParams#mWindowContextToken} and used to receive
|
||||
* configuration changes from the server side.
|
||||
*/
|
||||
@Nullable
|
||||
private final IBinder mWindowContextToken;
|
||||
|
||||
public WindowManagerImpl(Context context) {
|
||||
this(context, null);
|
||||
this(context, null /* parentWindow */, null /* clientToken */);
|
||||
}
|
||||
|
||||
private WindowManagerImpl(Context context, Window parentWindow) {
|
||||
private WindowManagerImpl(Context context, Window parentWindow,
|
||||
@Nullable IBinder windowContextToken) {
|
||||
mContext = context;
|
||||
mParentWindow = parentWindow;
|
||||
mWindowContextToken = windowContextToken;
|
||||
}
|
||||
|
||||
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
|
||||
return new WindowManagerImpl(mContext, parentWindow);
|
||||
return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
|
||||
}
|
||||
|
||||
public WindowManagerImpl createPresentationWindowManager(Context displayContext) {
|
||||
return new WindowManagerImpl(displayContext, mParentWindow);
|
||||
return new WindowManagerImpl(displayContext, mParentWindow, mWindowContextToken);
|
||||
}
|
||||
|
||||
/** Creates a {@link WindowManager} for a {@link android.app.WindowContext}. */
|
||||
public static WindowManager createWindowContextWindowManager(Context context) {
|
||||
final IBinder clientToken = context.getWindowContextToken();
|
||||
return new WindowManagerImpl(context, null /* parentWindow */, clientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,30 +125,27 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
|
||||
@Override
|
||||
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
|
||||
applyDefaultToken(params);
|
||||
applyTokens(params);
|
||||
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
|
||||
mContext.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
|
||||
applyDefaultToken(params);
|
||||
applyTokens(params);
|
||||
mGlobal.updateViewLayout(view, params);
|
||||
}
|
||||
|
||||
private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
|
||||
// Only use the default token if we don't have a parent window.
|
||||
if (mDefaultToken != null && mParentWindow == null) {
|
||||
if (!(params instanceof WindowManager.LayoutParams)) {
|
||||
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
|
||||
}
|
||||
|
||||
// Only use the default token if we don't already have a token.
|
||||
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
|
||||
if (wparams.token == null) {
|
||||
wparams.token = mDefaultToken;
|
||||
}
|
||||
private void applyTokens(@NonNull ViewGroup.LayoutParams params) {
|
||||
if (!(params instanceof WindowManager.LayoutParams)) {
|
||||
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
|
||||
}
|
||||
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
|
||||
// Only use the default token if we don't have a parent window and a token.
|
||||
if (mDefaultToken != null && mParentWindow == null && wparams.token == null) {
|
||||
wparams.token = mDefaultToken;
|
||||
}
|
||||
wparams.mWindowContextToken = mWindowContextToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.app;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -28,7 +29,10 @@ import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.Display;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.view.WindowManagerImpl;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
@@ -50,23 +54,41 @@ import org.junit.runner.RunWith;
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class WindowContextTest {
|
||||
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
private final WindowContext mWindowContext = createWindowContext();
|
||||
|
||||
@Test
|
||||
public void testWindowContextRelease_doRemoveWindowToken() throws Throwable {
|
||||
final Context instContext = InstrumentationRegistry.getInstrumentation()
|
||||
.getTargetContext();
|
||||
final Display display = instContext.getSystemService(DisplayManager.class)
|
||||
.getDisplay(DEFAULT_DISPLAY);
|
||||
final Context context = instContext.createDisplayContext(display);
|
||||
final WindowContext windowContext = new WindowContext(context, TYPE_APPLICATION_OVERLAY,
|
||||
null /* options */);
|
||||
|
||||
final IBinder token = windowContext.getWindowContextToken();
|
||||
|
||||
final IBinder token = mWindowContext.getWindowContextToken();
|
||||
final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
|
||||
|
||||
assertTrue("Token must be registered to WMS", wms.isWindowToken(token));
|
||||
|
||||
windowContext.release();
|
||||
mWindowContext.release();
|
||||
|
||||
assertFalse("Token must be unregistered to WMS", wms.isWindowToken(token));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWindowContextWindowManagerAttachClientToken() {
|
||||
final WindowManager windowContextWm = WindowManagerImpl
|
||||
.createWindowContextWindowManager(mWindowContext);
|
||||
final WindowManager.LayoutParams params =
|
||||
new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
final View view = new View(mWindowContext);
|
||||
windowContextWm.addView(view, params);
|
||||
});
|
||||
|
||||
assertEquals(mWindowContext.getWindowContextToken(), params.mWindowContextToken);
|
||||
}
|
||||
|
||||
private WindowContext createWindowContext() {
|
||||
final Context instContext = mInstrumentation.getTargetContext();
|
||||
final Display display = instContext.getSystemService(DisplayManager.class)
|
||||
.getDisplay(DEFAULT_DISPLAY);
|
||||
final Context context = instContext.createDisplayContext(display);
|
||||
return new WindowContext(context, TYPE_APPLICATION_OVERLAY,
|
||||
null /* options */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
@@ -46,7 +45,7 @@ import java.util.Objects;
|
||||
* {@link WindowManagerService#registerWindowContextListener(IBinder, int, int, Bundle)}
|
||||
* automatically.</li>
|
||||
* <li>When the {@link android.app.WindowContext} adds the first window to the screen via
|
||||
* {@link android.view.WindowManager#addView(View, ViewGroup.LayoutParams)},
|
||||
* {@link android.view.WindowManager#addView(View, android.view.ViewGroup.LayoutParams)},
|
||||
* {@link WindowManagerService} then updates the {@link WindowContextListenerImpl} to listen
|
||||
* to corresponding {@link WindowToken} via this controller.</li>
|
||||
* <li>When the {@link android.app.WindowContext} is GCed, it unregisters the previously
|
||||
|
||||
Reference in New Issue
Block a user