Extract WindowMetrics logic to WindowMetricsController
We would add some mechanisms to improve WindowMetrics performance, which will introduce more WindowMetrics logic. Extracting it to a separate module will make the WindowMetrics logic easier to maintain. No logic changes. Bug: 187712731 Test: atest WindowMetricsActivityTests WindowMetricsWindowContextTests Change-Id: Ic35501efc4e2b73af80593f3b1911be35c2f0e48
This commit is contained in:
@@ -16,11 +16,8 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
import static android.window.WindowProviderService.isWindowProviderService;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
@@ -28,12 +25,9 @@ import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UiContext;
|
||||
import android.app.ResourcesManager;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -42,6 +36,7 @@ import android.os.StrictMode;
|
||||
import android.window.ITaskFpsCallback;
|
||||
import android.window.TaskFpsCallback;
|
||||
import android.window.WindowContext;
|
||||
import android.window.WindowMetricsController;
|
||||
import android.window.WindowProvider;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -49,7 +44,6 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -107,6 +101,10 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
private final ArrayList<OnFpsCallbackListenerProxy> mOnFpsCallbackListenerProxies =
|
||||
new ArrayList<>();
|
||||
|
||||
/** A controller to handle {@link WindowMetrics} related APIs */
|
||||
@NonNull
|
||||
private final WindowMetricsController mWindowMetricsController;
|
||||
|
||||
public WindowManagerImpl(Context context) {
|
||||
this(context, null /* parentWindow */, null /* clientToken */);
|
||||
}
|
||||
@@ -116,6 +114,7 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
mContext = context;
|
||||
mParentWindow = parentWindow;
|
||||
mWindowContextToken = windowContextToken;
|
||||
mWindowMetricsController = new WindowMetricsController(mContext);
|
||||
}
|
||||
|
||||
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
|
||||
@@ -293,112 +292,18 @@ public final class WindowManagerImpl implements WindowManager {
|
||||
|
||||
@Override
|
||||
public WindowMetrics getCurrentWindowMetrics() {
|
||||
final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
|
||||
final Rect bounds = getCurrentBounds(context);
|
||||
|
||||
return new WindowMetrics(bounds, computeWindowInsets(bounds));
|
||||
}
|
||||
|
||||
private static Rect getCurrentBounds(Context context) {
|
||||
synchronized (ResourcesManager.getInstance()) {
|
||||
return context.getResources().getConfiguration().windowConfiguration.getBounds();
|
||||
}
|
||||
return mWindowMetricsController.getCurrentWindowMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowMetrics getMaximumWindowMetrics() {
|
||||
final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
|
||||
final Rect maxBounds = getMaximumBounds(context);
|
||||
|
||||
return new WindowMetrics(maxBounds, computeWindowInsets(maxBounds));
|
||||
}
|
||||
|
||||
private static Rect getMaximumBounds(Context context) {
|
||||
synchronized (ResourcesManager.getInstance()) {
|
||||
return context.getResources().getConfiguration().windowConfiguration.getMaxBounds();
|
||||
}
|
||||
}
|
||||
|
||||
private WindowInsets computeWindowInsets(Rect bounds) {
|
||||
// Initialize params which used for obtaining all system insets.
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
final Context context = (mParentWindow != null) ? mParentWindow.getContext() : mContext;
|
||||
params.token = Context.getToken(context);
|
||||
return getWindowInsetsFromServerForCurrentDisplay(params, bounds);
|
||||
}
|
||||
|
||||
private WindowInsets getWindowInsetsFromServerForCurrentDisplay(
|
||||
WindowManager.LayoutParams attrs, Rect bounds) {
|
||||
final Configuration config = mContext.getResources().getConfiguration();
|
||||
return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), attrs, bounds,
|
||||
config.isScreenRound(), config.windowConfiguration.getWindowingMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves WindowInsets for the given context and display, given the window bounds.
|
||||
*
|
||||
* @param displayId the ID of the logical display to calculate insets for
|
||||
* @param attrs the LayoutParams for the calling app
|
||||
* @param bounds the window bounds to calculate insets for
|
||||
* @param isScreenRound if the display identified by displayId is round
|
||||
* @param windowingMode the windowing mode of the window to calculate insets for
|
||||
* @return WindowInsets calculated for the given window bounds, on the given display
|
||||
*/
|
||||
private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId,
|
||||
WindowManager.LayoutParams attrs, Rect bounds, boolean isScreenRound,
|
||||
int windowingMode) {
|
||||
try {
|
||||
final InsetsState insetsState = new InsetsState();
|
||||
final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
|
||||
.getWindowInsets(attrs, displayId, insetsState);
|
||||
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
|
||||
isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
|
||||
SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode,
|
||||
null /* typeSideMap */);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
return mWindowMetricsController.getMaximumWindowMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
|
||||
List<DisplayInfo> possibleDisplayInfos;
|
||||
try {
|
||||
possibleDisplayInfos = WindowManagerGlobal.getWindowManagerService()
|
||||
.getPossibleDisplayInfo(displayId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
Set<WindowMetrics> maxMetrics = new HashSet<>();
|
||||
WindowInsets windowInsets;
|
||||
DisplayInfo currentDisplayInfo;
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
for (int i = 0; i < possibleDisplayInfos.size(); i++) {
|
||||
currentDisplayInfo = possibleDisplayInfos.get(i);
|
||||
|
||||
// Calculate max bounds for this rotation and state.
|
||||
Rect maxBounds = new Rect(0, 0, currentDisplayInfo.logicalWidth,
|
||||
currentDisplayInfo.logicalHeight);
|
||||
|
||||
// Calculate insets for the rotated max bounds.
|
||||
final boolean isScreenRound = (currentDisplayInfo.flags & Display.FLAG_ROUND) != 0;
|
||||
// Initialize insets based upon display rotation. Note any window-provided insets
|
||||
// will not be set.
|
||||
windowInsets = getWindowInsetsFromServerForDisplay(
|
||||
currentDisplayInfo.displayId, params,
|
||||
new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
|
||||
currentDisplayInfo.getNaturalHeight()), isScreenRound,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
// Set the hardware-provided insets.
|
||||
windowInsets = new WindowInsets.Builder(windowInsets).setRoundedCorners(
|
||||
currentDisplayInfo.roundedCorners)
|
||||
.setDisplayCutout(currentDisplayInfo.displayCutout).build();
|
||||
|
||||
maxMetrics.add(new WindowMetrics(maxBounds, windowInsets));
|
||||
}
|
||||
return maxMetrics;
|
||||
return mWindowMetricsController.getPossibleMaximumWindowMetrics(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
172
core/java/android/window/WindowMetricsController.java
Normal file
172
core/java/android/window/WindowMetricsController.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ResourcesManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.InsetsState;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.view.WindowMetrics;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A controller to handle {@link android.view.WindowMetrics} related APIs, which are
|
||||
* <ol>
|
||||
* <li>{@link WindowManager#getCurrentWindowMetrics()}</li>
|
||||
* <li>{@link WindowManager#getMaximumWindowMetrics()}</li>
|
||||
* <li>{@link WindowManager#getPossibleMaximumWindowMetrics(int)}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class WindowMetricsController {
|
||||
private final Context mContext;
|
||||
|
||||
public WindowMetricsController(@NonNull Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/** @see WindowManager#getCurrentWindowMetrics() */
|
||||
public WindowMetrics getCurrentWindowMetrics() {
|
||||
final Rect bounds = getCurrentBounds(mContext);
|
||||
|
||||
// TODO(b/187712731): Provide density for WindowMetrics.
|
||||
return new WindowMetrics(bounds, computeWindowInsets(bounds));
|
||||
}
|
||||
|
||||
private static Rect getCurrentBounds(Context context) {
|
||||
synchronized (ResourcesManager.getInstance()) {
|
||||
return context.getResources().getConfiguration().windowConfiguration.getBounds();
|
||||
}
|
||||
}
|
||||
|
||||
/** @see WindowManager#getMaximumWindowMetrics() */
|
||||
public WindowMetrics getMaximumWindowMetrics() {
|
||||
final Rect maxBounds = getMaximumBounds(mContext);
|
||||
|
||||
// TODO(b/187712731): Provide density for WindowMetrics.
|
||||
return new WindowMetrics(maxBounds, computeWindowInsets(maxBounds));
|
||||
}
|
||||
|
||||
private static Rect getMaximumBounds(Context context) {
|
||||
synchronized (ResourcesManager.getInstance()) {
|
||||
return context.getResources().getConfiguration().windowConfiguration.getMaxBounds();
|
||||
}
|
||||
}
|
||||
|
||||
private WindowInsets computeWindowInsets(Rect bounds) {
|
||||
// Initialize params which used for obtaining all system insets.
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
params.token = Context.getToken(mContext);
|
||||
return getWindowInsetsFromServerForCurrentDisplay(params, bounds);
|
||||
}
|
||||
|
||||
private WindowInsets getWindowInsetsFromServerForCurrentDisplay(
|
||||
WindowManager.LayoutParams attrs, Rect bounds) {
|
||||
final boolean isScreenRound;
|
||||
final int windowingMode;
|
||||
synchronized (ResourcesManager.getInstance()) {
|
||||
final Configuration config = mContext.getResources().getConfiguration();
|
||||
isScreenRound = config.isScreenRound();
|
||||
windowingMode = config.windowConfiguration.getWindowingMode();
|
||||
}
|
||||
return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), attrs, bounds,
|
||||
isScreenRound, windowingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves WindowInsets for the given context and display, given the window bounds.
|
||||
*
|
||||
* @param displayId the ID of the logical display to calculate insets for
|
||||
* @param attrs the LayoutParams for the calling app
|
||||
* @param bounds the window bounds to calculate insets for
|
||||
* @param isScreenRound if the display identified by displayId is round
|
||||
* @param windowingMode the windowing mode of the window to calculate insets for
|
||||
* @return WindowInsets calculated for the given window bounds, on the given display
|
||||
*/
|
||||
private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId,
|
||||
WindowManager.LayoutParams attrs, Rect bounds, boolean isScreenRound,
|
||||
int windowingMode) {
|
||||
try {
|
||||
final InsetsState insetsState = new InsetsState();
|
||||
final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
|
||||
.getWindowInsets(attrs, displayId, insetsState);
|
||||
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
|
||||
isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
|
||||
SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode,
|
||||
null /* typeSideMap */);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/** @see WindowManager#getPossibleMaximumWindowMetrics(int) */
|
||||
@NonNull
|
||||
public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
|
||||
List<DisplayInfo> possibleDisplayInfos;
|
||||
try {
|
||||
possibleDisplayInfos = WindowManagerGlobal.getWindowManagerService()
|
||||
.getPossibleDisplayInfo(displayId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
Set<WindowMetrics> maxMetrics = new HashSet<>();
|
||||
WindowInsets windowInsets;
|
||||
DisplayInfo currentDisplayInfo;
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
||||
for (int i = 0; i < possibleDisplayInfos.size(); i++) {
|
||||
currentDisplayInfo = possibleDisplayInfos.get(i);
|
||||
|
||||
// Calculate max bounds for this rotation and state.
|
||||
Rect maxBounds = new Rect(0, 0, currentDisplayInfo.logicalWidth,
|
||||
currentDisplayInfo.logicalHeight);
|
||||
|
||||
// Calculate insets for the rotated max bounds.
|
||||
final boolean isScreenRound = (currentDisplayInfo.flags & Display.FLAG_ROUND) != 0;
|
||||
// Initialize insets based upon display rotation. Note any window-provided insets
|
||||
// will not be set.
|
||||
windowInsets = getWindowInsetsFromServerForDisplay(
|
||||
currentDisplayInfo.displayId, params,
|
||||
new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
|
||||
currentDisplayInfo.getNaturalHeight()), isScreenRound,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
// Set the hardware-provided insets.
|
||||
windowInsets = new WindowInsets.Builder(windowInsets).setRoundedCorners(
|
||||
currentDisplayInfo.roundedCorners)
|
||||
.setDisplayCutout(currentDisplayInfo.displayCutout).build();
|
||||
|
||||
maxMetrics.add(new WindowMetrics(maxBounds, windowInsets));
|
||||
}
|
||||
return maxMetrics;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user