summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt8
-rw-r--r--core/java/android/view/IWindowManager.aidl9
-rw-r--r--core/java/android/view/WindowManager.java43
-rw-r--r--core/java/android/view/WindowManagerImpl.java79
-rw-r--r--core/java/android/view/WindowMetrics.java58
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java29
6 files changed, 226 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt
index f2755c9f62d6..4c3110c9189c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -54632,7 +54632,9 @@ package android.view {
}
public interface WindowManager extends android.view.ViewManager {
+ method @NonNull public default android.view.WindowMetrics getCurrentWindowMetrics();
method @Deprecated public android.view.Display getDefaultDisplay();
+ method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
method public void removeViewImmediate(android.view.View);
}
@@ -54801,6 +54803,12 @@ package android.view {
field @android.view.ViewDebug.ExportedProperty public int y;
}
+ public final class WindowMetrics {
+ ctor public WindowMetrics(@NonNull android.util.Size, @NonNull android.view.WindowInsets);
+ method @NonNull public android.util.Size getSize();
+ method @NonNull public android.view.WindowInsets getWindowInsets();
+ }
+
}
package android.view.accessibility {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5eb319f19cce..d9c502e14e68 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -32,6 +32,7 @@ import android.graphics.Region;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
+import android.view.DisplayCutout;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IDockedStackListener;
@@ -739,4 +740,12 @@ interface IWindowManager
* Called when a remote process modifies insets on a display window container.
*/
void modifyDisplayWindowInsets(int displayId, in InsetsState state);
+
+ /**
+ * Called to get the expected window insets.
+ * TODO(window-context): Remove when new insets flag is available.
+ */
+ void getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
+ out Rect outContentInsets, out Rect outStableInsets,
+ out DisplayCutout.ParcelableWrapper displayCutout);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 1333ffe272d3..c8dea43e8f4c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -437,6 +437,49 @@ public interface WindowManager extends ViewManager {
public void removeViewImmediate(View view);
/**
+ * Returns the {@link WindowMetrics} according to the current system state.
+ * <p>
+ * The metrics describe the size of the area the window would occupy with
+ * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
+ * such a window would have.
+ * <p>
+ * The value of this is based on the <b>current</b> windowing state of the system.
+ *
+ * For example, for activities in multi-window mode, the metrics returned are based on the
+ * current bounds that the user has selected for the {@link android.app.Activity Activity}'s
+ * task.
+ *
+ * @see #getMaximumWindowMetrics()
+ * @see WindowMetrics
+ */
+ default @NonNull WindowMetrics getCurrentWindowMetrics() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the largets {@link WindowMetrics} an app may expect in the current system state.
+ * <p>
+ * The metrics describe the size of the largest potential area the window might occupy with
+ * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
+ * such a window would have.
+ * <p>
+ * The value of this is based on the largest <b>potential</b> windowing state of the system.
+ *
+ * For example, for activities in multi-window mode, the metrics returned are based on the
+ * what the bounds would be if the user expanded the {@link android.app.Activity Activity}'s
+ * task to cover the entire screen.
+ *
+ * Note that this might still be smaller than the size of the physical display if certain areas
+ * of the display are not available to windows created in this {@link Context}.
+ *
+ * @see #getMaximumWindowMetrics()
+ * @see WindowMetrics
+ */
+ default @NonNull WindowMetrics getMaximumWindowMetrics() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Used to asynchronously request Keyboard Shortcuts from the focused window.
*
* @hide
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index cdeeaa438acb..4365d1f5194a 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,12 +17,17 @@
package android.view;
import android.annotation.NonNull;
+import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Size;
import com.android.internal.os.IResultReceiver;
@@ -62,6 +67,10 @@ public final class WindowManagerImpl implements WindowManager {
private IBinder mDefaultToken;
+ private boolean mIsViewAdded;
+ private View mLastView;
+ private WindowManager.LayoutParams mLastParams;
+
public WindowManagerImpl(Context context) {
this(context, null);
}
@@ -93,6 +102,9 @@ public final class WindowManagerImpl implements WindowManager {
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
+ mIsViewAdded = true;
+ mLastView = view;
+ mLastParams = (WindowManager.LayoutParams) params;
}
@Override
@@ -201,4 +213,71 @@ public final class WindowManagerImpl implements WindowManager {
}
return false;
}
+
+ @Override
+ public WindowMetrics getCurrentWindowMetrics() {
+ final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
+ final Rect bound = getCurrentBounds(context);
+
+ return new WindowMetrics(toSize(bound), computeWindowInsets());
+ }
+
+ private static Rect getCurrentBounds(Context context) {
+ synchronized (ResourcesManager.getInstance()) {
+ return context.getResources().getConfiguration().windowConfiguration.getBounds();
+ }
+ }
+
+ @Override
+ public WindowMetrics getMaximumWindowMetrics() {
+ return new WindowMetrics(toSize(getMaximumBounds()), computeWindowInsets());
+ }
+
+ private Size toSize(Rect frame) {
+ return new Size(frame.width(), frame.height());
+ }
+
+ private Rect getMaximumBounds() {
+ // TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
+ // bound after displayArea feature is finished.
+ final Display display = mContext.getDisplay();
+ final Point displaySize = new Point();
+ display.getRealSize(displaySize);
+ return new Rect(0, 0, displaySize.x, displaySize.y);
+ }
+
+ private WindowInsets computeWindowInsets() {
+ // TODO(window-context): This can only be properly implemented
+ // once we flip the new insets mode flag.
+ if (mParentWindow != null) {
+ if (mParentWindow.getDecorView().isAttachedToWindow()) {
+ return mParentWindow.getDecorView().getViewRootImpl()
+ .getWindowInsets(true /* forceConstruct */);
+ }
+ return getWindowInsetsFromServer(mParentWindow.getAttributes());
+ }
+ if (mIsViewAdded) {
+ return mLastView.getViewRootImpl().getWindowInsets(true /* forceConstruct */);
+ } else {
+ return getWindowInsetsFromServer(new WindowManager.LayoutParams());
+ }
+
+ }
+
+ private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
+ try {
+ final Rect systemWindowInsets = new Rect();
+ final Rect stableInsets = new Rect();
+ final DisplayCutout.ParcelableWrapper displayCutout =
+ new DisplayCutout.ParcelableWrapper();
+ WindowManagerGlobal.getWindowManagerService().getWindowInsets(attrs,
+ mContext.getDisplayId(), systemWindowInsets, stableInsets, displayCutout);
+ return new WindowInsets.Builder()
+ .setSystemWindowInsets(Insets.of(systemWindowInsets))
+ .setStableInsets(Insets.of(stableInsets))
+ .setDisplayCutout(displayCutout.get()).build();
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
}
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
new file mode 100644
index 000000000000..8caf5b7fc725
--- /dev/null
+++ b/core/java/android/view/WindowMetrics.java
@@ -0,0 +1,58 @@
+/*
+ * 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.view;
+
+import android.annotation.NonNull;
+import android.util.Size;
+
+/**
+ * Metrics about a Window, consisting of the size and {@link WindowInsets}.
+ * <p>
+ * This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and
+ * {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ * @see WindowInsets#getInsets(int)
+ * @see WindowManager#getCurrentWindowMetrics()
+ * @see WindowManager#getMaximumWindowMetrics()
+ */
+public final class WindowMetrics {
+ private final @NonNull Size mSize;
+ private final @NonNull WindowInsets mWindowInsets;
+
+ public WindowMetrics(@NonNull Size size, @NonNull WindowInsets windowInsets) {
+ mSize = size;
+ mWindowInsets = windowInsets;
+ }
+
+ /**
+ * Returns the size of the window.
+ *
+ * @return window size in pixel.
+ */
+ public @NonNull Size getSize() {
+ return mSize;
+ }
+
+ /**
+ * Returns the {@link WindowInsets} of the window.
+ *
+ * @return the {@link WindowInsets} of the window.
+ */
+ public @NonNull WindowInsets getWindowInsets() {
+ return mWindowInsets;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e82394c5ae27..8d4ad28972e9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7927,4 +7927,33 @@ public class WindowManagerService extends IWindowManager.Stub
return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
|| mForceDesktopModeOnExternalDisplays;
}
+
+ @Override
+ public void getWindowInsets(WindowManager.LayoutParams attrs,
+ int displayId, Rect outContentInsets, Rect outStableInsets,
+ DisplayCutout.ParcelableWrapper displayCutout) {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ final WindowToken windowToken = dc.getWindowToken(attrs.token);
+ final ActivityRecord activity;
+ if (windowToken != null && windowToken.asActivityRecord() != null) {
+ activity = windowToken.asActivityRecord();
+ } else {
+ activity = null;
+ }
+ final Rect taskBounds = new Rect();
+ final boolean floatingStack;
+ if (activity != null && activity.getTask() != null) {
+ final Task task = activity.getTask();
+ task.getBounds(taskBounds);
+ floatingStack = task.isFloating();
+ } else {
+ floatingStack = false;
+ }
+ final DisplayFrames displayFrames = dc.mDisplayFrames;
+ final DisplayPolicy policy = dc.getDisplayPolicy();
+ policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
+ new Rect(), outContentInsets, outStableInsets, displayCutout);
+ }
+ }
}