Merge "Allow WPS to create windows with multiple type" into sc-v2-dev am: cc2f80f5a0 am: ddfa753ff0
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15125751 Change-Id: I3e6c55f06e97c0a5e72cac7b181db4d0e2d0e624
This commit is contained in:
@@ -3338,7 +3338,7 @@ package android.window {
|
||||
ctor public WindowProviderService();
|
||||
method public final void attachToWindowToken(@NonNull android.os.IBinder);
|
||||
method @NonNull public int getInitialDisplayId();
|
||||
method @Nullable public android.os.Bundle getWindowContextOptions();
|
||||
method @CallSuper @Nullable public android.os.Bundle getWindowContextOptions();
|
||||
method public abstract int getWindowType();
|
||||
}
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ public abstract class AbstractInputMethodService extends WindowProviderService
|
||||
@Override
|
||||
@Nullable
|
||||
public final Bundle getWindowContextOptions() {
|
||||
return null;
|
||||
return super.getWindowContextOptions();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
|
||||
@@ -19,9 +19,12 @@ package android.view;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
import static android.window.WindowProvider.KEY_IS_WINDOW_PROVIDER_SERVICE;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
@@ -36,7 +39,9 @@ import android.graphics.Region;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.StrictMode;
|
||||
import android.window.WindowContext;
|
||||
import android.window.WindowProvider;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
@@ -145,6 +150,7 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
|
||||
}
|
||||
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
|
||||
assertWindowContextTypeMatches(wparams.type);
|
||||
// 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;
|
||||
@@ -152,6 +158,35 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
wparams.mWindowContextToken = mWindowContextToken;
|
||||
}
|
||||
|
||||
private void assertWindowContextTypeMatches(@LayoutParams.WindowType int windowType) {
|
||||
if (!(mContext instanceof WindowProvider)) {
|
||||
return;
|
||||
}
|
||||
// Don't need to check sub-window type because sub window should be allowed to be attached
|
||||
// to the parent window.
|
||||
if (windowType >= FIRST_SUB_WINDOW && windowType <= LAST_SUB_WINDOW) {
|
||||
return;
|
||||
}
|
||||
final WindowProvider windowProvider = (WindowProvider) mContext;
|
||||
if (windowProvider.getWindowType() == windowType) {
|
||||
return;
|
||||
}
|
||||
IllegalArgumentException exception = new IllegalArgumentException("Window type mismatch."
|
||||
+ " Window Context's window type is " + windowProvider.getWindowType()
|
||||
+ ", while LayoutParams' type is set to " + windowType + "."
|
||||
+ " Please create another Window Context via"
|
||||
+ " createWindowContext(getDisplay(), " + windowType + ", null)"
|
||||
+ " to add window with type:" + windowType);
|
||||
if (!windowProvider.getWindowContextOptions().getBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE,
|
||||
false)) {
|
||||
throw exception;
|
||||
}
|
||||
// Throw IncorrectCorrectViolation if the Window Context is allowed to provide multiple
|
||||
// window types. Usually it's because the Window Context is a WindowProviderService.
|
||||
StrictMode.onIncorrectContextUsed("WindowContext's window type must"
|
||||
+ " match type in WindowManager.LayoutParams", exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
mGlobal.removeView(view, false);
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -42,29 +43,33 @@ import java.lang.ref.Reference;
|
||||
* @hide
|
||||
*/
|
||||
@UiContext
|
||||
public class WindowContext extends ContextWrapper {
|
||||
public class WindowContext extends ContextWrapper implements WindowProvider {
|
||||
private final WindowManager mWindowManager;
|
||||
private final @WindowManager.LayoutParams.WindowType int mType;
|
||||
private final @Nullable Bundle mOptions;
|
||||
@WindowManager.LayoutParams.WindowType
|
||||
private final int mType;
|
||||
@Nullable
|
||||
private final Bundle mOptions;
|
||||
private final ComponentCallbacksController mCallbacksController =
|
||||
new ComponentCallbacksController();
|
||||
private final WindowContextController mController;
|
||||
|
||||
/**
|
||||
* Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
|
||||
* the token.
|
||||
* Default implementation of {@link WindowContext}
|
||||
* <p>
|
||||
* Note that the users should call {@link Context#createWindowContext(Display, int, Bundle)}
|
||||
* to create a {@link WindowContext} instead of using this constructor
|
||||
* </p><p>
|
||||
* Example usage:
|
||||
* <pre class="prettyprint">
|
||||
* Bundle options = new Bundle();
|
||||
* options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId);
|
||||
* Context windowContext = context.createWindowContext(display, windowType, options);
|
||||
* </pre></p>
|
||||
*
|
||||
* @param base Base {@link Context} for this new instance.
|
||||
* @param type Window type to be used with this context.
|
||||
* @param options A bundle used to pass window-related options. For example, on device with
|
||||
* multiple DisplayAreaGroups, one may specify the RootDisplayArea for the window
|
||||
* using {@link DisplayAreaOrganizer#KEY_ROOT_DISPLAY_AREA_ID} in the options.
|
||||
* Example usage:
|
||||
* Bundle options = new Bundle();
|
||||
* options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId);
|
||||
* Context windowContext = context.createWindowContext(display, type, options);
|
||||
* @param base Base {@link Context} for this new instance.
|
||||
* @param type Window type to be used with this context.
|
||||
* @param options A bundle used to pass window-related options.
|
||||
* @see DisplayAreaInfo#rootDisplayAreaId
|
||||
* @hide
|
||||
*/
|
||||
public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
|
||||
super(base);
|
||||
@@ -110,10 +115,13 @@ public class WindowContext extends ContextWrapper {
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
mCallbacksController.clearCallbacks();
|
||||
// Called to the base ContextImpl to do final clean-up.
|
||||
getBaseContext().destroy();
|
||||
Reference.reachabilityFence(this);
|
||||
try {
|
||||
mCallbacksController.clearCallbacks();
|
||||
// Called to the base ContextImpl to do final clean-up.
|
||||
getBaseContext().destroy();
|
||||
} finally {
|
||||
Reference.reachabilityFence(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,4 +138,15 @@ public class WindowContext extends ContextWrapper {
|
||||
void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
mCallbacksController.dispatchConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Bundle getWindowContextOptions() {
|
||||
return mOptions;
|
||||
}
|
||||
}
|
||||
|
||||
39
core/java/android/window/WindowProvider.java
Normal file
39
core/java/android/window/WindowProvider.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.window;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager.LayoutParams.WindowType;
|
||||
|
||||
/**
|
||||
* An interface to provide a non-activity window.
|
||||
* Examples are {@link WindowContext} and {@link WindowProviderService}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface WindowProvider {
|
||||
/** @hide */
|
||||
String KEY_IS_WINDOW_PROVIDER_SERVICE = "android.windowContext.isWindowProviderService";
|
||||
|
||||
/** Gets the window type of this provider */
|
||||
@WindowType
|
||||
int getWindowType();
|
||||
|
||||
/** Gets the launch options of this provider */
|
||||
@Nullable
|
||||
Bundle getWindowContextOptions();
|
||||
}
|
||||
@@ -42,21 +42,26 @@ import android.view.WindowManagerImpl;
|
||||
* {@link WindowContext}, but is represented as {@link Service}.
|
||||
*
|
||||
* @see android.inputmethodservice.InputMethodService
|
||||
* @see android.accessibilityservice.AccessibilityService
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@UiContext
|
||||
public abstract class WindowProviderService extends Service {
|
||||
public abstract class WindowProviderService extends Service implements WindowProvider {
|
||||
|
||||
private final Bundle mOptions;
|
||||
private final WindowTokenClient mWindowToken = new WindowTokenClient();
|
||||
private final WindowContextController mController = new WindowContextController(mWindowToken);
|
||||
private WindowManager mWindowManager;
|
||||
private boolean mInitialized;
|
||||
|
||||
public WindowProviderService() {
|
||||
mOptions = new Bundle();
|
||||
mOptions.putBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this {@link WindowProviderService}.
|
||||
* Returns the window type of this {@link WindowProviderService}.
|
||||
* Each inheriting class must implement this method to provide the type of the window. It is
|
||||
* used similar to {@code type} of {@link Context#createWindowContext(int, Bundle)}
|
||||
*
|
||||
@@ -68,15 +73,24 @@ public abstract class WindowProviderService extends Service {
|
||||
@SuppressLint("OnNameExpected")
|
||||
// Suppress the lint because it is not a callback and users should provide window type
|
||||
// so we cannot make it final.
|
||||
public abstract @WindowType int getWindowType();
|
||||
@WindowType
|
||||
@Override
|
||||
public abstract int getWindowType();
|
||||
|
||||
/**
|
||||
* Returns the option of this {@link WindowProviderService}.
|
||||
* Default is {@code null}. The inheriting class can implement this method to provide the
|
||||
* customization {@code option} of the window. It is used similar to {@code options} of
|
||||
* {@link Context#createWindowContext(int, Bundle)}
|
||||
*
|
||||
* @see Context#createWindowContext(int, Bundle)
|
||||
* <p>
|
||||
* The inheriting class can implement this method to provide the customization {@code option} of
|
||||
* the window, but must be based on this method's returned value.
|
||||
* It is used similar to {@code options} of {@link Context#createWindowContext(int, Bundle)}
|
||||
* </p>
|
||||
* <pre class="prettyprint">
|
||||
* public Bundle getWindowContextOptions() {
|
||||
* final Bundle options = super.getWindowContextOptions();
|
||||
* options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId);
|
||||
* return options;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -85,8 +99,10 @@ public abstract class WindowProviderService extends Service {
|
||||
// Suppress the lint because it is not a callback and users may override this API to provide
|
||||
// launch option. Also, the return value of this API is null by default.
|
||||
@Nullable
|
||||
@CallSuper
|
||||
@Override
|
||||
public Bundle getWindowContextOptions() {
|
||||
return null;
|
||||
return mOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,6 +94,8 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
||||
onConfigurationChanged(newConfig, newDisplayId, true /* shouldReportConfigChange */);
|
||||
}
|
||||
|
||||
// TODO(b/192048581): rewrite this method based on WindowContext and WindowProviderService
|
||||
// are inherited from WindowProvider.
|
||||
/**
|
||||
* Called when {@link Configuration} updates from the server side receive.
|
||||
*
|
||||
|
||||
@@ -87,6 +87,7 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
|
||||
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
|
||||
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN;
|
||||
import static android.window.WindowContext.KEY_IS_WINDOW_PROVIDER_SERVICE;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
|
||||
@@ -1730,16 +1731,22 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
&& mWindowContextListenerController.hasListener(windowContextToken)) {
|
||||
final int windowContextType = mWindowContextListenerController
|
||||
.getWindowType(windowContextToken);
|
||||
final Bundle options = mWindowContextListenerController
|
||||
.getOptions(windowContextToken);
|
||||
if (type != windowContextType) {
|
||||
ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
|
||||
+ " LayoutParams.type should match! Type from LayoutParams is %d,"
|
||||
+ " but type from WindowContext is %d", type, windowContextType);
|
||||
return WindowManagerGlobal.ADD_INVALID_TYPE;
|
||||
// We allow WindowProviderService to add window other than windowContextType,
|
||||
// but the WindowProviderService won't be associated with the window's
|
||||
// WindowToken.
|
||||
if (!options.getBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, false)) {
|
||||
return WindowManagerGlobal.ADD_INVALID_TYPE;
|
||||
}
|
||||
} else {
|
||||
mWindowContextListenerController.registerWindowContainerListener(
|
||||
windowContextToken, token, callingUid, type, options);
|
||||
}
|
||||
final Bundle options = mWindowContextListenerController
|
||||
.getOptions(windowContextToken);
|
||||
mWindowContextListenerController.registerWindowContainerListener(
|
||||
windowContextToken, token, callingUid, type, options);
|
||||
}
|
||||
|
||||
// From now on, no exceptions or errors allowed!
|
||||
|
||||
Reference in New Issue
Block a user