Merge "Allow WPS to create windows with multiple type" into sc-v2-dev am: cc2f80f5a0
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15125751 Change-Id: I240b960c6689ed8caa1bf4e3c15853f23410e991
This commit is contained in:
@@ -3323,7 +3323,7 @@ package android.window {
|
|||||||
ctor public WindowProviderService();
|
ctor public WindowProviderService();
|
||||||
method public final void attachToWindowToken(@NonNull android.os.IBinder);
|
method public final void attachToWindowToken(@NonNull android.os.IBinder);
|
||||||
method @NonNull public int getInitialDisplayId();
|
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();
|
method public abstract int getWindowType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ public abstract class AbstractInputMethodService extends WindowProviderService
|
|||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public final Bundle getWindowContextOptions() {
|
public final Bundle getWindowContextOptions() {
|
||||||
return null;
|
return super.getWindowContextOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @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_FULLSCREEN;
|
||||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
||||||
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
|
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_INSET_DECOR;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
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.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||||
|
import static android.window.WindowProvider.KEY_IS_WINDOW_PROVIDER_SERVICE;
|
||||||
|
|
||||||
import android.annotation.CallbackExecutor;
|
import android.annotation.CallbackExecutor;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -36,7 +39,9 @@ import android.graphics.Region;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.StrictMode;
|
||||||
import android.window.WindowContext;
|
import android.window.WindowContext;
|
||||||
|
import android.window.WindowProvider;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.os.IResultReceiver;
|
import com.android.internal.os.IResultReceiver;
|
||||||
@@ -145,6 +150,7 @@ public final class WindowManagerImpl implements WindowManager {
|
|||||||
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
|
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
|
||||||
}
|
}
|
||||||
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
|
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.
|
// Only use the default token if we don't have a parent window and a token.
|
||||||
if (mDefaultToken != null && mParentWindow == null && wparams.token == null) {
|
if (mDefaultToken != null && mParentWindow == null && wparams.token == null) {
|
||||||
wparams.token = mDefaultToken;
|
wparams.token = mDefaultToken;
|
||||||
@@ -152,6 +158,35 @@ public final class WindowManagerImpl implements WindowManager {
|
|||||||
wparams.mWindowContextToken = mWindowContextToken;
|
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
|
@Override
|
||||||
public void removeView(View view) {
|
public void removeView(View view) {
|
||||||
mGlobal.removeView(view, false);
|
mGlobal.removeView(view, false);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.content.Context;
|
|||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -42,29 +43,33 @@ import java.lang.ref.Reference;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@UiContext
|
@UiContext
|
||||||
public class WindowContext extends ContextWrapper {
|
public class WindowContext extends ContextWrapper implements WindowProvider {
|
||||||
private final WindowManager mWindowManager;
|
private final WindowManager mWindowManager;
|
||||||
private final @WindowManager.LayoutParams.WindowType int mType;
|
@WindowManager.LayoutParams.WindowType
|
||||||
private final @Nullable Bundle mOptions;
|
private final int mType;
|
||||||
|
@Nullable
|
||||||
|
private final Bundle mOptions;
|
||||||
private final ComponentCallbacksController mCallbacksController =
|
private final ComponentCallbacksController mCallbacksController =
|
||||||
new ComponentCallbacksController();
|
new ComponentCallbacksController();
|
||||||
private final WindowContextController mController;
|
private final WindowContextController mController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
|
* Default implementation of {@link WindowContext}
|
||||||
* the token.
|
* <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 base Base {@link Context} for this new instance.
|
||||||
* @param type Window type to be used with this context.
|
* @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
|
* @param options A bundle used to pass window-related options.
|
||||||
* 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);
|
|
||||||
* @see DisplayAreaInfo#rootDisplayAreaId
|
* @see DisplayAreaInfo#rootDisplayAreaId
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
|
public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
|
||||||
super(base);
|
super(base);
|
||||||
@@ -110,10 +115,13 @@ public class WindowContext extends ContextWrapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
mCallbacksController.clearCallbacks();
|
try {
|
||||||
// Called to the base ContextImpl to do final clean-up.
|
mCallbacksController.clearCallbacks();
|
||||||
getBaseContext().destroy();
|
// Called to the base ContextImpl to do final clean-up.
|
||||||
Reference.reachabilityFence(this);
|
getBaseContext().destroy();
|
||||||
|
} finally {
|
||||||
|
Reference.reachabilityFence(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,4 +138,15 @@ public class WindowContext extends ContextWrapper {
|
|||||||
void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
|
void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
mCallbacksController.dispatchConfigurationChanged(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}.
|
* {@link WindowContext}, but is represented as {@link Service}.
|
||||||
*
|
*
|
||||||
* @see android.inputmethodservice.InputMethodService
|
* @see android.inputmethodservice.InputMethodService
|
||||||
* @see android.accessibilityservice.AccessibilityService
|
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@TestApi
|
@TestApi
|
||||||
@UiContext
|
@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 WindowTokenClient mWindowToken = new WindowTokenClient();
|
||||||
private final WindowContextController mController = new WindowContextController(mWindowToken);
|
private final WindowContextController mController = new WindowContextController(mWindowToken);
|
||||||
private WindowManager mWindowManager;
|
private WindowManager mWindowManager;
|
||||||
private boolean mInitialized;
|
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
|
* 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)}
|
* used similar to {@code type} of {@link Context#createWindowContext(int, Bundle)}
|
||||||
*
|
*
|
||||||
@@ -68,15 +73,24 @@ public abstract class WindowProviderService extends Service {
|
|||||||
@SuppressLint("OnNameExpected")
|
@SuppressLint("OnNameExpected")
|
||||||
// Suppress the lint because it is not a callback and users should provide window type
|
// Suppress the lint because it is not a callback and users should provide window type
|
||||||
// so we cannot make it final.
|
// so we cannot make it final.
|
||||||
public abstract @WindowType int getWindowType();
|
@WindowType
|
||||||
|
@Override
|
||||||
|
public abstract int getWindowType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the option of this {@link WindowProviderService}.
|
* Returns the option of this {@link WindowProviderService}.
|
||||||
* Default is {@code null}. The inheriting class can implement this method to provide the
|
* <p>
|
||||||
* customization {@code option} of the window. It is used similar to {@code options} of
|
* The inheriting class can implement this method to provide the customization {@code option} of
|
||||||
* {@link Context#createWindowContext(int, Bundle)}
|
* 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)}
|
||||||
* @see 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
|
* @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
|
// 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.
|
// launch option. Also, the return value of this API is null by default.
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@CallSuper
|
||||||
|
@Override
|
||||||
public Bundle getWindowContextOptions() {
|
public Bundle getWindowContextOptions() {
|
||||||
return null;
|
return mOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
|||||||
onConfigurationChanged(newConfig, newDisplayId, true /* shouldReportConfigChange */);
|
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.
|
* 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.WindowManagerPolicyConstants.NAV_BAR_INVALID;
|
||||||
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
|
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.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_ADD_REMOVE;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
|
||||||
@@ -1730,16 +1731,22 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
&& mWindowContextListenerController.hasListener(windowContextToken)) {
|
&& mWindowContextListenerController.hasListener(windowContextToken)) {
|
||||||
final int windowContextType = mWindowContextListenerController
|
final int windowContextType = mWindowContextListenerController
|
||||||
.getWindowType(windowContextToken);
|
.getWindowType(windowContextToken);
|
||||||
|
final Bundle options = mWindowContextListenerController
|
||||||
|
.getOptions(windowContextToken);
|
||||||
if (type != windowContextType) {
|
if (type != windowContextType) {
|
||||||
ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
|
ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
|
||||||
+ " LayoutParams.type should match! Type from LayoutParams is %d,"
|
+ " LayoutParams.type should match! Type from LayoutParams is %d,"
|
||||||
+ " but type from WindowContext is %d", type, windowContextType);
|
+ " 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!
|
// From now on, no exceptions or errors allowed!
|
||||||
|
|||||||
Reference in New Issue
Block a user