Introducing WindowConfiguration
Used to house configurations that don't affect resources and that we don't want to communicate to apps, but need to be propagated along side Configuration. Test: bit FrameworksServicesTests:com.android.server.wm.WindowConfigurationTests Test: adb shell am instrument -w -e package com.android.server.wm com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner Change-Id: I97de3efbe6d5e1d3b07156a8cfbce9be5eae5cb5
This commit is contained in:
19
core/java/android/app/WindowConfiguration.aidl
Normal file
19
core/java/android/app/WindowConfiguration.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.app;
|
||||
|
||||
parcelable WindowConfiguration;
|
||||
225
core/java/android/app/WindowConfiguration.java
Normal file
225
core/java/android/app/WindowConfiguration.java
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.app;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Class that contains windowing configuration/state for other objects that contain windows directly
|
||||
* or indirectly. E.g. Activities, Task, Displays, ...
|
||||
* The test class is {@link com.android.server.wm.WindowConfigurationTests} which must be kept
|
||||
* up-to-date and ran anytime changes are made to this class.
|
||||
* @hide
|
||||
*/
|
||||
public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
|
||||
|
||||
/**
|
||||
* {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
|
||||
* {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
|
||||
* the display level. Lower levels can override these values to provide custom bounds to enforce
|
||||
* features such as a max aspect ratio.
|
||||
*/
|
||||
private Rect mAppBounds;
|
||||
|
||||
@IntDef(flag = true,
|
||||
value = {
|
||||
WINDOW_CONFIG_APP_BOUNDS,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface WindowConfig {}
|
||||
|
||||
/** Bit that indicates that the {@link #mAppBounds} changed. */
|
||||
public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0;
|
||||
|
||||
public WindowConfiguration() {
|
||||
unset();
|
||||
}
|
||||
|
||||
public WindowConfiguration(WindowConfiguration configuration) {
|
||||
setTo(configuration);
|
||||
}
|
||||
|
||||
private WindowConfiguration(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mAppBounds, flags);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel source) {
|
||||
mAppBounds = source.readParcelable(Rect.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<WindowConfiguration> CREATOR = new Creator<WindowConfiguration>() {
|
||||
@Override
|
||||
public WindowConfiguration createFromParcel(Parcel in) {
|
||||
return new WindowConfiguration(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowConfiguration[] newArray(int size) {
|
||||
return new WindowConfiguration[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set {@link #mAppBounds} to the input Rect.
|
||||
* @param rect The rect value to set {@link #mAppBounds} to.
|
||||
* @see #getAppBounds()
|
||||
*/
|
||||
public void setAppBounds(Rect rect) {
|
||||
if (rect == null) {
|
||||
mAppBounds = null;
|
||||
return;
|
||||
}
|
||||
|
||||
setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setAppBounds(Rect)
|
||||
* @see #getAppBounds()
|
||||
*/
|
||||
public void setAppBounds(int left, int top, int right, int bottom) {
|
||||
if (mAppBounds == null) {
|
||||
mAppBounds = new Rect();
|
||||
}
|
||||
|
||||
mAppBounds.set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setAppBounds(Rect)
|
||||
*/
|
||||
public Rect getAppBounds() {
|
||||
return mAppBounds;
|
||||
}
|
||||
|
||||
public void setTo(WindowConfiguration other) {
|
||||
setAppBounds(other.mAppBounds);
|
||||
}
|
||||
|
||||
/** Set this object to completely undefined. */
|
||||
public void unset() {
|
||||
setToDefaults();
|
||||
}
|
||||
|
||||
public void setToDefaults() {
|
||||
setAppBounds(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the fields from delta into this Configuration object, keeping
|
||||
* track of which ones have changed. Any undefined fields in {@code delta}
|
||||
* are ignored and not copied in to the current Configuration.
|
||||
*
|
||||
* @return a bit mask of the changed fields, as per {@link #diff}
|
||||
*/
|
||||
public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) {
|
||||
int changed = 0;
|
||||
if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) {
|
||||
changed |= WINDOW_CONFIG_APP_BOUNDS;
|
||||
setAppBounds(delta.mAppBounds);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a bit mask of the differences between this Configuration object and the given one.
|
||||
* Does not change the values of either. Any undefined fields in <var>other</var> are ignored.
|
||||
* @param other The configuration to diff against.
|
||||
* @param compareUndefined If undefined values should be compared.
|
||||
* @return Returns a bit mask indicating which configuration
|
||||
* values has changed, containing any combination of {@link WindowConfig} flags.
|
||||
*
|
||||
* @see Configuration#diff(Configuration)
|
||||
*/
|
||||
public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) {
|
||||
long changes = 0;
|
||||
|
||||
// Make sure that one of the values is not null and that they are not equal.
|
||||
if ((compareUndefined || other.mAppBounds != null)
|
||||
&& mAppBounds != other.mAppBounds
|
||||
&& (mAppBounds == null || !mAppBounds.equals(other.mAppBounds))) {
|
||||
changes |= WINDOW_CONFIG_APP_BOUNDS;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(WindowConfiguration that) {
|
||||
int n = 0;
|
||||
if (mAppBounds == null && that.mAppBounds != null) {
|
||||
return 1;
|
||||
} else if (mAppBounds != null && that.mAppBounds == null) {
|
||||
return -1;
|
||||
} else if (mAppBounds != null && that.mAppBounds != null) {
|
||||
n = mAppBounds.left - that.mAppBounds.left;
|
||||
if (n != 0) return n;
|
||||
n = mAppBounds.top - that.mAppBounds.top;
|
||||
if (n != 0) return n;
|
||||
n = mAppBounds.right - that.mAppBounds.right;
|
||||
if (n != 0) return n;
|
||||
n = mAppBounds.bottom - that.mAppBounds.bottom;
|
||||
if (n != 0) return n;
|
||||
}
|
||||
|
||||
// if (n != 0) return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) return false;
|
||||
if (that == this) return true;
|
||||
if (!(that instanceof WindowConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
return this.compareTo((WindowConfiguration) that) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 0;
|
||||
if (mAppBounds != null) {
|
||||
result = 31 * result + mAppBounds.hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{mAppBounds=" + mAppBounds + "}";
|
||||
}
|
||||
}
|
||||
@@ -780,6 +780,13 @@ public class ActivityInfo extends ComponentInfo
|
||||
* constant starts at the high bits.
|
||||
*/
|
||||
public static final int CONFIG_FONT_SCALE = 0x40000000;
|
||||
/**
|
||||
* Bit indicating changes to window configuration that isn't exposed to apps.
|
||||
* This is for internal use only and apps don't handle it.
|
||||
* @hide
|
||||
* {@link Configuration}.
|
||||
*/
|
||||
public static final int CONFIG_WINDOW_CONFIGURATION = 0x20000000;
|
||||
|
||||
/** @hide
|
||||
* Unfortunately the constants for config changes in native code are
|
||||
|
||||
@@ -19,15 +19,14 @@ package android.content.res;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ActivityInfo.Config;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.util.XmlUtils;
|
||||
@@ -42,7 +41,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* This class describes all device configuration information that can
|
||||
* impact the resources the application retrieves. This includes both
|
||||
@@ -298,13 +296,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
|
||||
* {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
|
||||
* the display level. Lower levels can override these values to provide custom bounds to enforce
|
||||
* features such as a max aspect ratio.
|
||||
* TODO(b/36812336): Move appBounds out of {@link Configuration}.
|
||||
* Configuration relating to the windowing state of the object associated with this
|
||||
* Configuration. Contents of this field are not intended to affect resources, but need to be
|
||||
* communicated and propagated at the same time as the rest of Configuration.
|
||||
*/
|
||||
public Rect appBounds;
|
||||
public final WindowConfiguration windowConfiguration = new WindowConfiguration();
|
||||
|
||||
/** @hide */
|
||||
static public int resetScreenLayout(int curLayout) {
|
||||
@@ -895,9 +891,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
compatScreenWidthDp = o.compatScreenWidthDp;
|
||||
compatScreenHeightDp = o.compatScreenHeightDp;
|
||||
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
|
||||
setAppBounds(o.appBounds);
|
||||
assetsSeq = o.assetsSeq;
|
||||
seq = o.seq;
|
||||
windowConfiguration.setTo(o.windowConfiguration);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -1046,9 +1042,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
|
||||
default: sb.append("/"); sb.append(navigationHidden); break;
|
||||
}
|
||||
if (appBounds != null) {
|
||||
sb.append(" appBounds="); sb.append(appBounds);
|
||||
}
|
||||
sb.append(" winConfig="); sb.append(windowConfiguration);
|
||||
if (assetsSeq != 0) {
|
||||
sb.append(" as.").append(assetsSeq);
|
||||
}
|
||||
@@ -1083,8 +1077,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
|
||||
densityDpi = DENSITY_DPI_UNDEFINED;
|
||||
assetsSeq = ASSETS_SEQ_UNDEFINED;
|
||||
appBounds = null;
|
||||
seq = 0;
|
||||
windowConfiguration.setToDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1183,7 +1177,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
changed |= ActivityInfo.CONFIG_ORIENTATION;
|
||||
orientation = delta.orientation;
|
||||
}
|
||||
|
||||
if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
|
||||
&& (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
|
||||
!= (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
|
||||
@@ -1271,10 +1264,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
|
||||
compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
|
||||
}
|
||||
if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) {
|
||||
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
setAppBounds(delta.appBounds);
|
||||
}
|
||||
if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) {
|
||||
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
|
||||
assetsSeq = delta.assetsSeq;
|
||||
@@ -1282,6 +1271,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
if (delta.seq != 0) {
|
||||
seq = delta.seq;
|
||||
}
|
||||
if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) {
|
||||
changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -1433,13 +1425,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
|
||||
}
|
||||
|
||||
// Make sure that one of the values is not null and that they are not equal.
|
||||
if ((compareUndefined || delta.appBounds != null)
|
||||
&& appBounds != delta.appBounds
|
||||
&& (appBounds == null || (!publicOnly && !appBounds.equals(delta.appBounds))
|
||||
|| (publicOnly && (appBounds.width() != delta.appBounds.width()
|
||||
|| appBounds.height() != delta.appBounds.height())))) {
|
||||
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
// WindowConfiguration differences aren't considered public...
|
||||
if (!publicOnly
|
||||
&& windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) {
|
||||
changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
}
|
||||
|
||||
return changed;
|
||||
@@ -1537,7 +1526,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
dest.writeInt(compatScreenWidthDp);
|
||||
dest.writeInt(compatScreenHeightDp);
|
||||
dest.writeInt(compatSmallestScreenWidthDp);
|
||||
dest.writeValue(appBounds);
|
||||
dest.writeValue(windowConfiguration);
|
||||
dest.writeInt(assetsSeq);
|
||||
dest.writeInt(seq);
|
||||
}
|
||||
@@ -1573,7 +1562,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
compatScreenWidthDp = source.readInt();
|
||||
compatScreenHeightDp = source.readInt();
|
||||
compatSmallestScreenWidthDp = source.readInt();
|
||||
appBounds = (Rect) source.readValue(null);
|
||||
windowConfiguration.setTo((WindowConfiguration) source.readValue(null));
|
||||
assetsSeq = source.readInt();
|
||||
seq = source.readInt();
|
||||
}
|
||||
@@ -1663,21 +1652,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
if (n != 0) return n;
|
||||
n = this.assetsSeq - that.assetsSeq;
|
||||
if (n != 0) return n;
|
||||
|
||||
if (this.appBounds == null && that.appBounds != null) {
|
||||
return 1;
|
||||
} else if (this.appBounds != null && that.appBounds == null) {
|
||||
return -1;
|
||||
} else if (this.appBounds != null && that.appBounds != null) {
|
||||
n = this.appBounds.left - that.appBounds.left;
|
||||
if (n != 0) return n;
|
||||
n = this.appBounds.top - that.appBounds.top;
|
||||
if (n != 0) return n;
|
||||
n = this.appBounds.right - that.appBounds.right;
|
||||
if (n != 0) return n;
|
||||
n = this.appBounds.bottom - that.appBounds.bottom;
|
||||
if (n != 0) return n;
|
||||
}
|
||||
n = windowConfiguration.compareTo(that.windowConfiguration);
|
||||
if (n != 0) return n;
|
||||
|
||||
// if (n != 0) return n;
|
||||
return n;
|
||||
@@ -1765,33 +1741,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
setLocales(loc == null ? LocaleList.getEmptyLocaleList() : new LocaleList(loc));
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* Helper method for setting the app bounds.
|
||||
*/
|
||||
public void setAppBounds(Rect rect) {
|
||||
if (rect == null) {
|
||||
appBounds = null;
|
||||
return;
|
||||
}
|
||||
|
||||
setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
* Helper method for setting the app bounds.
|
||||
*/
|
||||
public void setAppBounds(int left, int top, int right, int bottom) {
|
||||
if (appBounds == null) {
|
||||
appBounds = new Rect();
|
||||
}
|
||||
|
||||
appBounds.set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*
|
||||
@@ -2282,6 +2231,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
if (base.assetsSeq != change.assetsSeq) {
|
||||
delta.assetsSeq = change.assetsSeq;
|
||||
}
|
||||
|
||||
if (!base.windowConfiguration.equals(change.windowConfiguration)) {
|
||||
delta.windowConfiguration.setTo(change.windowConfiguration);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
@@ -2354,10 +2307,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
|
||||
configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
|
||||
DENSITY_DPI_UNDEFINED);
|
||||
configOut.appBounds =
|
||||
Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
|
||||
|
||||
// For persistence, we don't care about assetsSeq, so do not read it out.
|
||||
// For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
|
||||
// out.
|
||||
}
|
||||
|
||||
|
||||
@@ -2427,11 +2379,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
|
||||
XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
|
||||
}
|
||||
|
||||
if (config.appBounds != null) {
|
||||
XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS,
|
||||
config.appBounds.flattenToString());
|
||||
}
|
||||
|
||||
// For persistence, we do not care about assetsSeq, so do not write it out.
|
||||
// For persistence, we do not care about assetsSeq and window configuration, so do not write
|
||||
// it out.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
|
||||
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
@@ -568,10 +569,10 @@ public final class DisplayInfo implements Parcelable {
|
||||
outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
|
||||
outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
|
||||
|
||||
width = configuration != null && configuration.appBounds != null
|
||||
? configuration.appBounds.width() : width;
|
||||
height = configuration != null && configuration.appBounds != null
|
||||
? configuration.appBounds.height() : height;
|
||||
final Rect appBounds = configuration != null
|
||||
? configuration.windowConfiguration.getAppBounds() : null;
|
||||
width = appBounds != null ? appBounds.width() : width;
|
||||
height = appBounds != null ? appBounds.height() : height;
|
||||
|
||||
outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
|
||||
outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
|
||||
|
||||
@@ -46,6 +46,7 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
|
||||
import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
|
||||
import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
|
||||
@@ -429,11 +430,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
pw.print("\"");
|
||||
pw.print(" primaryColor=");
|
||||
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
|
||||
pw.print(prefix); pw.print(" backgroundColor=");
|
||||
pw.print(prefix + " backgroundColor=");
|
||||
pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
|
||||
pw.print(prefix); pw.print(" statusBarColor=");
|
||||
pw.print(prefix + " statusBarColor=");
|
||||
pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
|
||||
pw.print(prefix); pw.print(" navigationBarColor=");
|
||||
pw.print(prefix + " navigationBarColor=");
|
||||
pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
|
||||
}
|
||||
if (iconFilename == null && taskDescription.getIcon() != null) {
|
||||
@@ -2311,9 +2312,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
// We must base this on the parent configuration, because we set our override
|
||||
// configuration's appBounds based on the result of this method. If we used our own
|
||||
// configuration, it would be influenced by past invocations.
|
||||
final Configuration configuration = getParent().getConfiguration();
|
||||
final int containingAppWidth = configuration.appBounds.width();
|
||||
final int containingAppHeight = configuration.appBounds.height();
|
||||
final Rect appBounds = getParent().getConfiguration().windowConfiguration.getAppBounds();
|
||||
final int containingAppWidth = appBounds.width();
|
||||
final int containingAppHeight = appBounds.height();
|
||||
int maxActivityWidth = containingAppWidth;
|
||||
int maxActivityHeight = containingAppHeight;
|
||||
|
||||
@@ -2342,8 +2343,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
outBounds.set(0, 0, maxActivityWidth, maxActivityHeight);
|
||||
// Position the activity frame on the opposite side of the nav bar.
|
||||
final int navBarPosition = service.mWindowManager.getNavBarPosition();
|
||||
final int left = navBarPosition == NAV_BAR_LEFT
|
||||
? configuration.appBounds.right - outBounds.width() : 0;
|
||||
final int left = navBarPosition == NAV_BAR_LEFT ? appBounds.right - outBounds.width() : 0;
|
||||
outBounds.offsetTo(left, 0 /* top */);
|
||||
}
|
||||
|
||||
@@ -2574,6 +2574,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
|
||||
}
|
||||
}
|
||||
// We don't want window configuration to cause relaunches.
|
||||
if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
|
||||
changes &= ~CONFIG_WINDOW_CONFIGURATION;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
@@ -1205,8 +1205,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
final int leftInset = mTmpRect.left;
|
||||
final int topInset = mTmpRect.top;
|
||||
// appBounds at the root level should mirror the app screen size.
|
||||
config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + displayInfo.appWidth /*right*/,
|
||||
topInset + displayInfo.appHeight /*bottom*/);
|
||||
config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,
|
||||
leftInset + displayInfo.appWidth /* right */,
|
||||
topInset + displayInfo.appHeight /* bottom */);
|
||||
final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
|
||||
|| displayInfo.rotation == Surface.ROTATION_270);
|
||||
|
||||
|
||||
@@ -241,8 +241,8 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
final int leftInset = mTmpRect.left;
|
||||
final int topInset = mTmpRect.top;
|
||||
|
||||
config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + appWidth /*right*/,
|
||||
topInset + appHeight /*bottom*/);
|
||||
config.windowConfiguration.setAppBounds(leftInset /*left*/, topInset /*top*/,
|
||||
leftInset + appWidth /*right*/, topInset + appHeight /*bottom*/);
|
||||
|
||||
config.screenWidthDp = (int)
|
||||
(mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode,
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
|
||||
|
||||
import android.app.ActivityManager.StackId;
|
||||
import android.app.RemoteAction;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
@@ -30,11 +28,9 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
import com.android.server.UiThread;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||
@@ -278,9 +274,9 @@ public class StackWindowController
|
||||
int width;
|
||||
int height;
|
||||
|
||||
final Rect parentAppBounds = parentConfig.appBounds;
|
||||
final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
|
||||
|
||||
config.setAppBounds(!bounds.isEmpty() ? bounds : null);
|
||||
config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null);
|
||||
boolean intersectParentBounds = false;
|
||||
|
||||
if (StackId.tasksAreFloating(mStackId)) {
|
||||
@@ -295,7 +291,7 @@ public class StackWindowController
|
||||
nonDecorBounds.inset(mTmpNonDecorInsets);
|
||||
// Move app bounds to zero to apply intersection with parent correctly. They are
|
||||
// used only for evaluating width and height, so it's OK to move them around.
|
||||
config.appBounds.offsetTo(0, 0);
|
||||
config.windowConfiguration.getAppBounds().offsetTo(0, 0);
|
||||
intersectParentBounds = true;
|
||||
}
|
||||
width = (int) (stableBounds.width() / density);
|
||||
@@ -319,8 +315,8 @@ public class StackWindowController
|
||||
intersectParentBounds = true;
|
||||
}
|
||||
|
||||
if (intersectParentBounds && config.appBounds != null) {
|
||||
config.appBounds.intersect(parentAppBounds);
|
||||
if (intersectParentBounds && config.windowConfiguration.getAppBounds() != null) {
|
||||
config.windowConfiguration.getAppBounds().intersect(parentAppBounds);
|
||||
}
|
||||
|
||||
config.screenWidthDp = width;
|
||||
|
||||
@@ -126,7 +126,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
|
||||
// Verify with nav bar on the right.
|
||||
when(service.mWindowManager.getNavBarPosition()).thenReturn(navBarPosition);
|
||||
task.getConfiguration().setAppBounds(taskBounds);
|
||||
task.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
|
||||
record.info.maxAspectRatio = aspectRatio;
|
||||
record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */);
|
||||
assertEquals(expectedActivityBounds, record.getBounds());
|
||||
|
||||
@@ -11,36 +11,38 @@
|
||||
* 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.view.DisplayInfo;
|
||||
import org.junit.Test;
|
||||
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
|
||||
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test class to exercise logic related to {@link android.content.res.Configuration#appBounds}.
|
||||
* Test class to for {@link android.app.WindowConfiguration}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* bit FrameworksServicesTests:com.android.server.wm.AppBoundsTests
|
||||
* bit FrameworksServicesTests:com.android.server.wm.WindowConfigurationTests
|
||||
*/
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@org.junit.runner.RunWith(AndroidJUnit4.class)
|
||||
public class AppBoundsTests extends WindowTestsBase {
|
||||
public class WindowConfigurationTests extends WindowTestsBase {
|
||||
private Rect mParentBounds;
|
||||
|
||||
@Override
|
||||
@@ -49,44 +51,82 @@ public class AppBoundsTests extends WindowTestsBase {
|
||||
mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that appBounds causes {@link android.content.pm.ActivityInfo.CONFIG_APP_BOUNDS} diff.
|
||||
*/
|
||||
/** Tests {@link android.app.WindowConfiguration#diff(WindowConfiguration, boolean)}. */
|
||||
@Test
|
||||
public void testAppBoundsConfigurationDiff() {
|
||||
final Configuration config = new Configuration();
|
||||
public void testDiff() {
|
||||
final Configuration config1 = new Configuration();
|
||||
final WindowConfiguration winConfig1 = config1.windowConfiguration;
|
||||
final Configuration config2 = new Configuration();
|
||||
config.appBounds = new Rect(0, 1, 1, 0);
|
||||
config2.appBounds = new Rect(1, 2, 2, 1);
|
||||
final WindowConfiguration winConfig2 = config2.windowConfiguration;
|
||||
final Configuration config3 = new Configuration();
|
||||
final WindowConfiguration winConfig3 = config3.windowConfiguration;
|
||||
|
||||
assertEquals(ActivityInfo.CONFIG_SCREEN_SIZE, config.diff(config2));
|
||||
assertEquals(0, config.diffPublicOnly(config2));
|
||||
winConfig1.setAppBounds(0, 1, 1, 0);
|
||||
winConfig2.setAppBounds(1, 2, 2, 1);
|
||||
winConfig3.setAppBounds(winConfig1.getAppBounds());
|
||||
|
||||
|
||||
assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config2));
|
||||
assertEquals(0, config1.diffPublicOnly(config2));
|
||||
assertEquals(WINDOW_CONFIG_APP_BOUNDS,
|
||||
winConfig1.diff(winConfig2, false /* compareUndefined */));
|
||||
|
||||
assertEquals(0, config1.diff(config3));
|
||||
assertEquals(0, config1.diffPublicOnly(config3));
|
||||
assertEquals(0, winConfig1.diff(winConfig3, false /* compareUndefined */));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the configuration app bounds at the root level match the app dimensions.
|
||||
*/
|
||||
/** Tests {@link android.app.WindowConfiguration#compareTo(WindowConfiguration)}. */
|
||||
@Test
|
||||
public void testRootConfigurationBounds() throws Exception {
|
||||
public void testConfigurationCompareTo() throws Exception {
|
||||
final Configuration blankConfig = new Configuration();
|
||||
final WindowConfiguration blankWinConfig = new WindowConfiguration();
|
||||
|
||||
final Configuration config1 = new Configuration();
|
||||
final WindowConfiguration winConfig1 = config1.windowConfiguration;
|
||||
winConfig1.setAppBounds(1, 2, 3, 4);
|
||||
|
||||
final Configuration config2 = new Configuration(config1);
|
||||
final WindowConfiguration winConfig2 = config2.windowConfiguration;
|
||||
|
||||
assertEquals(config1.compareTo(config2), 0);
|
||||
assertEquals(winConfig1.compareTo(winConfig2), 0);
|
||||
|
||||
// Different bounds
|
||||
winConfig2.setAppBounds(0, 2, 3, 4);
|
||||
|
||||
assertNotEquals(config1.compareTo(config2), 0);
|
||||
assertNotEquals(winConfig1.compareTo(winConfig2), 0);
|
||||
|
||||
// No bounds
|
||||
assertEquals(config1.compareTo(blankConfig), -1);
|
||||
assertEquals(winConfig1.compareTo(blankWinConfig), -1);
|
||||
|
||||
assertEquals(blankConfig.compareTo(config1), 1);
|
||||
assertEquals(blankWinConfig.compareTo(winConfig1), 1);
|
||||
}
|
||||
|
||||
/** Ensures the configuration app bounds at the root level match the app dimensions. */
|
||||
@Test
|
||||
public void testAppBounds_RootConfigurationBounds() throws Exception {
|
||||
final DisplayInfo info = mDisplayContent.getDisplayInfo();
|
||||
info.appWidth = 1024;
|
||||
info.appHeight = 768;
|
||||
|
||||
final Configuration config = sWm.computeNewConfiguration(mDisplayContent.getDisplayId());
|
||||
final Rect appBounds = sWm.computeNewConfiguration(
|
||||
mDisplayContent.getDisplayId()).windowConfiguration.getAppBounds();
|
||||
// The bounds should always be positioned in the top left.
|
||||
assertEquals(config.appBounds.left, 0);
|
||||
assertEquals(config.appBounds.top, 0);
|
||||
assertEquals(appBounds.left, 0);
|
||||
assertEquals(appBounds.top, 0);
|
||||
|
||||
// The bounds should equal the defined app width and height
|
||||
assertEquals(config.appBounds.width(), info.appWidth);
|
||||
assertEquals(config.appBounds.height(), info.appHeight);
|
||||
assertEquals(appBounds.width(), info.appWidth);
|
||||
assertEquals(appBounds.height(), info.appHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that bounds are clipped to their parent.
|
||||
*/
|
||||
/** Ensures that bounds are clipped to their parent. */
|
||||
@Test
|
||||
public void testBoundsClipping() throws Exception {
|
||||
public void testAppBounds_BoundsClipping() throws Exception {
|
||||
final Rect shiftedBounds = new Rect(mParentBounds);
|
||||
shiftedBounds.offset(10, 10);
|
||||
final Rect expectedBounds = new Rect(mParentBounds);
|
||||
@@ -95,42 +135,34 @@ public class AppBoundsTests extends WindowTestsBase {
|
||||
expectedBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that empty bounds are not propagated to the configuration.
|
||||
*/
|
||||
/** Ensures that empty bounds are not propagated to the configuration. */
|
||||
@Test
|
||||
public void testEmptyBounds() throws Exception {
|
||||
public void testAppBounds_EmptyBounds() throws Exception {
|
||||
final Rect emptyBounds = new Rect();
|
||||
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds,
|
||||
null /*ExpectedBounds*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that bounds on freeform stacks are not clipped.
|
||||
*/
|
||||
/** Ensures that bounds on freeform stacks are not clipped. */
|
||||
@Test
|
||||
public void testFreeFormBounds() throws Exception {
|
||||
public void testAppBounds_FreeFormBounds() throws Exception {
|
||||
final Rect freeFormBounds = new Rect(mParentBounds);
|
||||
freeFormBounds.offset(10, 10);
|
||||
testStackBoundsConfiguration(ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID,
|
||||
mParentBounds, freeFormBounds, freeFormBounds);
|
||||
testStackBoundsConfiguration(FREEFORM_WORKSPACE_STACK_ID, mParentBounds, freeFormBounds,
|
||||
freeFormBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that fully contained bounds are not clipped.
|
||||
*/
|
||||
/** Ensures that fully contained bounds are not clipped. */
|
||||
@Test
|
||||
public void testContainedBounds() throws Exception {
|
||||
public void testAppBounds_ContainedBounds() throws Exception {
|
||||
final Rect insetBounds = new Rect(mParentBounds);
|
||||
insetBounds.inset(5, 5, 5, 5);
|
||||
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that full screen free form bounds are clipped
|
||||
*/
|
||||
/** Ensures that full screen free form bounds are clipped */
|
||||
@Test
|
||||
public void testFullScreenFreeFormBounds() throws Exception {
|
||||
public void testAppBounds_FullScreenFreeFormBounds() throws Exception {
|
||||
final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth,
|
||||
mDisplayInfo.logicalHeight);
|
||||
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds,
|
||||
@@ -144,40 +176,17 @@ public class AppBoundsTests extends WindowTestsBase {
|
||||
: createStackControllerOnDisplay(mDisplayContent);
|
||||
|
||||
final Configuration parentConfig = mDisplayContent.getConfiguration();
|
||||
parentConfig.setAppBounds(parentBounds);
|
||||
parentConfig.windowConfiguration.setAppBounds(parentBounds);
|
||||
|
||||
final Configuration config = new Configuration();
|
||||
final WindowConfiguration winConfig = config.windowConfiguration;
|
||||
stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/,
|
||||
new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/,
|
||||
false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig);
|
||||
// Assert that both expected and actual are null or are equal to each other
|
||||
|
||||
assertTrue((expectedConfigBounds == null && config.appBounds == null)
|
||||
|| expectedConfigBounds.equals(config.appBounds));
|
||||
assertTrue((expectedConfigBounds == null && winConfig.getAppBounds() == null)
|
||||
|| expectedConfigBounds.equals(winConfig.getAppBounds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures appBounds are considered in {@link Configuration#compareTo(Configuration)}.
|
||||
*/
|
||||
@Test
|
||||
public void testConfigurationCompareTo() throws Exception {
|
||||
final Configuration blankConfig = new Configuration();
|
||||
|
||||
final Configuration config1 = new Configuration();
|
||||
config1.appBounds = new Rect(1, 2, 3, 4);
|
||||
|
||||
final Configuration config2 = new Configuration(config1);
|
||||
|
||||
assertEquals(config1.compareTo(config2), 0);
|
||||
|
||||
config2.appBounds.left = 0;
|
||||
|
||||
// Different bounds
|
||||
assertNotEquals(config1.compareTo(config2), 0);
|
||||
|
||||
// No bounds
|
||||
assertEquals(config1.compareTo(blankConfig), -1);
|
||||
assertEquals(blankConfig.compareTo(config1), 1);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user