Merge "Allow Developer Menu state to be migrated"
diff --git a/Android.bp b/Android.bp
index 5c99b8c..3308768 100644
--- a/Android.bp
+++ b/Android.bp
@@ -484,7 +484,8 @@
installable: false, // this lib is a build-only library
static_libs: [
"framework-minus-apex",
- // TODO(jiyong): add stubs for APEXes here
+ "framework-sdkext-stubs-systemapi",
+ // TODO(jiyong): add more stubs for APEXes here
],
sdk_version: "core_platform",
apex_available: ["//apex_available:platform"],
@@ -1178,7 +1179,7 @@
arg_files: [
"core/res/AndroidManifest.xml",
],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi ",
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
write_sdk_values: true,
}
@@ -1489,7 +1490,7 @@
merge_annotations_dirs: [
"metalava-manual",
],
- args: " --show-annotation android.annotation.SystemApi",
+ args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
}
java_library_static {
@@ -1511,7 +1512,7 @@
removed_dex_api_filename: "removed-dex.txt",
args: metalava_framework_docs_args +
" --show-unannotated " +
- " --show-annotation android.annotation.SystemApi " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
" --show-annotation android.annotation.TestApi ",
}
@@ -1530,7 +1531,7 @@
" --hide ReferencesHidden " +
" --hide UnhiddenSystemApi " +
" --show-unannotated " +
- " --show-annotation android.annotation.SystemApi " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
" --show-annotation android.annotation.TestApi ",
}
@@ -1574,7 +1575,7 @@
arg_files: [
"core/res/AndroidManifest.xml",
],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi",
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
check_api: {
current: {
api_file: "api/system-current.txt",
diff --git a/apex/Android.bp b/apex/Android.bp
new file mode 100644
index 0000000..9ea3953
--- /dev/null
+++ b/apex/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2019 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.
+
+mainline_stubs_args =
+ "--error UnhiddenSystemApi " +
+ "--hide BroadcastBehavior " +
+ "--hide DeprecationMismatch " +
+ "--hide HiddenSuperclass " +
+ "--hide HiddenTypedefConstant " +
+ "--hide HiddenTypeParameter " +
+ "--hide MissingPermission " +
+ "--hide RequiresPermission " +
+ "--hide SdkConstant " +
+ "--hide Todo " +
+ "--hide Typo " +
+ "--hide UnavailableSymbol "
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-publicapi",
+ args: mainline_stubs_args,
+ installable: false,
+}
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-systemapi",
+ args: mainline_stubs_args + " --show-annotation android.annotation.SystemApi ",
+ installable: false,
+}
diff --git a/apex/sdkext/Android.bp b/apex/sdkext/Android.bp
index aaf25b1..6b52481 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkext/Android.bp
@@ -25,6 +25,11 @@
certificate: ":com.android.sdkext.certificate",
}
+sdk {
+ name: "sdkext-sdk",
+ java_libs: [ "framework-sdkext-stubs-systemapi" ],
+}
+
apex_key {
name: "com.android.sdkext.key",
public_key: "com.android.sdkext.avbpubkey",
diff --git a/apex/sdkext/framework/Android.bp b/apex/sdkext/framework/Android.bp
index b17f0f8..3a71c58 100644
--- a/apex/sdkext/framework/Android.bp
+++ b/apex/sdkext/framework/Android.bp
@@ -28,3 +28,34 @@
permitted_packages: [ "android.os.ext" ],
installable: true,
}
+
+droidstubs {
+ name: "framework-sdkext-droidstubs-publicapi",
+ defaults: [
+ "framework-sdkext-stubs-defaults",
+ "framework-module-stubs-defaults-publicapi",
+ ]
+}
+
+droidstubs {
+ name: "framework-sdkext-droidstubs-systemapi",
+ defaults: [
+ "framework-sdkext-stubs-defaults",
+ "framework-module-stubs-defaults-systemapi",
+ ]
+}
+
+stubs_defaults {
+ name: "framework-sdkext-stubs-defaults",
+ srcs: [
+ ":framework-sdkext-sources",
+ ":framework-annotations",
+ ],
+ sdk_version: "system_current",
+}
+
+java_library {
+ name: "framework-sdkext-stubs-systemapi",
+ srcs: [":framework-sdkext-droidstubs-systemapi"],
+ sdk_version: "system_current",
+}
diff --git a/api/current.txt b/api/current.txt
index b61917d..2c1b066 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6732,6 +6732,7 @@
method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
method public boolean getAutoTime(@NonNull android.content.ComponentName);
method @Deprecated public boolean getAutoTimeRequired();
+ method public boolean getAutoTimeZone(@NonNull android.content.ComponentName);
method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
@@ -6850,6 +6851,7 @@
method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
method public void setAutoTime(@NonNull android.content.ComponentName, boolean);
method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
+ method public void setAutoTimeZone(@NonNull android.content.ComponentName, boolean);
method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 8dcc095..7cfc218 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4434,7 +4434,7 @@
field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
field public CharSequence accessibilityTitle;
- field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC")}) public int privateFlags;
+ field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="FIT_INSETS_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="ONLY_DRAW_BOTTOM_BAR_BACKGROUND")}) public int privateFlags;
}
public class WindowlessViewRoot {
diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS
index e07028b..8aceb56 100644
--- a/core/java/android/annotation/OWNERS
+++ b/core/java/android/annotation/OWNERS
@@ -1,2 +1,3 @@
tnorbye@google.com
+aurimas@google.com
per-file UnsupportedAppUsage.java = mathewi@google.com, dbrazdil@google.com, atrost@google.com, andreionea@google.com
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index e96ff01..f589cc5 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -41,4 +41,29 @@
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemApi {
+ enum Client {
+ /**
+ * Specifies that the intended clients of a SystemApi are privileged apps.
+ * This is the default value for {@link #client}.
+ */
+ PRIVILEGED_APPS,
+ }
+
+ enum Process {
+ /**
+ * Specifies that the SystemAPI is available in every Java processes.
+ * This is the default value for {@link #process}.
+ */
+ ALL,
+ }
+
+ /**
+ * The intended client of this SystemAPI.
+ */
+ Client client() default android.annotation.SystemApi.Client.PRIVILEGED_APPS;
+
+ /**
+ * The process(es) that this SystemAPI is available
+ */
+ Process process() default android.annotation.SystemApi.Process.ALL;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 36ce4e8..5cdc505 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4407,7 +4407,9 @@
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
- WindowManager.LayoutParams l = r.window.getAttributes();
+ ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
+ WindowManager.LayoutParams l = impl != null
+ ? impl.mWindowAttributes : r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ec981b2..6e7ead1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5810,6 +5810,49 @@
}
/**
+ * Called by a device owner, a profile owner for the primary user or a profile
+ * owner of an organization-owned managed profile to turn auto time zone on and off.
+ * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
+ * to prevent the user from changing this setting.
+ * <p>
+ * If user restriction {@link UserManager#DISALLOW_CONFIG_DATE_TIME} is used,
+ * no user will be able set the date and time zone. Instead, the network date
+ * and time zone will be used.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enabled Whether time zone should be obtained automatically from the network or not.
+ * @throws SecurityException if caller is not a device owner, a profile owner for the
+ * primary user, or a profile owner of an organization-owned managed profile.
+ */
+ public void setAutoTimeZone(@NonNull ComponentName admin, boolean enabled) {
+ throwIfParentInstance("setAutoTimeZone");
+ if (mService != null) {
+ try {
+ mService.setAutoTimeZone(admin, enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * @return true if auto time zone is enabled on the device.
+ * @throws SecurityException if caller is not a device owner, a profile owner for the
+ * primary user, or a profile owner of an organization-owned managed profile.
+ */
+ public boolean getAutoTimeZone(@NonNull ComponentName admin) {
+ throwIfParentInstance("getAutoTimeZone");
+ if (mService != null) {
+ try {
+ return mService.getAutoTimeZone(admin);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by a device owner to set whether all users created on the device should be ephemeral.
* <p>
* The system user is exempt from this policy - it is never ephemeral.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ff1ecd5..949e8ab 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -298,6 +298,9 @@
void setAutoTime(in ComponentName who, boolean enabled);
boolean getAutoTime(in ComponentName who);
+ void setAutoTimeZone(in ComponentName who, boolean enabled);
+ boolean getAutoTimeZone(in ComponentName who);
+
void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
boolean getForceEphemeralUsers(in ComponentName who);
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 43842c5..156bcfe 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -21,6 +21,7 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -66,6 +67,7 @@
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
@@ -1019,6 +1021,16 @@
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
+ mWindow.getWindow().setFitWindowInsetsTypes(WindowInsets.Type.systemBars());
+ mWindow.getWindow().addPrivateFlags(PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND);
+ mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
+ (v, insets) -> v.onApplyWindowInsets(
+ new WindowInsets.Builder(insets).setSystemWindowInsets(
+ android.graphics.Insets.of(
+ insets.getSystemWindowInsetLeft(),
+ insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(),
+ insets.getStableInsetBottom())).build()));
// For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
// by default (but IME developers can opt this out later if they want a new behavior).
mWindow.getWindow().setFlags(
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bd1eb21..197d814 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8410,6 +8410,12 @@
public static final String TAP_GESTURE = "tap_gesture";
/**
+ * Controls whether the people strip is enabled.
+ * @hide
+ */
+ public static final String PEOPLE_STRIP = "people_strip";
+
+ /**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
*
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index c9d37bf..52b7294 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1137,6 +1137,7 @@
mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
mCallbacks, this, mDispatcherState,
WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
+ mWindow.getWindow().setFitWindowInsetsTypes(0 /* types */);
mWindow.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index d5c6766..e50d6c2 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -811,6 +811,7 @@
// Add window
mLayout.type = mIWallpaperEngine.mWindowType;
mLayout.gravity = Gravity.START|Gravity.TOP;
+ mLayout.setFitWindowInsetsTypes(0 /* types */);
mLayout.setTitle(WallpaperService.this.getClass().getName());
mLayout.windowAnimations =
com.android.internal.R.style.Animation_Wallpaper;
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index bc70d63..43fec82 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -123,6 +123,10 @@
if (mAnimationControls.isEmpty()) {
return;
}
+ if (mViewRoot.mView == null) {
+ // The view has already detached from window.
+ return;
+ }
mTmpFinishedControls.clear();
InsetsState state = new InsetsState(mState, true /* copySources */);
@@ -154,6 +158,7 @@
mFrame.set(frame);
}
+ @Override
public InsetsState getState() {
return mState;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3171306..e3f0da1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -19,12 +19,29 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.PFLAG_DRAW_ANIMATION;
+import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+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.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import android.Manifest;
@@ -93,6 +110,7 @@
import android.view.View.AttachInfo;
import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
+import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.accessibility.AccessibilityEvent;
@@ -118,6 +136,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.PhoneFallbackEventHandler;
@@ -519,6 +538,9 @@
private WindowInsets mLastWindowInsets;
+ // Insets types hidden by legacy window flags or system UI flags.
+ private @InsetsType int mTypesHiddenByFlags = 0;
+
/** Last applied configuration obtained from resources. */
private final Configuration mLastConfigurationFromResources = new Configuration();
/** Last configuration reported from WM or via {@link #MSG_UPDATE_CONFIGURATION}. */
@@ -890,6 +912,7 @@
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
+ adjustLayoutParamsForCompatibility(mWindowAttributes);
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
@@ -1841,15 +1864,96 @@
private int getImpliedSystemUiVisibility(WindowManager.LayoutParams params) {
int vis = 0;
// Translucent decor window flags imply stable system ui visibility.
- if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
+ if ((params.flags & FLAG_TRANSLUCENT_STATUS) != 0) {
vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
}
- if ((params.flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) != 0) {
+ if ((params.flags & FLAG_TRANSLUCENT_NAVIGATION) != 0) {
vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
}
return vis;
}
+ @VisibleForTesting
+ public static void adjustLayoutParamsForCompatibility(WindowManager.LayoutParams inOutParams) {
+ if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
+ return;
+ }
+ final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
+ final int flags = inOutParams.flags;
+ final int type = inOutParams.type;
+ final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST;
+
+ if ((sysUiVis & SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0) {
+ inOutParams.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+ } else if ((sysUiVis & SYSTEM_UI_FLAG_IMMERSIVE) != 0) {
+ inOutParams.insetsFlags.behavior = BEHAVIOR_SHOW_BARS_BY_SWIPE;
+ }
+
+ if ((inOutParams.privateFlags & PRIVATE_FLAG_FIT_INSETS_CONTROLLED) != 0) {
+ return;
+ }
+
+ int types = inOutParams.getFitWindowInsetsTypes();
+ int sides = inOutParams.getFitWindowInsetsSides();
+ boolean ignoreVis = inOutParams.getFitIgnoreVisibility();
+
+ if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
+ || (flags & FLAG_LAYOUT_IN_SCREEN) != 0)
+ || (flags & FLAG_TRANSLUCENT_STATUS) != 0) {
+ types &= ~Type.statusBars();
+ }
+ if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ || (flags & FLAG_TRANSLUCENT_NAVIGATION) != 0) {
+ types &= ~Type.systemBars();
+ }
+ if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
+ ignoreVis = true;
+ } else if ((types & Type.systemBars()) == Type.systemBars()
+ && adjust == SOFT_INPUT_ADJUST_RESIZE) {
+ types |= Type.ime();
+ }
+ inOutParams.setFitWindowInsetsTypes(types);
+ inOutParams.setFitWindowInsetsSides(sides);
+ inOutParams.setFitIgnoreVisibility(ignoreVis);
+
+ // The fitting of insets are not really controlled by the clients, so we remove the flag.
+ inOutParams.privateFlags &= ~PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
+ }
+
+ private void controlInsetsForCompatibility(WindowManager.LayoutParams params) {
+ if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
+ return;
+ }
+ final int sysUiVis = params.systemUiVisibility | params.subtreeSystemUiVisibility;
+ final int flags = params.flags;
+ final boolean statusWasHiddenByFlags = (mTypesHiddenByFlags & Type.statusBars()) != 0;
+ final boolean statusIsHiddenByFlags = (sysUiVis & SYSTEM_UI_FLAG_FULLSCREEN) != 0
+ || (flags & FLAG_FULLSCREEN) != 0;
+ final boolean navWasHiddenByFlags = (mTypesHiddenByFlags & Type.navigationBars()) != 0;
+ final boolean navIsHiddenByFlags = (sysUiVis & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+
+ @InsetsType int typesToHide = 0;
+ @InsetsType int typesToShow = 0;
+ if (statusIsHiddenByFlags && !statusWasHiddenByFlags) {
+ typesToHide |= Type.statusBars();
+ } else if (!statusIsHiddenByFlags && statusWasHiddenByFlags) {
+ typesToShow |= Type.statusBars();
+ }
+ if (navIsHiddenByFlags && !navWasHiddenByFlags) {
+ typesToHide |= Type.navigationBars();
+ } else if (!navIsHiddenByFlags && navWasHiddenByFlags) {
+ typesToShow |= Type.navigationBars();
+ }
+ if (typesToHide != 0) {
+ getInsetsController().hide(typesToHide);
+ }
+ if (typesToShow != 0) {
+ getInsetsController().show(typesToShow);
+ }
+ mTypesHiddenByFlags |= typesToHide;
+ mTypesHiddenByFlags &= ~typesToShow;
+ }
+
private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
int childWidthMeasureSpec;
@@ -2271,6 +2375,8 @@
&& !PixelFormat.formatHasAlpha(params.format)) {
params.format = PixelFormat.TRANSLUCENT;
}
+ adjustLayoutParamsForCompatibility(params);
+ controlInsetsForCompatibility(params);
}
if (mFirst || windowShouldResize || insetsChanged ||
@@ -2757,7 +2863,7 @@
if (changedVisibility || regainedFocus) {
// Toasts are presented as notifications - don't present them as windows as well
boolean isToast = (mWindowAttributes == null) ? false
- : (mWindowAttributes.type == WindowManager.LayoutParams.TYPE_TOAST);
+ : (mWindowAttributes.type == TYPE_TOAST);
if (!isToast) {
host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
@@ -4051,7 +4157,7 @@
}
boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
- final Rect ci = mAttachInfo.mContentInsets;
+ final Rect ci = getWindowInsets(false).getSystemWindowInsetsAsRect();
final Rect vi = mAttachInfo.mVisibleInsets;
int scrollY = 0;
boolean handled = false;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d79abc2..af1882b 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -46,6 +46,8 @@
import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionManager;
+import android.view.WindowInsets.Side.InsetsSide;
+import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityEvent;
import java.util.Collections;
@@ -1241,6 +1243,60 @@
}
/**
+ * A shortcut for {@link WindowManager.LayoutParams#setFitWindowInsetsTypes(int)}
+ * @hide pending unhide
+ */
+ public void setFitWindowInsetsTypes(@InsetsType int types) {
+ final WindowManager.LayoutParams attrs = getAttributes();
+ attrs.setFitWindowInsetsTypes(types);
+ dispatchWindowAttributesChanged(attrs);
+ }
+
+ /**
+ * A shortcut for {@link WindowManager.LayoutParams#setFitWindowInsetsSides(int)}
+ * @hide pending unhide
+ */
+ public void setFitWindowInsetsSides(@InsetsSide int sides) {
+ final WindowManager.LayoutParams attrs = getAttributes();
+ attrs.setFitWindowInsetsSides(sides);
+ dispatchWindowAttributesChanged(attrs);
+ }
+
+ /**
+ * A shortcut for {@link WindowManager.LayoutParams#setFitIgnoreVisibility(boolean)}
+ * @hide pending unhide
+ */
+ public void setFitIgnoreVisibility(boolean ignore) {
+ final WindowManager.LayoutParams attrs = getAttributes();
+ attrs.setFitIgnoreVisibility(ignore);
+ dispatchWindowAttributesChanged(attrs);
+ }
+
+ /**
+ * A shortcut for {@link WindowManager.LayoutParams#getFitWindowInsetsTypes}
+ * @hide pending unhide
+ */
+ public @InsetsType int getFitWindowInsetsTypes() {
+ return getAttributes().getFitWindowInsetsTypes();
+ }
+
+ /**
+ * A shortcut for {@link WindowManager.LayoutParams#getFitWindowInsetsSides()}
+ * @hide pending unhide
+ */
+ public @InsetsSide int getFitWindowInsetsSides() {
+ return getAttributes().getFitWindowInsetsSides();
+ }
+
+ /**
+ * A shortcut for {@link WindowManager.LayoutParams#getFitIgnoreVisibility()}
+ * @hide pending unhide
+ */
+ public boolean getFitIgnoreVisibility() {
+ return getAttributes().getFitIgnoreVisibility();
+ }
+
+ /**
* Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
* layout params you give here should generally be from values previously
* retrieved with {@link #getAttributes()}; you probably do not want to
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 57bd5bb..b16a4ca 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -1295,4 +1295,31 @@
return 0xFFFFFFFF;
}
}
+
+ /**
+ * Class that defines different sides for insets.
+ * @hide pending unhide
+ */
+ public static final class Side {
+
+ public static final int LEFT = 1 << 0;
+ public static final int TOP = 1 << 1;
+ public static final int RIGHT = 1 << 2;
+ public static final int BOTTOM = 1 << 3;
+
+ private Side() {
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {LEFT, TOP, RIGHT, BOTTOM})
+ public @interface InsetsSide {}
+
+ /**
+ * @return all four sides.
+ */
+ public static @InsetsSide int all() {
+ return LEFT | TOP | RIGHT | BOTTOM;
+ }
+ }
}
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 39e2e73..a045a6a 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -203,4 +203,9 @@
* @see Behavior
*/
void setSystemBarsBehavior(@Behavior int behavior);
+
+ /**
+ * @hide
+ */
+ InsetsState getState();
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9d5f98e..34092e2 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -17,11 +17,26 @@
package android.view;
import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
+import static android.view.WindowInsets.Side.BOTTOM;
+import static android.view.WindowInsets.Side.LEFT;
+import static android.view.WindowInsets.Side.RIGHT;
+import static android.view.WindowInsets.Side.TOP;
+import static android.view.WindowInsets.Type.CAPTION_BAR;
+import static android.view.WindowInsets.Type.IME;
+import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
+import static android.view.WindowInsets.Type.NAVIGATION_BARS;
+import static android.view.WindowInsets.Type.STATUS_BARS;
+import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
+import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
+import static android.view.WindowInsets.Type.WINDOW_DECOR;
import static android.view.WindowLayoutParamsProto.ALPHA;
import static android.view.WindowLayoutParamsProto.APPEARANCE;
import static android.view.WindowLayoutParamsProto.BEHAVIOR;
import static android.view.WindowLayoutParamsProto.BUTTON_BRIGHTNESS;
import static android.view.WindowLayoutParamsProto.COLOR_MODE;
+import static android.view.WindowLayoutParamsProto.FIT_IGNORE_VISIBILITY;
+import static android.view.WindowLayoutParamsProto.FIT_INSETS_SIDES;
+import static android.view.WindowLayoutParamsProto.FIT_INSETS_TYPES;
import static android.view.WindowLayoutParamsProto.FLAGS;
import static android.view.WindowLayoutParamsProto.FORMAT;
import static android.view.WindowLayoutParamsProto.GRAVITY;
@@ -65,6 +80,10 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
+import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Side.InsetsSide;
+import android.view.WindowInsets.Type;
+import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityNodeInfo;
import java.lang.annotation.Retention;
@@ -1840,6 +1859,20 @@
public static final int PRIVATE_FLAG_USE_BLAST = 0x02000000;
/**
+ * Flag to indicate that the window is controlling how it fits window insets on its own.
+ * So we don't need to adjust its attributes for fitting window insets.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_FIT_INSETS_CONTROLLED = 0x04000000;
+
+ /**
+ * Flag to indicate that the window only draws the bottom bar background so that we don't
+ * extend it to system bar areas at other sides.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND = 0x08000000;
+
+ /**
* An internal annotation for flags that can be specified to {@link #softInputMode}.
*
* @hide
@@ -1941,7 +1974,15 @@
@ViewDebug.FlagToString(
mask = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
- name = "COLOR_SPACE_AGNOSTIC")
+ name = "COLOR_SPACE_AGNOSTIC"),
+ @ViewDebug.FlagToString(
+ mask = PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
+ equals = PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
+ name = "FIT_INSETS_CONTROLLED"),
+ @ViewDebug.FlagToString(
+ mask = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND,
+ equals = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND,
+ name = "ONLY_DRAW_BOTTOM_BAR_BACKGROUND")
})
@TestApi
public int privateFlags;
@@ -2591,6 +2632,124 @@
*/
public final InsetsFlags insetsFlags = new InsetsFlags();
+ @ViewDebug.ExportedProperty(flagMapping = {
+ @ViewDebug.FlagToString(
+ mask = STATUS_BARS,
+ equals = STATUS_BARS,
+ name = "STATUS_BARS"),
+ @ViewDebug.FlagToString(
+ mask = NAVIGATION_BARS,
+ equals = NAVIGATION_BARS,
+ name = "NAVIGATION_BARS"),
+ @ViewDebug.FlagToString(
+ mask = CAPTION_BAR,
+ equals = CAPTION_BAR,
+ name = "CAPTION_BAR"),
+ @ViewDebug.FlagToString(
+ mask = IME,
+ equals = IME,
+ name = "IME"),
+ @ViewDebug.FlagToString(
+ mask = SYSTEM_GESTURES,
+ equals = SYSTEM_GESTURES,
+ name = "SYSTEM_GESTURES"),
+ @ViewDebug.FlagToString(
+ mask = MANDATORY_SYSTEM_GESTURES,
+ equals = MANDATORY_SYSTEM_GESTURES,
+ name = "MANDATORY_SYSTEM_GESTURES"),
+ @ViewDebug.FlagToString(
+ mask = TAPPABLE_ELEMENT,
+ equals = TAPPABLE_ELEMENT,
+ name = "TAPPABLE_ELEMENT"),
+ @ViewDebug.FlagToString(
+ mask = WINDOW_DECOR,
+ equals = WINDOW_DECOR,
+ name = "WINDOW_DECOR")
+ })
+ private @InsetsType int mFitWindowInsetsTypes = Type.systemBars();
+
+ @ViewDebug.ExportedProperty(flagMapping = {
+ @ViewDebug.FlagToString(
+ mask = LEFT,
+ equals = LEFT,
+ name = "LEFT"),
+ @ViewDebug.FlagToString(
+ mask = TOP,
+ equals = TOP,
+ name = "TOP"),
+ @ViewDebug.FlagToString(
+ mask = RIGHT,
+ equals = RIGHT,
+ name = "RIGHT"),
+ @ViewDebug.FlagToString(
+ mask = BOTTOM,
+ equals = BOTTOM,
+ name = "BOTTOM")
+ })
+ private @InsetsSide int mFitWindowInsetsSides = Side.all();
+
+ private boolean mFitIgnoreVisibility = false;
+
+ /**
+ * Specifies types of insets that this window should avoid overlapping during layout.
+ *
+ * @param types which types of insets that this window should avoid. The initial value of
+ * this object includes all system bars.
+ * @hide pending unhide
+ */
+ public void setFitWindowInsetsTypes(@InsetsType int types) {
+ mFitWindowInsetsTypes = types;
+ privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
+ }
+
+ /**
+ * Specifies sides of insets that this window should avoid overlapping during layout.
+ *
+ * @param sides which sides that this window should avoid overlapping with the types
+ * specified. The initial value of this object includes all sides.
+ * @hide pending unhide
+ */
+ public void setFitWindowInsetsSides(@InsetsSide int sides) {
+ mFitWindowInsetsSides = sides;
+ privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
+ }
+
+ /**
+ * Specifies if this window should fit the window insets no matter they are visible or not.
+ *
+ * @param ignore if true, this window will fit the given types even if they are not visible.
+ * @hide pending unhide
+ */
+ public void setFitIgnoreVisibility(boolean ignore) {
+ mFitIgnoreVisibility = ignore;
+ privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
+ }
+
+ /**
+ * @return the insets types that this window is avoiding overlapping.
+ * @hide pending unhide
+ */
+ public @InsetsType int getFitWindowInsetsTypes() {
+ return mFitWindowInsetsTypes;
+ }
+
+ /**
+ * @return the sides that this window is avoiding overlapping.
+ * @hide pending unhide
+ */
+ public @InsetsSide int getFitWindowInsetsSides() {
+ return mFitWindowInsetsSides;
+ }
+
+ /**
+ * @return {@code true} if this window fits the window insets no matter they are visible or
+ * not.
+ * @hide pending unhide
+ */
+ public boolean getFitIgnoreVisibility() {
+ return mFitIgnoreVisibility;
+ }
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -2754,6 +2913,9 @@
out.writeLong(hideTimeoutMilliseconds);
out.writeInt(insetsFlags.appearance);
out.writeInt(insetsFlags.behavior);
+ out.writeInt(mFitWindowInsetsTypes);
+ out.writeInt(mFitWindowInsetsSides);
+ out.writeBoolean(mFitIgnoreVisibility);
}
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -2811,6 +2973,9 @@
hideTimeoutMilliseconds = in.readLong();
insetsFlags.appearance = in.readInt();
insetsFlags.behavior = in.readInt();
+ mFitWindowInsetsTypes = in.readInt();
+ mFitWindowInsetsSides = in.readInt();
+ mFitIgnoreVisibility = in.readBoolean();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -3049,6 +3214,21 @@
changes |= INSET_FLAGS_CHANGED;
}
+ if (mFitWindowInsetsTypes != o.mFitWindowInsetsTypes) {
+ mFitWindowInsetsTypes = o.mFitWindowInsetsTypes;
+ changes |= LAYOUT_CHANGED;
+ }
+
+ if (mFitWindowInsetsSides != o.mFitWindowInsetsSides) {
+ mFitWindowInsetsSides = o.mFitWindowInsetsSides;
+ changes |= LAYOUT_CHANGED;
+ }
+
+ if (mFitIgnoreVisibility != o.mFitIgnoreVisibility) {
+ mFitIgnoreVisibility = o.mFitIgnoreVisibility;
+ changes |= LAYOUT_CHANGED;
+ }
+
return changes;
}
@@ -3203,6 +3383,20 @@
sb.append(prefix).append(" bhv=").append(ViewDebug.flagsToString(
InsetsFlags.class, "behavior", insetsFlags.behavior));
}
+ if (mFitWindowInsetsTypes != 0) {
+ sb.append(System.lineSeparator());
+ sb.append(prefix).append(" fitTypes=").append(ViewDebug.flagsToString(
+ LayoutParams.class, "mFitWindowInsetsTypes", mFitWindowInsetsTypes));
+ }
+ if (mFitWindowInsetsSides != Side.all()) {
+ sb.append(System.lineSeparator());
+ sb.append(prefix).append(" fitSides=").append(ViewDebug.flagsToString(
+ LayoutParams.class, "mFitWindowInsetsSides", mFitWindowInsetsSides));
+ }
+ if (mFitIgnoreVisibility) {
+ sb.append(System.lineSeparator());
+ sb.append(prefix).append(" fitIgnoreVis");
+ }
sb.append('}');
return sb.toString();
@@ -3240,6 +3434,9 @@
proto.write(SUBTREE_SYSTEM_UI_VISIBILITY_FLAGS, subtreeSystemUiVisibility);
proto.write(APPEARANCE, insetsFlags.appearance);
proto.write(BEHAVIOR, insetsFlags.behavior);
+ proto.write(FIT_INSETS_TYPES, mFitWindowInsetsTypes);
+ proto.write(FIT_INSETS_SIDES, mFitWindowInsetsSides);
+ proto.write(FIT_IGNORE_VISIBILITY, mFitIgnoreVisibility);
proto.end(token);
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index bdc2f9a..8f2133f 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -401,6 +401,7 @@
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
+ params.setFitIgnoreVisibility(true);
params.setTitle("Toast");
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index c33b6dc..29b148c 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -22,6 +22,8 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.N;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getMode;
@@ -74,6 +76,8 @@
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.InputQueue;
+import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
@@ -90,6 +94,9 @@
import android.view.Window;
import android.view.WindowCallbacks;
import android.view.WindowInsets;
+import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Type;
+import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -134,7 +141,7 @@
Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN);
+ FLAG_FULLSCREEN, ITYPE_STATUS_BAR);
public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
new ColorViewAttributes(
@@ -142,7 +149,7 @@
Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */);
+ 0 /* hideWindowFlag */, ITYPE_NAVIGATION_BAR);
// This is used to workaround an issue where the PiP shadow can be transparent if the window
// background is transparent
@@ -1085,6 +1092,9 @@
WindowManager.LayoutParams attrs = mWindow.getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
+ final WindowInsetsController controller = getWindowInsetsController();
+ final InsetsState state = controller != null ? controller.getState() : null;
+
// IME is an exceptional floating window that requires color view.
final boolean isImeWindow =
mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -1133,7 +1143,7 @@
calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
0 /* sideInset */, animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds);
+ mForceWindowDrawsBarBackgrounds, state);
boolean oldDrawLegacy = mDrawLegacyNavigationBarBackground;
mDrawLegacyNavigationBarBackground = mNavigationColorViewState.visible
&& (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
@@ -1154,7 +1164,7 @@
calculateStatusBarColor(), 0, mLastTopInset,
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
- mForceWindowDrawsBarBackgrounds);
+ mForceWindowDrawsBarBackgrounds, state);
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
@@ -1164,16 +1174,19 @@
// Note: We don't need to check for IN_SCREEN or INSET_DECOR because unlike the status bar,
// these flags wouldn't make the window draw behind the navigation bar, unless
// LAYOUT_HIDE_NAVIGATION was set.
- boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+ boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
+ || !(state == null || state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds
&& (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
+ && (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) != 0
&& !hideNavigation)
|| (mLastShouldAlwaysConsumeSystemBars && hideNavigation);
boolean consumingNavBar =
((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
+ && (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) != 0
&& !hideNavigation)
|| forceConsumingNavBar;
@@ -1182,18 +1195,21 @@
// If we should always consume system bars, only consume that if the app wanted to go to
// fullscreen, as othrewise we can expect the app to handle it.
boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
- || (attrs.flags & FLAG_FULLSCREEN) != 0;
+ || (attrs.flags & FLAG_FULLSCREEN) != 0
+ || !(state == null || state.getSource(ITYPE_STATUS_BAR).isVisible());
boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
&& (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
+ && (attrs.getFitWindowInsetsTypes() & Type.statusBars()) != 0
&& mForceWindowDrawsBarBackgrounds
&& mLastTopInset != 0
|| (mLastShouldAlwaysConsumeSystemBars && fullscreen);
- int consumedTop = consumingStatusBar ? mLastTopInset : 0;
- int consumedRight = consumingNavBar ? mLastRightInset : 0;
- int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
- int consumedLeft = consumingNavBar ? mLastLeftInset : 0;
+ int sides = attrs.getFitWindowInsetsSides();
+ int consumedTop = consumingStatusBar && (sides & Side.TOP) != 0 ? mLastTopInset : 0;
+ int consumedRight = consumingNavBar && (sides & Side.RIGHT) != 0 ? mLastRightInset : 0;
+ int consumedBottom = consumingNavBar && (sides & Side.BOTTOM) != 0 ? mLastBottomInset : 0;
+ int consumedLeft = consumingNavBar && (sides & Side.LEFT) != 0 ? mLastLeftInset : 0;
if (mContentRoot != null
&& mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
@@ -1325,8 +1341,10 @@
*/
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin,
- boolean animate, boolean force) {
- state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
+ boolean animate, boolean force, InsetsState insetsState) {
+ state.present = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
+ ? state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force)
+ : state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
mWindow.getAttributes().flags, force);
boolean showView = show && !isResizing() && size > 0;
@@ -2536,10 +2554,11 @@
final int seascapeGravity;
final String transitionName;
final int hideWindowFlag;
+ final @InternalInsetsType int insetsType;
private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
int horizontalGravity, int seascapeGravity, String transitionName, int id,
- int hideWindowFlag) {
+ int hideWindowFlag, @InternalInsetsType int insetsType) {
this.id = id;
this.systemUiHideFlag = systemUiHideFlag;
this.translucentFlag = translucentFlag;
@@ -2548,8 +2567,10 @@
this.seascapeGravity = seascapeGravity;
this.transitionName = transitionName;
this.hideWindowFlag = hideWindowFlag;
+ this.insetsType = insetsType;
}
+ // TODO(b/118118435): remove after migration
public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
return (sysUiVis & systemUiHideFlag) == 0
&& (windowFlags & hideWindowFlag) == 0
@@ -2557,16 +2578,27 @@
|| force);
}
+ public boolean isPresent(InsetsState state, int windowFlags, boolean force) {
+ return (state == null || state.getSource(insetsType).isVisible())
+ && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || force);
+ }
+
public boolean isVisible(boolean present, int color, int windowFlags, boolean force) {
return present
&& (color & Color.BLACK) != 0
&& ((windowFlags & translucentFlag) == 0 || force);
}
+ // TODO(b/118118435): remove after migration
public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
final boolean present = isPresent(sysUiVis, windowFlags, force);
return isVisible(present, color, windowFlags, force);
}
+
+ public boolean isVisible(InsetsState state, int color, int windowFlags, boolean force) {
+ final boolean present = isPresent(state, windowFlags, force);
+ return isVisible(present, color, windowFlags, force);
+ }
}
/**
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index 1290026..6c2a5a3 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -25,6 +25,7 @@
#include <SkPicture.h>
#include <SkPictureRecorder.h>
#include <hwui/AnimatedImageDrawable.h>
+#include <hwui/ImageDecoder.h>
#include <hwui/Canvas.h>
#include <utils/Looper.h>
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index 4d907f6..627f8f5 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -20,10 +20,12 @@
#include "CreateJavaOutputStreamAdaptor.h"
#include "GraphicsJNI.h"
#include "ImageDecoder.h"
+#include "NinePatchPeeker.h"
#include "Utils.h"
#include "core_jni_helpers.h"
#include <hwui/Bitmap.h>
+#include <hwui/ImageDecoder.h>
#include <HardwareBitmapUploader.h>
#include <SkAndroidCodec.h>
@@ -49,6 +51,28 @@
static jmethodID gCanvas_constructorMethodID;
static jmethodID gCanvas_releaseMethodID;
+// These need to stay in sync with ImageDecoder.java's Allocator constants.
+enum Allocator {
+ kDefault_Allocator = 0,
+ kSoftware_Allocator = 1,
+ kSharedMemory_Allocator = 2,
+ kHardware_Allocator = 3,
+};
+
+// These need to stay in sync with ImageDecoder.java's Error constants.
+enum Error {
+ kSourceException = 1,
+ kSourceIncomplete = 2,
+ kSourceMalformedData = 3,
+};
+
+// These need to stay in sync with PixelFormat.java's Format constants.
+enum PixelFormat {
+ kUnknown = 0,
+ kTranslucent = -3,
+ kOpaque = -1,
+};
+
// Clear and return any pending exception for handling other than throwing directly.
static jthrowable get_and_clear_exception(JNIEnv* env) {
jthrowable jexception = env->ExceptionOccurred();
@@ -59,7 +83,7 @@
}
// Throw a new ImageDecoder.DecodeException. Returns null for convenience.
-static jobject throw_exception(JNIEnv* env, ImageDecoder::Error error, const char* msg,
+static jobject throw_exception(JNIEnv* env, Error error, const char* msg,
jthrowable cause, jobject source) {
jstring jstr = nullptr;
if (msg) {
@@ -81,27 +105,27 @@
static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream,
jobject source, jboolean preferAnimation) {
if (!stream.get()) {
- return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to create a stream",
+ return throw_exception(env, kSourceMalformedData, "Failed to create a stream",
nullptr, source);
}
- std::unique_ptr<ImageDecoder> decoder(new ImageDecoder);
+ sk_sp<NinePatchPeeker> peeker(new NinePatchPeeker);
SkCodec::Result result;
auto codec = SkCodec::MakeFromStream(
- std::move(stream), &result, decoder->mPeeker.get(),
+ std::move(stream), &result, peeker.get(),
preferAnimation ? SkCodec::SelectionPolicy::kPreferAnimation
: SkCodec::SelectionPolicy::kPreferStillImage);
if (jthrowable jexception = get_and_clear_exception(env)) {
- return throw_exception(env, ImageDecoder::kSourceException, "", jexception, source);
+ return throw_exception(env, kSourceException, "", jexception, source);
}
if (!codec) {
switch (result) {
case SkCodec::kIncompleteInput:
- return throw_exception(env, ImageDecoder::kSourceIncomplete, "", nullptr, source);
+ return throw_exception(env, kSourceIncomplete, "", nullptr, source);
default:
SkString msg;
msg.printf("Failed to create image decoder with message '%s'",
SkCodec::ResultToString(result));
- return throw_exception(env, ImageDecoder::kSourceMalformedData, msg.c_str(),
+ return throw_exception(env, kSourceMalformedData, msg.c_str(),
nullptr, source);
}
@@ -109,21 +133,22 @@
const bool animated = codec->getFrameCount() > 1;
if (jthrowable jexception = get_and_clear_exception(env)) {
- return throw_exception(env, ImageDecoder::kSourceException, "", jexception, source);
+ return throw_exception(env, kSourceException, "", jexception, source);
}
- decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
+ auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
SkAndroidCodec::ExifOrientationBehavior::kRespect);
- if (!decoder->mCodec.get()) {
- return throw_exception(env, ImageDecoder::kSourceMalformedData, "", nullptr, source);
+ if (!androidCodec.get()) {
+ return throw_exception(env, kSourceMalformedData, "", nullptr, source);
}
- const auto& info = decoder->mCodec->getInfo();
+ const auto& info = androidCodec->getInfo();
const int width = info.width();
const int height = info.height();
- const bool isNinePatch = decoder->mPeeker->mPatch != nullptr;
+ const bool isNinePatch = peeker->mPatch != nullptr;
+ ImageDecoder* decoder = new ImageDecoder(std::move(androidCodec), std::move(peeker));
return env->NewObject(gImageDecoder_class, gImageDecoder_constructorMethodID,
- reinterpret_cast<jlong>(decoder.release()), width, height,
+ reinterpret_cast<jlong>(decoder), width, height,
animated, isNinePatch);
}
@@ -133,7 +158,7 @@
struct stat fdStat;
if (fstat(descriptor, &fdStat) == -1) {
- return throw_exception(env, ImageDecoder::kSourceMalformedData,
+ return throw_exception(env, kSourceMalformedData,
"broken file descriptor; fstat returned -1", nullptr, source);
}
@@ -141,7 +166,7 @@
FILE* file = fdopen(dupDescriptor, "r");
if (file == NULL) {
close(dupDescriptor);
- return throw_exception(env, ImageDecoder::kSourceMalformedData, "Could not open file",
+ return throw_exception(env, kSourceMalformedData, "Could not open file",
nullptr, source);
}
@@ -154,7 +179,7 @@
std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage, false));
if (!stream.get()) {
- return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to create a stream",
+ return throw_exception(env, kSourceMalformedData, "Failed to create a stream",
nullptr, source);
}
@@ -177,7 +202,7 @@
std::unique_ptr<SkStream> stream = CreateByteBufferStreamAdaptor(env, jbyteBuffer,
initialPosition, limit);
if (!stream) {
- return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to read ByteBuffer",
+ return throw_exception(env, kSourceMalformedData, "Failed to read ByteBuffer",
nullptr, source);
}
return native_create(env, std::move(stream), source, preferAnimation);
@@ -195,7 +220,7 @@
reinterpret_cast<jlong>(canvas.get()));
if (!jcanvas) {
doThrowOOME(env, "Failed to create Java Canvas for PostProcess!");
- return ImageDecoder::kUnknown;
+ return kUnknown;
}
// jcanvas now owns canvas.
@@ -206,43 +231,23 @@
static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
jobject jdecoder, jboolean jpostProcess,
- jint desiredWidth, jint desiredHeight, jobject jsubset,
+ jint targetWidth, jint targetHeight, jobject jsubset,
jboolean requireMutable, jint allocator,
jboolean requireUnpremul, jboolean preferRamOverQuality,
jboolean asAlphaMask, jlong colorSpaceHandle,
jboolean extended) {
auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
- SkAndroidCodec* codec = decoder->mCodec.get();
- const SkISize desiredSize = SkISize::Make(desiredWidth, desiredHeight);
- SkISize decodeSize = desiredSize;
- const int sampleSize = codec->computeSampleSize(&decodeSize);
- const bool scale = desiredSize != decodeSize;
- SkImageInfo decodeInfo = codec->getInfo().makeWH(decodeSize.width(), decodeSize.height());
- if (scale && requireUnpremul && kOpaque_SkAlphaType != decodeInfo.alphaType()) {
+ if (!decoder->setTargetSize(targetWidth, targetHeight)) {
+ doThrowISE(env, "Could not scale to target size!");
+ return nullptr;
+ }
+ if (requireUnpremul && !decoder->setOutAlphaType(kUnpremul_SkAlphaType)) {
doThrowISE(env, "Cannot scale unpremultiplied pixels!");
return nullptr;
}
- switch (decodeInfo.alphaType()) {
- case kUnpremul_SkAlphaType:
- if (!requireUnpremul) {
- decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
- }
- break;
- case kPremul_SkAlphaType:
- if (requireUnpremul) {
- decodeInfo = decodeInfo.makeAlphaType(kUnpremul_SkAlphaType);
- }
- break;
- case kOpaque_SkAlphaType:
- break;
- case kUnknown_SkAlphaType:
- doThrowIOE(env, "Unknown alpha type");
- return nullptr;
- }
-
SkColorType colorType = kN32_SkColorType;
- if (asAlphaMask && decodeInfo.colorType() == kGray_8_SkColorType) {
+ if (asAlphaMask && decoder->gray()) {
// We have to trick Skia to decode this to a single channel.
colorType = kGray_8_SkColorType;
} else if (preferRamOverQuality) {
@@ -250,12 +255,12 @@
// result incorrect. If we call the postProcess before now and record
// to a picture, we can know whether alpha was added, and if not, we
// can still use 565.
- if (decodeInfo.alphaType() == kOpaque_SkAlphaType && !jpostProcess) {
+ if (decoder->opaque() && !jpostProcess) {
// If the final result will be hardware, decoding to 565 and then
// uploading to the gpu as 8888 will not save memory. This still
// may save us from using F16, but do not go down to 565.
- if (allocator != ImageDecoder::kHardware_Allocator &&
- (allocator != ImageDecoder::kDefault_Allocator || requireMutable)) {
+ if (allocator != kHardware_Allocator &&
+ (allocator != kDefault_Allocator || requireMutable)) {
colorType = kRGB_565_SkColorType;
}
}
@@ -263,12 +268,12 @@
} else if (extended) {
colorType = kRGBA_F16_SkColorType;
} else {
- colorType = codec->computeOutputColorType(colorType);
+ colorType = decoder->mCodec->computeOutputColorType(colorType);
}
const bool isHardware = !requireMutable
- && (allocator == ImageDecoder::kDefault_Allocator ||
- allocator == ImageDecoder::kHardware_Allocator)
+ && (allocator == kDefault_Allocator ||
+ allocator == kHardware_Allocator)
&& colorType != kGray_8_SkColorType;
if (colorType == kRGBA_F16_SkColorType && isHardware &&
@@ -276,12 +281,28 @@
colorType = kN32_SkColorType;
}
- sk_sp<SkColorSpace> colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
- colorSpace = codec->computeOutputColorSpace(colorType, colorSpace);
- decodeInfo = decodeInfo.makeColorType(colorType).makeColorSpace(colorSpace);
+ if (!decoder->setOutColorType(colorType)) {
+ doThrowISE(env, "Failed to set out color type!");
+ return nullptr;
+ }
+
+ {
+ sk_sp<SkColorSpace> colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
+ colorSpace = decoder->mCodec->computeOutputColorSpace(colorType, colorSpace);
+ decoder->setOutColorSpace(std::move(colorSpace));
+ }
+
+ if (jsubset) {
+ SkIRect subset;
+ GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
+ if (!decoder->setCropRect(&subset)) {
+ doThrowISE(env, "Invalid crop rect!");
+ return nullptr;
+ }
+ }
SkBitmap bm;
- auto bitmapInfo = decodeInfo;
+ SkImageInfo bitmapInfo = decoder->getOutputInfo();
if (asAlphaMask && colorType == kGray_8_SkColorType) {
bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType);
}
@@ -291,10 +312,7 @@
}
sk_sp<Bitmap> nativeBitmap;
- // If we are going to scale or subset, we will create a new bitmap later on,
- // so use the heap for the temporary.
- // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380.
- if (allocator == ImageDecoder::kSharedMemory_Allocator && !scale && !jsubset) {
+ if (allocator == kSharedMemory_Allocator) {
nativeBitmap = Bitmap::allocateAshmemBitmap(&bm);
} else {
nativeBitmap = Bitmap::allocateHeapBitmap(&bm);
@@ -302,16 +320,14 @@
if (!nativeBitmap) {
SkString msg;
msg.printf("OOM allocating Bitmap with dimensions %i x %i",
- decodeInfo.width(), decodeInfo.height());
+ bitmapInfo.width(), bitmapInfo.height());
doThrowOOME(env, msg.c_str());
return nullptr;
}
- SkAndroidCodec::AndroidOptions options;
- options.fSampleSize = sampleSize;
- auto result = codec->getAndroidPixels(decodeInfo, bm.getPixels(), bm.rowBytes(), &options);
+ SkCodec::Result result = decoder->decode(bm.getPixels(), bm.rowBytes());
jthrowable jexception = get_and_clear_exception(env);
- int onPartialImageError = jexception ? ImageDecoder::kSourceException
+ int onPartialImageError = jexception ? kSourceException
: 0; // No error.
switch (result) {
case SkCodec::kSuccess:
@@ -321,12 +337,12 @@
break;
case SkCodec::kIncompleteInput:
if (!jexception) {
- onPartialImageError = ImageDecoder::kSourceIncomplete;
+ onPartialImageError = kSourceIncomplete;
}
break;
case SkCodec::kErrorInInput:
if (!jexception) {
- onPartialImageError = ImageDecoder::kSourceMalformedData;
+ onPartialImageError = kSourceMalformedData;
}
break;
default:
@@ -350,20 +366,21 @@
// Ignore ninepatch when post-processing.
if (!jpostProcess) {
// FIXME: Share more code with BitmapFactory.cpp.
- if (decoder->mPeeker->mPatch != nullptr) {
- size_t ninePatchArraySize = decoder->mPeeker->mPatch->serializedSize();
+ auto* peeker = reinterpret_cast<NinePatchPeeker*>(decoder->mPeeker.get());
+ if (peeker->mPatch != nullptr) {
+ size_t ninePatchArraySize = peeker->mPatch->serializedSize();
ninePatchChunk = env->NewByteArray(ninePatchArraySize);
if (ninePatchChunk == nullptr) {
doThrowOOME(env, "Failed to allocate nine patch chunk.");
return nullptr;
}
- env->SetByteArrayRegion(ninePatchChunk, 0, decoder->mPeeker->mPatchSize,
- reinterpret_cast<jbyte*>(decoder->mPeeker->mPatch));
+ env->SetByteArrayRegion(ninePatchChunk, 0, peeker->mPatchSize,
+ reinterpret_cast<jbyte*>(peeker->mPatch));
}
- if (decoder->mPeeker->mHasInsets) {
- ninePatchInsets = decoder->mPeeker->createNinePatchInsets(env, 1.0f);
+ if (peeker->mHasInsets) {
+ ninePatchInsets = peeker->createNinePatchInsets(env, 1.0f);
if (ninePatchInsets == nullptr) {
doThrowOOME(env, "Failed to allocate nine patch insets.");
return nullptr;
@@ -371,58 +388,6 @@
}
}
- if (scale || jsubset) {
- int translateX = 0;
- int translateY = 0;
- SkImageInfo scaledInfo;
- if (jsubset) {
- SkIRect subset;
- GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
-
- translateX = -subset.fLeft;
- translateY = -subset.fTop;
- scaledInfo = bitmapInfo.makeWH(subset.width(), subset.height());
- } else {
- scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
- }
- SkBitmap scaledBm;
- if (!scaledBm.setInfo(scaledInfo)) {
- doThrowIOE(env, "Failed scaled setInfo");
- return nullptr;
- }
-
- sk_sp<Bitmap> scaledPixelRef;
- if (allocator == ImageDecoder::kSharedMemory_Allocator) {
- scaledPixelRef = Bitmap::allocateAshmemBitmap(&scaledBm);
- } else {
- scaledPixelRef = Bitmap::allocateHeapBitmap(&scaledBm);
- }
- if (!scaledPixelRef) {
- SkString msg;
- msg.printf("OOM allocating scaled Bitmap with dimensions %i x %i",
- desiredWidth, desiredHeight);
- doThrowOOME(env, msg.c_str());
- return nullptr;
- }
-
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
-
- SkCanvas canvas(scaledBm, SkCanvas::ColorBehavior::kLegacy);
- canvas.translate(translateX, translateY);
- if (scale) {
- float scaleX = (float) desiredWidth / decodeInfo.width();
- float scaleY = (float) desiredHeight / decodeInfo.height();
- canvas.scale(scaleX, scaleY);
- }
-
- canvas.drawBitmap(bm, 0.0f, 0.0f, &paint);
-
- bm.swap(scaledBm);
- nativeBitmap = std::move(scaledPixelRef);
- }
-
if (jpostProcess) {
std::unique_ptr<Canvas> canvas(Canvas::create_canvas(bm));
@@ -433,12 +398,12 @@
SkAlphaType newAlphaType = bm.alphaType();
switch (pixelFormat) {
- case ImageDecoder::kUnknown:
+ case kUnknown:
break;
- case ImageDecoder::kTranslucent:
+ case kTranslucent:
newAlphaType = kPremul_SkAlphaType;
break;
- case ImageDecoder::kOpaque:
+ case kOpaque:
newAlphaType = kOpaque_SkAlphaType;
break;
default:
@@ -477,7 +442,7 @@
return bitmap::createBitmap(env, hwBitmap.release(), bitmapCreateFlags,
ninePatchChunk, ninePatchInsets);
}
- if (allocator == ImageDecoder::kHardware_Allocator) {
+ if (allocator == kHardware_Allocator) {
doThrowOOME(env, "failed to allocate hardware Bitmap!");
return nullptr;
}
@@ -501,7 +466,7 @@
static void ImageDecoder_nGetPadding(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
jobject outPadding) {
auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
- decoder->mPeeker->getPadding(env, outPadding);
+ reinterpret_cast<NinePatchPeeker*>(decoder->mPeeker.get())->getPadding(env, outPadding);
}
static void ImageDecoder_nClose(JNIEnv* /*env*/, jobject /*clazz*/, jlong nativePtr) {
diff --git a/core/jni/android/graphics/ImageDecoder.h b/core/jni/android/graphics/ImageDecoder.h
index fd9827b..8a7fa79 100644
--- a/core/jni/android/graphics/ImageDecoder.h
+++ b/core/jni/android/graphics/ImageDecoder.h
@@ -14,48 +14,12 @@
* limitations under the License.
*/
-#include "NinePatchPeeker.h"
-
#include <hwui/Canvas.h>
#include <jni.h>
-class SkAndroidCodec;
-
-using namespace android;
-
-struct ImageDecoder {
- // These need to stay in sync with ImageDecoder.java's Allocator constants.
- enum Allocator {
- kDefault_Allocator = 0,
- kSoftware_Allocator = 1,
- kSharedMemory_Allocator = 2,
- kHardware_Allocator = 3,
- };
-
- // These need to stay in sync with ImageDecoder.java's Error constants.
- enum Error {
- kSourceException = 1,
- kSourceIncomplete = 2,
- kSourceMalformedData = 3,
- };
-
- // These need to stay in sync with PixelFormat.java's Format constants.
- enum PixelFormat {
- kUnknown = 0,
- kTranslucent = -3,
- kOpaque = -1,
- };
-
- std::unique_ptr<SkAndroidCodec> mCodec;
- sk_sp<NinePatchPeeker> mPeeker;
-
- ImageDecoder()
- :mPeeker(new NinePatchPeeker)
- {}
-};
-
// Creates a Java Canvas object from canvas, calls jimageDecoder's PostProcess on it, and then
// releases the Canvas.
// Caller needs to check for exceptions.
-jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas);
+jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder,
+ std::unique_ptr<android::Canvas> canvas);
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index f8c304c..ee5144c 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -152,4 +152,5 @@
CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES = 125;
CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER = 126;
SET_AUTO_TIME = 127;
+ SET_AUTO_TIME_ZONE = 128;
}
diff --git a/core/proto/android/view/windowlayoutparams.proto b/core/proto/android/view/windowlayoutparams.proto
index e7c2827..272a245 100644
--- a/core/proto/android/view/windowlayoutparams.proto
+++ b/core/proto/android/view/windowlayoutparams.proto
@@ -63,4 +63,7 @@
optional uint32 subtree_system_ui_visibility_flags = 28;
optional uint32 appearance = 29;
optional uint32 behavior = 30;
+ optional uint32 fit_insets_types = 31;
+ optional uint32 fit_insets_sides = 32;
+ optional bool fit_ignore_visibility = 33;
}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 9a57847..cf5d079 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -16,13 +16,25 @@
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.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+
import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Type;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -55,6 +67,8 @@
@Test
public void negativeInsets_areSetToZero() throws Exception {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
mViewRootImpl.getAttachInfo().getContentInsets().set(-10, -20, -30 , -40);
mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
@@ -65,6 +79,8 @@
@Test
public void negativeInsets_areSetToZero_positiveAreLeftAsIs() throws Exception {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
mViewRootImpl.getAttachInfo().getContentInsets().set(-10, 20, -30 , 40);
mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
@@ -75,6 +91,8 @@
@Test
public void positiveInsets_areLeftAsIs() throws Exception {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
mViewRootImpl.getAttachInfo().getContentInsets().set(10, 20, 30 , 40);
mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
@@ -83,6 +101,80 @@
assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 20, 30, 40)));
}
+ @Test
+ public void adjustLayoutParamsForInsets_layoutFullscreen() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.statusBars());
+ }
+
+ @Test
+ public void adjustLayoutParamsForInsets_layoutInScreen() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ attrs.flags = FLAG_LAYOUT_IN_SCREEN;
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.statusBars());
+ }
+
+ @Test
+ public void adjustLayoutParamsForInsets_layoutHideNavigation() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.systemBars());
+ }
+
+ @Test
+ public void adjustLayoutParamsForInsets_toast() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_TOAST);
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(Type.systemBars(), attrs.getFitWindowInsetsTypes() & Type.systemBars());
+ assertEquals(true, attrs.getFitIgnoreVisibility());
+ }
+
+ @Test
+ public void adjustLayoutParamsForInsets_systemAlert() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_SYSTEM_ALERT);
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(Type.systemBars(), attrs.getFitWindowInsetsTypes() & Type.systemBars());
+ assertEquals(true, attrs.getFitIgnoreVisibility());
+ }
+
+ @Test
+ public void adjustLayoutParamsForInsets_noAdjust() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ final int types = Type.all();
+ final int sides = Side.TOP | Side.LEFT;
+ final boolean fitMaxInsets = true;
+ attrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ attrs.setFitWindowInsetsTypes(types);
+ attrs.setFitWindowInsetsSides(sides);
+ attrs.setFitIgnoreVisibility(fitMaxInsets);
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
+ assertEquals(types, attrs.getFitWindowInsetsTypes());
+ assertEquals(sides, attrs.getFitWindowInsetsSides());
+ assertEquals(fitMaxInsets, attrs.getFitIgnoreVisibility());
+ }
+
private static class ViewRootImplAccessor {
private final ViewRootImpl mViewRootImpl;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index f670cf9..d945fc4 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -176,6 +176,7 @@
"hwui/AnimatedImageThread.cpp",
"hwui/Bitmap.cpp",
"hwui/Canvas.cpp",
+ "hwui/ImageDecoder.cpp",
"hwui/MinikinSkia.cpp",
"hwui/MinikinUtils.cpp",
"hwui/PaintImpl.cpp",
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 2ba6fbe..f4149b9 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -44,9 +44,7 @@
namespace android {
-// returns true if rowBytes * height can be represented by a positive int32_t value
-// and places that value in size.
-static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
+bool Bitmap::computeAllocationSize(size_t rowBytes, int height, size_t* size) {
return 0 <= height && height <= std::numeric_limits<size_t>::max() &&
!__builtin_mul_overflow(rowBytes, (size_t)height, size) &&
*size <= std::numeric_limits<int32_t>::max();
@@ -66,7 +64,7 @@
// we must respect the rowBytes value already set on the bitmap instead of
// attempting to compute our own.
const size_t rowBytes = bitmap->rowBytes();
- if (!computeAllocationSize(rowBytes, bitmap->height(), &size)) {
+ if (!Bitmap::computeAllocationSize(rowBytes, bitmap->height(), &size)) {
return nullptr;
}
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 00733c6..1cda046 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -138,6 +138,10 @@
return mPalette;
}
+ // returns true if rowBytes * height can be represented by a positive int32_t value
+ // and places that value in size.
+ static bool computeAllocationSize(size_t rowBytes, int height, size_t* size);
+
private:
static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
new file mode 100644
index 0000000..4f2027d
--- /dev/null
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "ImageDecoder.h"
+
+#include <hwui/Bitmap.h>
+
+#include <SkAndroidCodec.h>
+#include <SkCanvas.h>
+#include <SkPaint.h>
+
+using namespace android;
+
+ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChunkReader> peeker)
+ : mCodec(std::move(codec))
+ , mPeeker(std::move(peeker))
+ , mTargetSize(mCodec->getInfo().dimensions())
+ , mDecodeSize(mTargetSize)
+ , mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType))
+ , mOutAlphaType(mCodec->getInfo().isOpaque() ?
+ kOpaque_SkAlphaType : kPremul_SkAlphaType)
+ , mOutColorSpace(mCodec->getInfo().refColorSpace())
+ , mSampleSize(1)
+{
+}
+
+bool ImageDecoder::setTargetSize(int width, int height) {
+ if (width <= 0 || height <= 0) {
+ return false;
+ }
+
+ auto info = SkImageInfo::Make(width, height, mOutColorType, mOutAlphaType);
+ size_t rowBytes = info.minRowBytes();
+ if (rowBytes == 0) {
+ // This would have overflowed.
+ return false;
+ }
+
+ size_t pixelMemorySize;
+ if (!Bitmap::computeAllocationSize(rowBytes, height, &pixelMemorySize)) {
+ return false;
+ }
+
+ if (mCropRect) {
+ if (mCropRect->right() > width || mCropRect->bottom() > height) {
+ return false;
+ }
+ }
+
+ SkISize targetSize = { width, height }, decodeSize = targetSize;
+ int sampleSize = mCodec->computeSampleSize(&decodeSize);
+
+ if (decodeSize != targetSize && mOutAlphaType == kUnpremul_SkAlphaType
+ && !mCodec->getInfo().isOpaque()) {
+ return false;
+ }
+
+ mTargetSize = targetSize;
+ mDecodeSize = decodeSize;
+ mSampleSize = sampleSize;
+ return true;
+}
+
+bool ImageDecoder::setCropRect(const SkIRect* crop) {
+ if (!crop) {
+ mCropRect.reset();
+ return true;
+ }
+
+ if (crop->left() >= crop->right() || crop->top() >= crop->bottom()) {
+ return false;
+ }
+
+ const auto& size = mTargetSize;
+ if (crop->left() < 0 || crop->top() < 0
+ || crop->right() > size.width() || crop->bottom() > size.height()) {
+ return false;
+ }
+
+ mCropRect.emplace(*crop);
+ return true;
+}
+
+bool ImageDecoder::setOutColorType(SkColorType colorType) {
+ switch (colorType) {
+ case kRGB_565_SkColorType:
+ if (!opaque()) {
+ return false;
+ }
+ break;
+ case kGray_8_SkColorType:
+ if (!gray()) {
+ return false;
+ }
+ mOutColorSpace = nullptr;
+ break;
+ case kN32_SkColorType:
+ break;
+ case kRGBA_F16_SkColorType:
+ break;
+ default:
+ return false;
+ }
+
+ mOutColorType = colorType;
+ return true;
+}
+
+bool ImageDecoder::setOutAlphaType(SkAlphaType alpha) {
+ switch (alpha) {
+ case kOpaque_SkAlphaType:
+ return opaque();
+ case kPremul_SkAlphaType:
+ if (opaque()) {
+ // Opaque can be treated as premul.
+ return true;
+ }
+ break;
+ case kUnpremul_SkAlphaType:
+ if (opaque()) {
+ // Opaque can be treated as unpremul.
+ return true;
+ }
+ if (mDecodeSize != mTargetSize) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ mOutAlphaType = alpha;
+ return true;
+}
+
+void ImageDecoder::setOutColorSpace(sk_sp<SkColorSpace> colorSpace) {
+ mOutColorSpace = std::move(colorSpace);
+}
+
+SkImageInfo ImageDecoder::getOutputInfo() const {
+ SkISize size = mCropRect ? mCropRect->size() : mTargetSize;
+ return SkImageInfo::Make(size, mOutColorType, mOutAlphaType, mOutColorSpace);
+}
+
+bool ImageDecoder::opaque() const {
+ return mOutAlphaType == kOpaque_SkAlphaType;
+}
+
+bool ImageDecoder::gray() const {
+ return mCodec->getInfo().colorType() == kGray_8_SkColorType;
+}
+
+SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
+ void* decodePixels = pixels;
+ size_t decodeRowBytes = rowBytes;
+ auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, mOutAlphaType, mOutColorSpace);
+ // Used if we need a temporary before scaling or subsetting.
+ // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380.
+ SkBitmap tmp;
+ const bool scale = mDecodeSize != mTargetSize;
+ if (scale || mCropRect) {
+ if (!tmp.setInfo(decodeInfo)) {
+ return SkCodec::kInternalError;
+ }
+ if (!Bitmap::allocateHeapBitmap(&tmp)) {
+ return SkCodec::kInternalError;
+ }
+ decodePixels = tmp.getPixels();
+ decodeRowBytes = tmp.rowBytes();
+ }
+
+ SkAndroidCodec::AndroidOptions options;
+ options.fSampleSize = mSampleSize;
+ auto result = mCodec->getAndroidPixels(decodeInfo, decodePixels, decodeRowBytes, &options);
+
+ if (scale || mCropRect) {
+ SkBitmap scaledBm;
+ if (!scaledBm.installPixels(getOutputInfo(), pixels, rowBytes)) {
+ return SkCodec::kInternalError;
+ }
+
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc);
+ paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
+
+ SkCanvas canvas(scaledBm, SkCanvas::ColorBehavior::kLegacy);
+ if (mCropRect) {
+ canvas.translate(-mCropRect->fLeft, -mCropRect->fTop);
+ }
+ if (scale) {
+ float scaleX = (float) mTargetSize.width() / mDecodeSize.width();
+ float scaleY = (float) mTargetSize.height() / mDecodeSize.height();
+ canvas.scale(scaleX, scaleY);
+ }
+
+ canvas.drawBitmap(tmp, 0.0f, 0.0f, &paint);
+ }
+
+ return result;
+}
+
diff --git a/libs/hwui/hwui/ImageDecoder.h b/libs/hwui/hwui/ImageDecoder.h
new file mode 100644
index 0000000..b956f4a
--- /dev/null
+++ b/libs/hwui/hwui/ImageDecoder.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#pragma once
+
+#include <SkCodec.h>
+#include <SkImageInfo.h>
+#include <SkPngChunkReader.h>
+#include <SkRect.h>
+#include <SkSize.h>
+#include <cutils/compiler.h>
+
+#include <optional>
+
+class SkAndroidCodec;
+
+namespace android {
+
+class ANDROID_API ImageDecoder {
+public:
+ std::unique_ptr<SkAndroidCodec> mCodec;
+ sk_sp<SkPngChunkReader> mPeeker;
+
+ ImageDecoder(std::unique_ptr<SkAndroidCodec> codec,
+ sk_sp<SkPngChunkReader> peeker = nullptr);
+
+ bool setTargetSize(int width, int height);
+ bool setCropRect(const SkIRect*);
+
+ bool setOutColorType(SkColorType outColorType);
+
+ bool setOutAlphaType(SkAlphaType outAlphaType);
+
+ void setOutColorSpace(sk_sp<SkColorSpace> cs);
+
+ // The size is the final size after scaling and cropping.
+ SkImageInfo getOutputInfo() const;
+ SkColorType getOutColorType() const { return mOutColorType; }
+ SkAlphaType getOutAlphaType() const { return mOutAlphaType; }
+
+ bool opaque() const;
+ bool gray() const;
+
+ SkCodec::Result decode(void* pixels, size_t rowBytes);
+
+private:
+ SkISize mTargetSize;
+ SkISize mDecodeSize;
+ SkColorType mOutColorType;
+ SkAlphaType mOutAlphaType;
+ sk_sp<SkColorSpace> mOutColorSpace;
+ int mSampleSize;
+ std::optional<SkIRect> mCropRect;
+
+ ImageDecoder(const ImageDecoder&) = delete;
+ ImageDecoder& operator=(const ImageDecoder&) = delete;
+};
+
+} // namespace android
diff --git a/media/Android.bp b/media/Android.bp
index 1912930..e2bdad1 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -82,7 +82,7 @@
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi "
+ "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) "
droidstubs {
name: "updatable-media-stubs",
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index 08ab492..998d2b9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -278,6 +278,7 @@
leftlp.windowAnimations = 0;
leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
leftlp.gravity = Gravity.LEFT;
+ leftlp.setFitWindowInsetsTypes(0 /* types */);
mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
}
if (mRightNavigationBarWindow != null) {
@@ -295,6 +296,7 @@
rightlp.windowAnimations = 0;
rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
rightlp.gravity = Gravity.RIGHT;
+ rightlp.setFitWindowInsetsTypes(0 /* types */);
mWindowManager.addView(mRightNavigationBarWindow, rightlp);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index ec46433..2d57be1 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -240,7 +240,7 @@
}
private WindowManager.LayoutParams createLayoutParams() {
- return new WindowManager.LayoutParams(
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
@@ -249,6 +249,8 @@
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
PixelFormat.TRANSLUCENT
);
+ attrs.setFitWindowInsetsTypes(0 /* types */);
+ return attrs;
}
private void logd(String message) {
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 3b929b9..76e7ab4 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -155,6 +155,7 @@
Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED,
Settings.Secure.AWARE_LOCK_ENABLED,
Settings.Secure.AWARE_TAP_PAUSE_GESTURE_COUNT,
- Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT
+ Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
+ Settings.Secure.PEOPLE_STRIP,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 090af98..ae07598 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -234,5 +234,6 @@
VALIDATORS.put(Secure.AWARE_LOCK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 9380eb4..4e7956d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -290,6 +290,7 @@
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ getWindow().setFitWindowInsetsTypes(0 /* types */);
getWindow().setNavigationBarContrastEnforced(false);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
index 812f215..0210e08 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
@@ -25,12 +25,12 @@
final class ClockInfo {
private final String mName;
- private final String mTitle;
+ private final Supplier<String> mTitle;
private final String mId;
private final Supplier<Bitmap> mThumbnail;
private final Supplier<Bitmap> mPreview;
- private ClockInfo(String name, String title, String id,
+ private ClockInfo(String name, Supplier<String> title, String id,
Supplier<Bitmap> thumbnail, Supplier<Bitmap> preview) {
mName = name;
mTitle = title;
@@ -50,7 +50,7 @@
* Gets the name (title) of the clock face to be shown in the picker app.
*/
String getTitle() {
- return mTitle;
+ return mTitle.get();
}
/**
@@ -80,7 +80,7 @@
static class Builder {
private String mName;
- private String mTitle;
+ private Supplier<String> mTitle;
private String mId;
private Supplier<Bitmap> mThumbnail;
private Supplier<Bitmap> mPreview;
@@ -94,7 +94,7 @@
return this;
}
- public Builder setTitle(String title) {
+ public Builder setTitle(Supplier<String> title) {
mTitle = title;
return this;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index dfabe69..9cd4aec 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -244,11 +244,12 @@
mPreviewClocks.reloadCurrentClock();
mListeners.forEach((listener, clocks) -> {
clocks.reloadCurrentClock();
- ClockPlugin clock = clocks.getCurrentClock();
- if (clock instanceof DefaultClockController) {
- listener.onClockChanged(null);
+ final ClockPlugin clock = clocks.getCurrentClock();
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ listener.onClockChanged(clock instanceof DefaultClockController ? null : clock);
} else {
- listener.onClockChanged(clock);
+ mMainHandler.post(() -> listener.onClockChanged(
+ clock instanceof DefaultClockController ? null : clock));
}
});
}
@@ -323,7 +324,7 @@
mClocks.put(plugin.getClass().getName(), plugin);
mClockInfo.add(ClockInfo.builder()
.setName(plugin.getName())
- .setTitle(plugin.getTitle())
+ .setTitle(plugin::getTitle)
.setId(id)
.setThumbnail(plugin::getThumbnail)
.setPreview(() -> plugin.getPreview(mWidth, mHeight))
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index ab7eec5..9ce277e 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -495,6 +495,7 @@
lp.gravity = Gravity.TOP | Gravity.LEFT;
}
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ lp.setFitWindowInsetsTypes(0 /* types */);
if (isLandscape(mRotation)) {
lp.width = WRAP_CONTENT;
lp.height = MATCH_PARENT;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index 79d4f8d..659629b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -70,6 +70,7 @@
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
PixelFormat.TRANSLUCENT);
lp.setTitle("AssistDisclosure");
+ lp.setFitWindowInsetsTypes(0 /* types */);
mWm.addView(mView, lp);
mViewAdded = true;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 4cb1708..eb615a0 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -85,6 +85,7 @@
PixelFormat.TRANSLUCENT);
mLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
mLayoutParams.gravity = Gravity.BOTTOM;
+ mLayoutParams.setFitWindowInsetsTypes(0 /* types */);
mLayoutParams.setTitle("Assist");
mInvocationLightsView = (InvocationLightsView)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 3948416..36c89fd 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -35,6 +35,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
@@ -590,6 +591,7 @@
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("BiometricPrompt");
lp.token = windowToken;
+ lp.setFitWindowInsetsTypes(lp.getFitWindowInsetsTypes() & ~Type.statusBars());
return lp;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 63a7771..ef853e6 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1562,6 +1562,7 @@
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ window.setFitWindowInsetsTypes(0 /* types */);
setTitle(R.string.global_actions);
mPanelController = plugin;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 53053fc..d385123 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -120,6 +120,7 @@
window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ window.setFitWindowInsetsTypes(0 /* types */);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 3f15966..750cc60 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -109,6 +109,7 @@
lp.setTitle("pip-dismiss-overlay");
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+ lp.setFitWindowInsetsTypes(0 /* types */);
mWindowManager.addView(mDismissView, lp);
}
mDismissView.animate().cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index e0f26cd..1d37911 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -413,6 +413,7 @@
handleSetListening(false);
}
mCallbacks.clear();
+ mHandler.removeCallbacksAndMessages(null);
}
protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index d819b8e..1d649ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -138,6 +138,7 @@
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ScreenPinningConfirmation");
lp.gravity = Gravity.FILL;
+ lp.setFitWindowInsetsTypes(0 /* types */);
return lp;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 5041354..00220ce 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -258,6 +258,7 @@
PixelFormat.TRANSLUCENT);
mWindowLayoutParams.setTitle("ScreenshotAnimation");
mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.setFitWindowInsetsTypes(0 /* types */);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mNotificationManager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index bb34a87..f2b4ad8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -23,6 +23,7 @@
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -40,12 +41,14 @@
import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
+import android.view.ViewRootImpl;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
@@ -321,6 +324,16 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ if (isAttachedToWindow()
+ && ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL) {
+ // Our window doesn't cover entire display, so we use the display frame to re-calculate
+ // the insets.
+ final InsetsState state = getWindowInsetsController().getState();
+ insets = state.calculateInsets(state.getDisplayFrame(), insets.isRound(),
+ insets.shouldAlwaysConsumeSystemBars(), insets.getDisplayCutout(),
+ null /* legacyContentInsets */, null /* legacyStableInsets */,
+ SOFT_INPUT_ADJUST_NOTHING, null /* typeSideMap */);
+ }
if (mStableInsets.left != insets.getStableInsetLeft()
|| mStableInsets.top != insets.getStableInsetTop()
|| mStableInsets.right != insets.getStableInsetRight()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
index 4f03003..efcef71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
@@ -31,6 +31,11 @@
abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource<PeopleHubModel>
@Binds
+ abstract fun peopleHubSettingChangeDataSource(
+ impl: PeopleHubSettingChangeDataSourceImpl
+ ): DataSource<Boolean>
+
+ @Binds
abstract fun peopleHubViewModelFactoryDataSource(
impl: PeopleHubViewModelFactoryDataSourceImpl
): DataSource<PeopleHubViewModelFactory>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
index 5c35408..e9d6a0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -16,7 +16,14 @@
package com.android.systemui.statusbar.notification.people
+import android.content.Context
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.UserHandle
+import android.provider.Settings
import android.view.View
+import com.android.systemui.dagger.qualifiers.MainHandler
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
import javax.inject.Inject
@@ -90,29 +97,58 @@
@Singleton
class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
private val activityStarter: ActivityStarter,
- private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>
+ private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>,
+ private val settingChangeSource: DataSource<@JvmSuppressWildcards Boolean>
) : DataSource<PeopleHubViewModelFactory> {
- override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>) =
- dataSource.registerListener(PeopleHubModelListenerImpl(activityStarter, listener))
+ override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>): Subscription {
+ var stripEnabled = false
+ var model: PeopleHubModel? = null
+
+ fun updateListener() {
+ // don't invoke listener until we've received our first model
+ model?.let { model ->
+ val factory =
+ if (stripEnabled) PeopleHubViewModelFactoryImpl(model, activityStarter)
+ else EmptyViewModelFactory
+ listener.onDataChanged(factory)
+ }
+ }
+
+ val settingSub = settingChangeSource.registerListener(object : DataListener<Boolean> {
+ override fun onDataChanged(data: Boolean) {
+ stripEnabled = data
+ updateListener()
+ }
+ })
+ val dataSub = dataSource.registerListener(object : DataListener<PeopleHubModel> {
+ override fun onDataChanged(data: PeopleHubModel) {
+ model = data
+ updateListener()
+ }
+ })
+ return object : Subscription {
+ override fun unsubscribe() {
+ settingSub.unsubscribe()
+ dataSub.unsubscribe()
+ }
+ }
+ }
}
-private class PeopleHubModelListenerImpl(
- private val activityStarter: ActivityStarter,
- private val dataListener: DataListener<PeopleHubViewModelFactory>
-) : DataListener<PeopleHubModel> {
-
- override fun onDataChanged(data: PeopleHubModel) =
- dataListener.onDataChanged(PeopleHubViewModelFactoryImpl(data, activityStarter))
+private object EmptyViewModelFactory : PeopleHubViewModelFactory {
+ override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
+ return PeopleHubViewModel(emptySequence(), false)
+ }
}
private class PeopleHubViewModelFactoryImpl(
- private val data: PeopleHubModel,
+ private val model: PeopleHubModel,
private val activityStarter: ActivityStarter
) : PeopleHubViewModelFactory {
override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
- val personViewModels = data.people.asSequence().map { personModel ->
+ val personViewModels = model.people.asSequence().map { personModel ->
val onClick = {
activityStarter.startPendingIntentDismissingKeyguard(
personModel.clickIntent,
@@ -122,7 +158,42 @@
}
PersonViewModel(personModel.name, personModel.avatar, onClick)
}
- return PeopleHubViewModel(personViewModels, data.people.isNotEmpty())
+ return PeopleHubViewModel(personViewModels, model.people.isNotEmpty())
+ }
+}
+
+@Singleton
+class PeopleHubSettingChangeDataSourceImpl @Inject constructor(
+ @MainHandler private val handler: Handler,
+ context: Context
+) : DataSource<Boolean> {
+
+ private val settingUri = Settings.Secure.getUriFor(Settings.Secure.PEOPLE_STRIP)
+ private val contentResolver = context.contentResolver
+
+ override fun registerListener(listener: DataListener<Boolean>): Subscription {
+ // Immediately report current value of setting
+ updateListener(listener)
+ val observer = object : ContentObserver(handler) {
+ override fun onChange(selfChange: Boolean, uri: Uri?, userId: Int) {
+ super.onChange(selfChange, uri, userId)
+ updateListener(listener)
+ }
+ }
+ contentResolver.registerContentObserver(settingUri, false, observer, UserHandle.USER_ALL)
+ return object : Subscription {
+ override fun unsubscribe() = contentResolver.unregisterContentObserver(observer)
+ }
+ }
+
+ private fun updateListener(listener: DataListener<Boolean>) {
+ val setting = Settings.Secure.getIntForUser(
+ contentResolver,
+ Settings.Secure.PEOPLE_STRIP,
+ 0,
+ UserHandle.USER_CURRENT
+ )
+ listener.onDataChanged(setting != 0)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index 782aad1..315ea0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -34,6 +34,7 @@
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.Window
+import android.view.WindowInsets.Type
import android.view.WindowManager
import android.widget.TextView
import com.android.internal.annotations.VisibleForTesting
@@ -287,6 +288,7 @@
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
addFlags(wmFlags)
setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL)
+ setFitWindowInsetsTypes(getFitWindowInsetsTypes() and Type.statusBars().inv())
setWindowAnimations(com.android.internal.R.style.Animation_InputMethod)
attributes = attributes.apply {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 8ee964f..f25f910 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -300,6 +300,7 @@
layoutParams.setTitle(TAG + mContext.getDisplayId());
layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
layoutParams.windowAnimations = 0;
+ layoutParams.setFitWindowInsetsTypes(0 /* types */);
return layoutParams;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index a784984..783e7ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -84,6 +84,7 @@
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("FloatingRotationButton");
+ lp.setFitWindowInsetsTypes(0 /*types */);
switch (mWindowManager.getDefaultDisplay().getRotation()) {
case Surface.ROTATION_0:
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 2ecceba..f94b2ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -204,6 +204,7 @@
PixelFormat.TRANSLUCENT);
mLp.token = new Binder();
mLp.gravity = Gravity.TOP;
+ mLp.setFitWindowInsetsTypes(0 /* types */);
mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 44be6bc..28b6c38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -23,6 +23,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
+import android.view.Window;
+import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -102,16 +104,22 @@
public static void setWindowOnTop(Dialog dialog) {
if (Dependency.get(KeyguardStateController.class).isShowing()) {
- dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_PANEL);
+ final Window window = dialog.getWindow();
+ window.setType(LayoutParams.TYPE_STATUS_BAR_PANEL);
+ window.setFitWindowInsetsTypes(
+ window.getFitWindowInsetsTypes() & ~Type.statusBars());
} else {
dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
}
}
public static AlertDialog applyFlags(AlertDialog dialog) {
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
- dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ final Window window = dialog.getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
+ window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ window.setFitWindowInsetsTypes(
+ window.getFitWindowInsetsTypes() & ~Type.statusBars());
return dialog;
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
index d2b2654..4c0890a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
@@ -57,7 +57,7 @@
@Test
public void testGetTitle() {
final String title = "title";
- ClockInfo info = ClockInfo.builder().setTitle(title).build();
+ ClockInfo info = ClockInfo.builder().setTitle(() -> title).build();
assertThat(info.getTitle()).isEqualTo(title);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
index 0cd6f9a..d2832fb9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
@@ -117,12 +117,12 @@
public void testQuery_listOptions() {
mClocks.add(ClockInfo.builder()
.setName("name_a")
- .setTitle("title_a")
+ .setTitle(() -> "title_a")
.setId("id_a")
.build());
mClocks.add(ClockInfo.builder()
.setName("name_b")
- .setTitle("title_b")
+ .setTitle(() -> "title_b")
.setId("id_b")
.build());
Cursor cursor = mProvider.query(mListOptionsUri, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 192d8f8..49b47c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -188,6 +188,16 @@
verify(mTile).handleSetListening(eq(false));
}
+ @Test
+ public void testHandleDestroyClearsHandlerQueue() {
+ when(mTile.getStaleTimeout()).thenReturn(0L);
+ mTile.handleRefreshState(null); // this will add a delayed H.STALE message
+ mTile.handleDestroy();
+
+ mTestableLooper.processAllMessages();
+ verify(mTile, never()).handleStale();
+ }
+
private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
private final int mCategory;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
index f5d6f22..0764d0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
@@ -89,8 +89,17 @@
return mockSubscription
}
}
+ val fakeSettingDataSource = object : DataSource<Boolean> {
+ override fun registerListener(listener: DataListener<Boolean>): Subscription {
+ listener.onDataChanged(true)
+ return mockSubscription
+ }
+ }
val factoryDataSource = PeopleHubViewModelFactoryDataSourceImpl(
- mockActivityStarter, fakeModelDataSource)
+ mockActivityStarter,
+ fakeModelDataSource,
+ fakeSettingDataSource
+ )
val fakeListener = FakeDataListener<PeopleHubViewModelFactory>()
val mockClickView = mock(View::class.java)
@@ -112,6 +121,41 @@
same(mockClickView)
)
}
+
+ @Test
+ fun testViewModelDataSource_notVisibleIfSettingDisabled() {
+ val fakeClickIntent = PendingIntent.getActivity(context, 0, Intent("action"), 0)
+ val fakePerson = fakePersonModel("id", "name", fakeClickIntent)
+ val fakeModel = PeopleHubModel(listOf(fakePerson))
+ val mockSubscription = mock(Subscription::class.java)
+ val fakeModelDataSource = object : DataSource<PeopleHubModel> {
+ override fun registerListener(listener: DataListener<PeopleHubModel>): Subscription {
+ listener.onDataChanged(fakeModel)
+ return mockSubscription
+ }
+ }
+ val fakeSettingDataSource = object : DataSource<Boolean> {
+ override fun registerListener(listener: DataListener<Boolean>): Subscription {
+ listener.onDataChanged(false)
+ return mockSubscription
+ }
+ }
+ val factoryDataSource = PeopleHubViewModelFactoryDataSourceImpl(
+ mockActivityStarter,
+ fakeModelDataSource,
+ fakeSettingDataSource
+ )
+ val fakeListener = FakeDataListener<PeopleHubViewModelFactory>()
+ val mockClickView = mock(View::class.java)
+
+ factoryDataSource.registerListener(fakeListener)
+
+ val viewModel = (fakeListener.lastSeen as Maybe.Just).value
+ .createWithAssociatedClickView(mockClickView)
+ assertThat(viewModel.isVisible).isFalse()
+ val people = viewModel.people.toList()
+ assertThat(people.size).isEqualTo(0)
+ }
}
/** Works around Mockito matchers returning `null` and breaking non-nullable Kotlin code. */
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 7c78ef8..743fd6a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -456,7 +456,7 @@
mLog.e("setWifiTethering: failed to get WifiManager!");
return TETHER_ERROR_SERVICE_UNAVAIL;
}
- if ((enable && mgr.startSoftAp(null /* use existing wifi config */))
+ if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
|| (!enable && mgr.stopSoftAp())) {
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 0273ed3..cdbc541 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -94,7 +94,7 @@
import android.net.util.InterfaceParams;
import android.net.util.NetworkConstants;
import android.net.util.SharedLog;
-import android.net.wifi.WifiConfiguration;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
@@ -806,12 +806,12 @@
// TODO: Test with and without interfaceStatusChanged().
@Test
public void failingWifiTetheringLegacyApBroadcast() throws Exception {
- when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+ when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startSoftAp(null);
+ verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService);
@@ -833,12 +833,12 @@
// TODO: Test with and without interfaceStatusChanged().
@Test
public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
- when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+ when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startSoftAp(null);
+ verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService);
@@ -907,13 +907,13 @@
// TODO: Test with and without interfaceStatusChanged().
@Test
public void failureEnablingIpForwarding() throws Exception {
- when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+ when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startSoftAp(null);
+ verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNMService);
@@ -1155,7 +1155,7 @@
when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
.thenReturn(upstreamState);
- when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+ when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
mLooper.dispatchAll();
tetherState = callback.pollTetherStatesChanged();
diff --git a/services/Android.bp b/services/Android.bp
index fd4094f..8376d2b 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -111,7 +111,7 @@
srcs: [":services-sources"],
installable: false,
// TODO: remove the --hide options below
- args: " --show-single-annotation android.annotation.SystemApi" +
+ args: " --show-single-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.INTERNAL,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
" --hide-annotation android.annotation.Hide" +
" --hide-package com.google.android.startop.iorap" +
" --hide ReferencesHidden" +
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 92d1da5..c0f10a3 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,8 +16,6 @@
package com.android.server;
-import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
-
import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -39,7 +37,6 @@
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -526,11 +523,11 @@
// Grant permission for the carrier app.
Intent intent = new Intent(action);
- TelephonyManager telephonyManager = (TelephonyManager)
- mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<String> carrierPackages = telephonyManager
- .getCarrierPackageNamesForIntentAndPhone(
- intent, getPhoneIdFromSubId(subId));
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ List<String> carrierPackages =
+ telephonyManager.getCarrierPackageNamesForIntentAndPhone(
+ intent, SubscriptionManager.getPhoneId(subId));
if (carrierPackages != null && carrierPackages.size() == 1) {
LocalServices.getService(UriGrantsManagerInternal.class)
.grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
@@ -542,13 +539,4 @@
return contentUri;
}
}
-
- private int getPhoneIdFromSubId(int subId) {
- SubscriptionManager subManager = (SubscriptionManager)
- mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- if (subManager == null) return INVALID_SIM_SLOT_INDEX;
- SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
- if (info == null) return INVALID_SIM_SLOT_INDEX;
- return info.getSimSlotIndex();
- }
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 29d3a1d7..9b1d9e9 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3824,7 +3824,7 @@
}
}
if ((hasInstall || hasInstallOp) && hasWrite) {
- return Zygote.MOUNT_EXTERNAL_WRITE;
+ return Zygote.MOUNT_EXTERNAL_INSTALLER;
}
// Otherwise we're willing to give out sandboxed or non-sandboxed if
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 7f62747..6bc117b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -16,7 +16,6 @@
package com.android.server;
-import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_DATA;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_VOICE;
@@ -60,7 +59,6 @@
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -99,7 +97,7 @@
* and 15973975 by saving the phoneId of the registrant and then using the
* phoneId when deciding to to make a callback. This is necessary because
* a subId changes from to a dummy value when a SIM is removed and thus won't
- * compare properly. Because getPhoneIdFromSubId(int subId) handles
+ * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles
* the dummy value conversion we properly do the callbacks.
*
* Eventually we may want to remove the notion of dummy value but for now this
@@ -133,7 +131,7 @@
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
@@ -233,7 +231,7 @@
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private int mDefaultPhoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
private int[] mRingingCallState;
@@ -360,7 +358,7 @@
SubscriptionManager.getDefaultSubscriptionId());
int newDefaultPhoneId = intent.getIntExtra(
SubscriptionManager.EXTRA_SLOT_INDEX,
- getPhoneIdFromSubId(newDefaultSubId));
+ SubscriptionManager.getPhoneId(newDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
+ " current mDefaultPhoneId=" + mDefaultPhoneId
@@ -770,7 +768,7 @@
return;
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
@@ -1101,7 +1099,7 @@
// Called only by Telecomm to communicate call state across different phone accounts. So
// there is no need to add a valid subId or slotId.
broadcastCallStateChanged(state, phoneNumber,
- SubscriptionManager.INVALID_SIM_SLOT_INDEX,
+ SubscriptionManager.INVALID_PHONE_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
@@ -1326,7 +1324,7 @@
synchronized (mRecords) {
mCarrierNetworkChangeState = active;
for (int subId : subIds) {
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
if (VDBG) {
log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
@@ -1359,7 +1357,7 @@
log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellInfo.set(phoneId, cellInfo);
@@ -1450,7 +1448,7 @@
log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCallForwarding[phoneId] = cfi;
@@ -1478,7 +1476,7 @@
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mDataActivity[phoneId] = state;
@@ -1629,7 +1627,7 @@
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellLocation[phoneId] = cellLocation;
@@ -1657,7 +1655,7 @@
if (!checkNotifyPermission("notifyOtaspChanged()" )) {
return;
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mOtaspMode[phoneId] = otaspMode;
@@ -1761,7 +1759,7 @@
if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
return;
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mImsReasonInfo.set(phoneId, imsReasonInfo);
@@ -1821,7 +1819,7 @@
if (VDBG) {
log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
}
- int phoneId = getPhoneIdFromSubId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mSrvccState[phoneId] = state;
@@ -2229,7 +2227,7 @@
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
}
// If the phoneId is invalid, the broadcast is for overall call state.
- if (phoneId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
@@ -2702,18 +2700,4 @@
private static CallQuality createCallQuality() {
return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
-
- private int getPhoneIdFromSubId(int subId) {
- SubscriptionManager subManager = (SubscriptionManager)
- mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- if (subManager == null) return INVALID_SIM_SLOT_INDEX;
-
- if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
- subId = SubscriptionManager.getDefaultSubscriptionId();
- }
-
- SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
- if (info == null) return INVALID_SIM_SLOT_INDEX;
- return info.getSimSlotIndex();
- }
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 1a62eb2..335cac8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4488,12 +4488,13 @@
}
if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+ && !isStreamMutedByRingerOrZenMode(AudioSystem.STREAM_MUSIC)
&& DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice)
&& mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
&& mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
&& (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
if (DEBUG_VOL) {
- Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
+ Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
newDevice, AudioSystem.getOutputDeviceName(newDevice)));
}
mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
@@ -6167,6 +6168,7 @@
pw.println("\nRinger mode: ");
pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
+ pw.println("- zen mode:" + Settings.Global.zenModeToString(mNm.getZenMode()));
dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
pw.print("- delegate = "); pw.println(mRingerModeDelegate);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c05b704..0d8f257 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4952,6 +4952,7 @@
mBootMsgDialog.getWindow().setDimAmount(1);
WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+ lp.setFitWindowInsetsTypes(0 /* types */);
mBootMsgDialog.getWindow().setAttributes(lp);
mBootMsgDialog.setCancelable(false);
mBootMsgDialog.show();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2283041..667e713 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -33,6 +33,7 @@
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_GESTURES;
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
+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.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
@@ -49,7 +50,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -63,6 +63,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -149,13 +150,17 @@
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InsetsFlags;
+import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewRootImpl;
-import android.view.WindowInsets;
+import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Side.InsetsSide;
+import android.view.WindowInsets.Type;
+import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -337,6 +342,7 @@
private int mLastAppearance;
private int mLastFullscreenAppearance;
private int mLastDockedAppearance;
+ private int mLastBehavior;
private final Rect mNonDockedStackBounds = new Rect();
private final Rect mDockedStackBounds = new Rect();
private final Rect mLastNonDockedStackBounds = new Rect();
@@ -353,6 +359,7 @@
private static final Rect sTmpRect = new Rect();
private static final Rect sTmpNavFrame = new Rect();
private static final Rect sTmpLastParentFrame = new Rect();
+ private static final int[] sTmpTypesAndSides = new int[2];
private WindowState mTopFullscreenOpaqueWindowState;
private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
@@ -1228,7 +1235,8 @@
final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
if (layoutInScreenAndInsetDecor && !screenDecor) {
- if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+ if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ || (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) == 0) {
outFrame.set(displayFrames.mUnrestricted);
} else {
outFrame.set(displayFrames.mRestricted);
@@ -1281,11 +1289,27 @@
}
}
+ private static void getImpliedTypesAndSidesToFit(LayoutParams attrs, int[] typesAndSides) {
+ typesAndSides[0] = attrs.getFitWindowInsetsTypes();
+ typesAndSides[1] = attrs.getFitWindowInsetsSides();
+ final boolean forceDrawsBarBackgrounds =
+ (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
+ && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
+ if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || forceDrawsBarBackgrounds) {
+ if ((attrs.privateFlags & PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND) != 0) {
+ typesAndSides[1] &= ~Side.BOTTOM;
+ } else {
+ typesAndSides[0] &= ~Type.systemBars();
+ }
+ }
+ }
+
+ // TODO(b/118118435): remove after migration
private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
int impliedFlags = 0;
final boolean forceWindowDrawsBarBackgrounds =
(attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
- && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
+ && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
|| forceWindowDrawsBarBackgrounds) {
impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
@@ -1300,6 +1324,13 @@
synchronized (mLock) {
mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
mDisplayContent.reevaluateStatusBarVisibility();
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL && mNavigationBar != null) {
+ final InsetsControlTarget target =
+ mNavigationBar.getControllableInsetProvider().getControlTarget();
+ if (target != null) {
+ target.showInsets(Type.navigationBars(), false /* fromIme */);
+ }
+ }
}
}
};
@@ -1376,11 +1407,18 @@
// For purposes of putting out fake window up to steal focus, we will
// drive nav being hidden only by whether it is requested.
final int sysui = mLastSystemUiFlags;
- boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+ final int behavior = mLastBehavior;
+ boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
+ ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
+ : mNavigationBar != null && mNavigationBar.getControllableInsetProvider() != null
+ && mNavigationBar.getControllableInsetProvider().isClientVisible()
+ && !mDisplayContent.getInsetsPolicy().isTransient(ITYPE_NAVIGATION_BAR);
boolean navTranslucent = (sysui
& (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
- boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
- boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
+ boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0
+ || (behavior & BEHAVIOR_SHOW_BARS_BY_SWIPE) != 0;
+ boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
+ || (behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
boolean navAllowedHidden = immersive || immersiveSticky;
navTranslucent &= !immersiveSticky; // transient trumps translucent
boolean isKeyguardShowing = isStatusBarKeyguard()
@@ -1464,6 +1502,9 @@
displayFrames.mUnrestricted /* stableFrame */);
w.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
w.computeFrameLw();
+ if (w.getControllableInsetProvider() != null) {
+ w.getControllableInsetProvider().updateSourceFrame();
+ }
final Rect frame = w.getFrameLw();
if (frame.left <= 0 && frame.top <= 0) {
@@ -1526,6 +1567,11 @@
// Let the status bar determine its size.
mStatusBar.computeFrameLw();
+ // Update the source frame to provide insets to other windows during layout.
+ if (mStatusBar.getControllableInsetProvider() != null) {
+ mStatusBar.getControllableInsetProvider().updateSourceFrame();
+ }
+
// For layout, the status bar is always at the top with our fixed height.
displayFrames.mStable.top = displayFrames.mUnrestricted.top
+ mStatusBarHeightForRotation[displayFrames.mRotation];
@@ -1540,7 +1586,8 @@
sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
mStatusBarController.setContentFrame(sTmpRect);
- boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
+ boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0
+ || mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR);
boolean statusBarTranslucent = (sysui
& (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
@@ -1676,6 +1723,9 @@
navigationFrame /* stableFrame */);
mNavigationBar.getWindowFrames().setDisplayCutout(displayFrames.mDisplayCutout);
mNavigationBar.computeFrameLw();
+ if (mNavigationBar.getControllableInsetProvider() != null) {
+ mNavigationBar.getControllableInsetProvider().updateSourceFrame();
+ }
mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
@@ -1811,19 +1861,44 @@
final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
- final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
- || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
-
final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN;
final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
sf.set(displayFrames.mStable);
- if (type == TYPE_INPUT_METHOD) {
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+ getImpliedTypesAndSidesToFit(attrs, sTmpTypesAndSides);
+ final @InsetsType int typesToFit = sTmpTypesAndSides[0];
+ final @InsetsSide int sidesToFit = sTmpTypesAndSides[1];
+ final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
+ final Rect dfu = displayFrames.mUnrestricted;
+ Insets insets = Insets.of(0, 0, 0, 0);
+ for (int i = types.size() - 1; i >= 0; i--) {
+ insets = Insets.max(insets, mDisplayContent.getInsetsStateController()
+ .getInsetsForDispatch(win).getSource(types.valueAt(i))
+ .calculateInsets(dfu, attrs.getFitIgnoreVisibility()));
+ }
+ final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
+ final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
+ final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
+ final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
+ df.set(left, top, dfu.right - right, dfu.bottom - bottom);
+ if (attached == null) {
+ pf.set(df);
+ vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
+ ? displayFrames.mCurrent : displayFrames.mDock);
+ } else {
+ pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df);
+ vf.set(attached.getVisibleFrameLw());
+ }
+ cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE
+ ? displayFrames.mDock : displayFrames.mContent);
+ dcf.set(displayFrames.mSystem);
+ } else if (type == TYPE_INPUT_METHOD) {
vf.set(displayFrames.mDock);
cf.set(displayFrames.mDock);
df.set(displayFrames.mDock);
- windowFrames.mParentFrame.set(displayFrames.mDock);
+ pf.set(displayFrames.mDock);
// IM dock windows layout below the nav bar...
pf.bottom = df.bottom = displayFrames.mUnrestricted.bottom;
// ...with content insets above the nav bar
@@ -1989,7 +2064,7 @@
}
}
} else if (layoutInScreen || (sysUiFl
- & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
+ "): IN_SCREEN");
@@ -2039,7 +2114,7 @@
cf.set(displayFrames.mUnrestricted);
df.set(displayFrames.mUnrestricted);
pf.set(displayFrames.mUnrestricted);
- } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
+ } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
df.set(displayFrames.mRestricted);
pf.set(displayFrames.mRestricted);
@@ -2111,8 +2186,12 @@
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
final boolean attachedInParent = attached != null && !layoutInScreen;
+ final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
+ || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
+ || !win.getClientInsetsState().getSource(ITYPE_STATUS_BAR).isVisible();
final boolean requestedHideNavigation =
- (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+ (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
+ || !win.getClientInsetsState().getSource(ITYPE_NAVIGATION_BAR).isVisible();
// TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
// cropped / shifted to the displayFrame in WindowState.
@@ -2195,6 +2274,9 @@
}
win.computeFrameLw();
+ if (win.getControllableInsetProvider() != null) {
+ win.getControllableInsetProvider().updateSourceFrame();
+ }
// Dock windows carve out the bottom of the screen, so normal windows
// can't appear underneath them.
if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
@@ -2985,7 +3067,7 @@
mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
} else {
- controlTarget.showInsets(WindowInsets.Type.systemBars(), false);
+ controlTarget.showInsets(Type.systemBars(), false);
}
} else {
boolean sb = mStatusBarController.checkShowTransientBarLw();
@@ -3109,6 +3191,7 @@
&& mLastAppearance == appearance
&& mLastFullscreenAppearance == fullscreenAppearance
&& mLastDockedAppearance == dockedAppearance
+ && mLastBehavior == behavior
&& mLastFocusIsFullscreen == isFullscreen
&& mLastFocusIsImmersive == isImmersive
&& mFocusedApp == win.getAppToken()
@@ -3125,6 +3208,7 @@
mLastAppearance = appearance;
mLastFullscreenAppearance = fullscreenAppearance;
mLastDockedAppearance = dockedAppearance;
+ mLastBehavior = behavior;
mLastFocusIsFullscreen = isFullscreen;
mLastFocusIsImmersive = isImmersive;
mFocusedApp = win.getAppToken();
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index 82ac6b8..bef1442 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -46,6 +46,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -189,6 +190,7 @@
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
+ lp.setFitWindowInsetsTypes(lp.getFitWindowInsetsTypes() & ~Type.statusBars());
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ImmersiveModeConfirmation");
lp.windowAnimations = com.android.internal.R.style.Animation_ImmersiveModeConfirmation;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index d50bcc4..af84836 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -45,7 +45,7 @@
private final IntArray mShowingTransientTypes = new IntArray();
private WindowState mFocusedWin;
- private BarWindow mTopBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
+ private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
@@ -57,15 +57,15 @@
/** Updates the target which can control system bars. */
void updateBarControlTarget(@Nullable WindowState focusedWin) {
mFocusedWin = focusedWin;
- mStateController.onBarControlTargetChanged(getTopControlTarget(focusedWin),
- getFakeTopControlTarget(focusedWin),
+ mStateController.onBarControlTargetChanged(getStatusControlTarget(focusedWin),
+ getFakeStatusControlTarget(focusedWin),
getNavControlTarget(focusedWin),
getFakeNavControlTarget(focusedWin));
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
return;
}
- mTopBar.setVisible(focusedWin == null
- || focusedWin != getTopControlTarget(focusedWin)
+ mStatusBar.setVisible(focusedWin == null
+ || focusedWin != getStatusControlTarget(focusedWin)
|| focusedWin.getClientInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
mNavBar.setVisible(focusedWin == null
|| focusedWin != getNavControlTarget(focusedWin)
@@ -110,6 +110,10 @@
mStateController.notifyInsetsChanged();
}
+ boolean isTransient(@InternalInsetsType int type) {
+ return mShowingTransientTypes.indexOf(type) != -1;
+ }
+
/**
* @see InsetsStateController#getInsetsForDispatch
*/
@@ -130,8 +134,8 @@
if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
return;
}
- if (windowState == getTopControlTarget(mFocusedWin)) {
- mTopBar.setVisible(state.getSource(ITYPE_STATUS_BAR).isVisible());
+ if (windowState == getStatusControlTarget(mFocusedWin)) {
+ mStatusBar.setVisible(state.getSource(ITYPE_STATUS_BAR).isVisible());
}
if (windowState == getNavControlTarget(mFocusedWin)) {
mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
@@ -164,7 +168,8 @@
}
}
- private @Nullable InsetsControlTarget getFakeTopControlTarget(@Nullable WindowState focused) {
+ private @Nullable InsetsControlTarget getFakeStatusControlTarget(
+ @Nullable WindowState focused) {
if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
return focused;
}
@@ -178,7 +183,7 @@
return null;
}
- private @Nullable InsetsControlTarget getTopControlTarget(@Nullable WindowState focusedWin) {
+ private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) {
if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
return mTransientControlTarget;
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 69e8fdc..0821873 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -141,9 +141,10 @@
}
/**
- * Called when a layout pass has occurred.
+ * The source frame can affect the layout of other windows, so this should be called once the
+ * window gets laid out.
*/
- void onPostLayout() {
+ void updateSourceFrame() {
if (mWin == null) {
return;
}
@@ -155,6 +156,17 @@
mTmpRect.inset(mWin.mGivenContentInsets);
}
mSource.setFrame(mTmpRect);
+ }
+
+ /**
+ * Called when a layout pass has occurred.
+ */
+ void onPostLayout() {
+ if (mWin == null) {
+ return;
+ }
+
+ updateSourceFrame();
if (mControl != null) {
final Rect frame = mWin.getWindowFrames().mFrame;
if (mControl.setSurfacePosition(frame.left, frame.top)) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 12b2845..dee9e9f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -414,7 +414,7 @@
final LayoutParams attrs = mainWindow.getAttrs();
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
- mFullSnapshotScale);
+ mFullSnapshotScale, mainWindow.getClientInsetsState());
final int width = (int) (task.getBounds().width() * mFullSnapshotScale);
final int height = (int) (task.getBounds().height() * mFullSnapshotScale);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index b3750e9..1484d6a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -71,6 +71,7 @@
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -154,6 +155,7 @@
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
final TaskDescription taskDescription = new TaskDescription();
taskDescription.setBackgroundColor(WHITE);
+ final WindowState topFullscreenWindow;
final int sysUiVis;
final int windowFlags;
final int windowPrivateFlags;
@@ -173,7 +175,7 @@
+ task);
return null;
}
- final WindowState topFullscreenWindow = topFullscreenActivity.getTopFullscreenWindow();
+ topFullscreenWindow = topFullscreenActivity.getTopFullscreenWindow();
if (mainWindow == null || topFullscreenWindow == null) {
Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+ activity);
@@ -220,7 +222,7 @@
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
windowFlags, windowPrivateFlags, taskBounds,
- currentOrientation);
+ currentOrientation, topFullscreenWindow.getClientInsetsState());
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
@@ -238,7 +240,7 @@
TaskSnapshotSurface(WindowManagerService service, Window window, SurfaceControl surfaceControl,
TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
int sysUiVis, int windowFlags, int windowPrivateFlags, Rect taskBounds,
- int currentOrientation) {
+ int currentOrientation, InsetsState insetsState) {
mService = service;
mSurface = service.mSurfaceFactory.get();
mHandler = new Handler(mService.mH.getLooper());
@@ -251,7 +253,7 @@
mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
mTaskBounds = taskBounds;
mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
- windowPrivateFlags, sysUiVis, taskDescription, 1f);
+ windowPrivateFlags, sysUiVis, taskDescription, 1f, insetsState);
mStatusBarColor = taskDescription.getStatusBarColor();
mOrientationOnCreation = currentOrientation;
mTransaction = mService.mTransactionFactory.get();
@@ -502,9 +504,10 @@
private final int mWindowPrivateFlags;
private final int mSysUiVis;
private final float mScale;
+ private final InsetsState mInsetsState;
SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
- TaskDescription taskDescription, float scale) {
+ TaskDescription taskDescription, float scale, InsetsState insetsState) {
mWindowFlags = windowFlags;
mWindowPrivateFlags = windowPrivateFlags;
mSysUiVis = sysUiVis;
@@ -524,6 +527,7 @@
&& context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
mStatusBarPaint.setColor(mStatusBarColor);
mNavigationBarPaint.setColor(mNavigationBarColor);
+ mInsetsState = insetsState;
}
void setInsets(Rect contentInsets, Rect stableInsets) {
@@ -534,8 +538,11 @@
int getStatusBarColorViewHeight() {
final boolean forceBarBackground =
(mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)) {
+ if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
+ ? STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
+ : STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
return (int) (getColorViewTopInset(mStableInsets.top, mContentInsets.top) * mScale);
} else {
return 0;
@@ -545,8 +552,11 @@
private boolean isNavigationBarColorViewVisible() {
final boolean forceBarBackground =
(mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mSysUiVis, mNavigationBarColor, mWindowFlags, forceBarBackground);
+ return ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
+ ? NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, forceBarBackground)
+ : NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
}
void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 0490bac..97186b4 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -207,6 +207,7 @@
return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
}
+ // TODO(b/118118435): Remove after migration.
/**
* Calculate the insets for the type
* {@link android.view.WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index 10c8ef0..74d5c04 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -19,6 +19,8 @@
import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
import android.provider.AndroidDeviceConfig;
import android.provider.DeviceConfig;
@@ -72,8 +74,8 @@
WindowManagerConstants(WindowManagerGlobalLock globalLock,
Runnable updateSystemGestureExclusionCallback,
DeviceConfigInterface deviceConfig) {
- mGlobalLock = globalLock;
- mUpdateSystemGestureExclusionCallback = updateSystemGestureExclusionCallback;
+ mGlobalLock = checkNotNull(globalLock);
+ mUpdateSystemGestureExclusionCallback = checkNotNull(updateSystemGestureExclusionCallback);
mDeviceConfig = deviceConfig;
mListenerAndroid = this::onAndroidPropertiesChanged;
mListenerWindowManager = this::onWindowPropertiesChanged;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3fe5c7d..acaaed9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -405,8 +405,7 @@
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
- final WindowManagerConstants mConstants = new WindowManagerConstants(this,
- DeviceConfigInterface.REAL);
+ final WindowManagerConstants mConstants;
final WindowTracing mWindowTracing;
@@ -1232,6 +1231,7 @@
mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create(context.getResources());
+ mConstants = new WindowManagerConstants(this, DeviceConfigInterface.REAL);
mConstants.start(new HandlerExecutor(mH));
LocalServices.addService(WindowManagerInternal.class, new LocalService());
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index eb1753b..078bab4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7440,7 +7440,7 @@
}
/**
- * Returns whether or auto time is used on the device or not.
+ * Returns whether auto time is used on the device or not.
*/
@Override
public boolean getAutoTime(ComponentName who) {
@@ -7453,6 +7453,42 @@
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
}
+ /**
+ * Set whether auto time zone is enabled on the device.
+ */
+ @Override
+ public void setAutoTimeZone(ComponentName who, boolean enabled) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ // TODO (b/145286957) Refactor security checks
+ enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+ mInjector.binderWithCleanCallingIdentity(() ->
+ mInjector.settingsGlobalPutInt(Global.AUTO_TIME_ZONE, enabled ? 1 : 0));
+
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.SET_AUTO_TIME_ZONE)
+ .setAdmin(who)
+ .setBoolean(enabled)
+ .write();
+ }
+
+ /**
+ * Returns whether auto time zone is used on the device or not.
+ */
+ @Override
+ public boolean getAutoTimeZone(ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+ return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
+ }
+
@Override
public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) {
if (!mHasFeature) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 3f09f57..f54f885 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3673,6 +3673,45 @@
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
+ public void testSetAutoTimeZoneModifiesSetting() throws Exception {
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setupDeviceOwner();
+ dpm.setAutoTimeZone(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
+
+ dpm.setAutoTimeZone(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
+ }
+
+ public void testSetAutoTimeZoneWithPOOnUser0() throws Exception {
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setupProfileOwnerOnUser0();
+ dpm.setAutoTimeZone(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
+
+ dpm.setAutoTimeZone(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
+ }
+
+ public void testSetAutoTimeZoneFailWithPONotOnUser0() throws Exception {
+ setupProfileOwner();
+ assertExpectException(SecurityException.class, null,
+ () -> dpm.setAutoTimeZone(admin1, false));
+ verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE,
+ 0);
+ }
+
+ public void testSetAutoTimeZoneWithPOOfOrganizationOwnedDevice() throws Exception {
+ setupProfileOwner();
+ configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+
+ dpm.setAutoTimeZone(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
+
+ dpm.setAutoTimeZone(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
+ }
+
public void testSetTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 62ab11c..de73645 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -36,6 +36,7 @@
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -45,6 +46,7 @@
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
@@ -55,6 +57,10 @@
import android.util.Pair;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
+import android.view.InsetsState;
+import android.view.ViewRootImpl;
+import android.view.WindowInsets.Side;
+import android.view.WindowInsets.Type;
import android.view.WindowManager;
import androidx.test.filters.FlakyTest;
@@ -97,8 +103,6 @@
final WindowManager.LayoutParams attrs = mWindow.mAttrs;
attrs.width = MATCH_PARENT;
attrs.height = MATCH_PARENT;
- attrs.flags =
- FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
attrs.format = PixelFormat.TRANSLUCENT;
}
@@ -134,8 +138,186 @@
}
@Test
+ public void layoutWindowLw_fitStatusBars() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.statusBars());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_fitNavigationBars() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.navigationBars());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
public void layoutWindowLw_appDrawsBars() {
- mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_forceAppDrawBars() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.privateFlags = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_onlyDrawBottomBar() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.privateFlags = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_fitAllSides() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.setFitWindowInsetsSides(Side.all());
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_fitTopOnly() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.setFitWindowInsetsSides(Side.TOP);
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_fitMax() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final InsetsState state =
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow);
+ state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+ state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
+ mWindow.mAttrs.setFitIgnoreVisibility(true);
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ @Test
+ public void layoutWindowLw_fitNonMax() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ final InsetsState state =
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow);
+ state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+ state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
+ mWindow.mAttrs.setFitIgnoreVisibility(false);
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+ }
+
+ // TODO(b/118118435): remove after migration
+ @Test
+ public void layoutWindowLw_appDrawsBarsLegacy() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -148,9 +330,12 @@
assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
}
+ // TODO(b/118118435): remove after migration
@Test
public void layoutWindowLw_appWontDrawBars() {
- mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -163,10 +348,13 @@
assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT);
}
+ // TODO(b/118118435): remove after migration
@Test
public void layoutWindowLw_appWontDrawBars_forceStatusAndNav() throws Exception {
- mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
+ mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+ mWindow.mAttrs.privateFlags = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -179,11 +367,14 @@
assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
}
+ // TODO(b/118118435): remove after migration (keyguard dialog is not special with the new logic)
@Test
public void layoutWindowLw_keyguardDialog_hideNav() {
mWindow.mAttrs.type = TYPE_KEYGUARD_DIALOG;
- mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ mWindow.mAttrs.setFitWindowInsetsTypes(0 /* types */);
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* uiMode */);
@@ -200,6 +391,8 @@
public void layoutWindowLw_withDisplayCutout() {
addDisplayCutout();
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -216,6 +409,8 @@
public void layoutWindowLw_withDisplayCutout_never() {
addDisplayCutout();
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
addWindow(mWindow);
@@ -233,7 +428,11 @@
public void layoutWindowLw_withDisplayCutout_layoutFullscreen() {
addDisplayCutout();
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ mWindow.mAttrs.setFitWindowInsetsTypes(
+ mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -243,14 +442,18 @@
assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
- assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
}
@Test
public void layoutWindowLw_withDisplayCutout_fullscreen() {
addDisplayCutout();
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow)
+ .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -267,7 +470,11 @@
public void layoutWindowLw_withDisplayCutout_fullscreenInCutout() {
addDisplayCutout();
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(mWindow)
+ .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
addWindow(mWindow);
@@ -286,6 +493,9 @@
public void layoutWindowLw_withDisplayCutout_landscape() {
addDisplayCutout();
setRotation(ROTATION_90);
+
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -303,6 +513,9 @@
public void layoutWindowLw_withDisplayCutout_seascape() {
addDisplayCutout();
setRotation(ROTATION_270);
+
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -321,7 +534,11 @@
addDisplayCutout();
setRotation(ROTATION_90);
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ mWindow.mAttrs.setFitWindowInsetsTypes(
+ mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -339,6 +556,7 @@
addDisplayCutout();
mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN;
+ mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars() & ~Type.statusBars());
mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY;
mWindow.mAttrs.width = DISPLAY_WIDTH;
mWindow.mAttrs.height = DISPLAY_HEIGHT;
@@ -356,7 +574,11 @@
addDisplayCutout();
setRotation(ROTATION_90);
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ mWindow.mAttrs.setFitWindowInsetsTypes(
+ mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
addWindow(mWindow);
@@ -372,6 +594,8 @@
@Test
public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() {
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
addWindow(mWindow);
@@ -392,6 +616,8 @@
@Test
public void layoutWindowLw_withForwardInset_SoftInputAdjustNothing() {
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
addWindow(mWindow);
@@ -408,9 +634,12 @@
assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
}
+ // TODO(b/118118435): remove after removing PolicyControl
@FlakyTest(bugId = 129711077)
@Test
public void layoutWindowLw_withImmersive_SoftInputAdjustResize() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
synchronized (mWm.mGlobalLock) {
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
mWindow.mAttrs.flags = 0;
@@ -433,9 +662,12 @@
}
}
+ // TODO(b/118118435): remove after removing PolicyControl
@FlakyTest(bugId = 129711077)
@Test
public void layoutWindowLw_withImmersive_SoftInputAdjustNothing() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
synchronized (mWm.mGlobalLock) {
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
mWindow.mAttrs.flags = 0;
@@ -457,9 +689,12 @@
}
}
+ // TODO(b/118118435): remove after removing PolicyControl
@FlakyTest(bugId = 129711077)
@Test
public void layoutWindowLw_withForceImmersive_fullscreen() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
synchronized (mWm.mGlobalLock) {
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
mWindow.mAttrs.flags = 0;
@@ -481,9 +716,12 @@
}
}
+ // TODO(b/118118435): remove after removing PolicyControl
@FlakyTest(bugId = 129711077)
@Test
public void layoutWindowLw_withForceImmersive_nonFullscreen() {
+ assumeTrue(ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL);
+
synchronized (mWm.mGlobalLock) {
mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
mWindow.mAttrs.flags = 0;
@@ -509,6 +747,9 @@
@Test
public void layoutHint_appWindow() {
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -530,6 +771,9 @@
@Test
public void layoutHint_appWindowInTask() {
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -553,6 +797,9 @@
@Test
public void layoutHint_appWindowInTask_outsideContentFrame() {
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -581,7 +828,8 @@
public void forceShowSystemBars_clearsSystemUIFlags() {
mDisplayPolicy.mLastSystemUiFlags |= SYSTEM_UI_FLAG_FULLSCREEN;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
- mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.flags =
+ FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mSystemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN;
mDisplayPolicy.setForceShowSystemBars(true);
addWindow(mWindow);
@@ -600,7 +848,8 @@
@Test
public void testScreenDecorWindows() {
final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow");
- decorWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ mWindow.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR
+ | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
decorWindow.mAttrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR;
addWindow(decorWindow);
addWindow(mWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index d4558dc..d0b3350 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -78,6 +78,8 @@
resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT);
+ resources.addOverride(R.dimen.navigation_bar_frame_height_landscape, NAV_BAR_HEIGHT);
+ resources.addOverride(R.dimen.navigation_bar_frame_height, NAV_BAR_HEIGHT);
doReturn(resources.getResources()).when(mDisplayPolicy).getCurrentUserResources();
doReturn(true).when(mDisplayPolicy).hasNavigationBar();
doReturn(true).when(mDisplayPolicy).hasStatusBar();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 817344f..2d418ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -74,7 +74,7 @@
0 /* systemUiVisibility */, false /* isTranslucent */);
mSurface = new TaskSnapshotSurface(mWm, new Window(), new SurfaceControl(), snapshot, "Test",
createTaskDescription(Color.WHITE, Color.RED, Color.BLUE), sysuiVis, windowFlags, 0,
- taskBounds, ORIENTATION_PORTRAIT);
+ taskBounds, ORIENTATION_PORTRAIT, null /* insetsState */);
}
private static TaskDescription createTaskDescription(int background, int statusBar,