Merge "SysUI: Fix a bunch of hacks around insets and cutouts" into pi-dev

am: 802bf39664

Change-Id: I2ba1dbd6dfcf031d93cb0f83740977c3ad0cb21e
This commit is contained in:
Adrian Roos
2018-03-09 14:57:18 +00:00
committed by android-build-merger
9 changed files with 71 additions and 238 deletions

View File

@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.systemui.volume.VolumeUiLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -89,4 +89,4 @@
</LinearLayout>
</LinearLayout>
</com.android.systemui.volume.VolumeUiLayout>
</FrameLayout>

View File

@@ -335,6 +335,7 @@
<style name="qs_theme" parent="qs_base">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
<item name="android:windowIsFloating">true</item>
</style>
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
@@ -345,7 +346,9 @@
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
<style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" />
<style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
<item name="android:windowIsFloating">true</item>
</style>
<style name="QSBorderlessButton">
<item name="android:padding">12dp</item>

View File

@@ -14,6 +14,7 @@
package com.android.systemui.globalactions;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
@@ -1356,11 +1357,17 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
// Window initialization
Window window = getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
// Inflate the decor view, so the attributes below are not overwritten by the theme.
window.getDecorView();
window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
window.setLayout(MATCH_PARENT, MATCH_PARENT);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

View File

@@ -15,12 +15,14 @@
package com.android.systemui.globalactions;
import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import android.app.Dialog;
import android.app.KeyguardManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Point;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
@@ -80,15 +82,21 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
// Window initialization
Window window = d.getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
// Inflate the decor view, so the attributes below are not overwritten by the theme.
window.getDecorView();
window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
window.requestFeature(Window.FEATURE_NO_TITLE);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

View File

@@ -20,7 +20,6 @@ import android.annotation.ColorInt;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -29,21 +28,19 @@ import android.util.TypedValue;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -210,18 +207,26 @@ public class KeyguardStatusBarView extends RelativeLayout
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void updateLayoutConsideringCutout() {
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (updateLayoutConsideringCutout()) {
requestLayout();
}
return super.onApplyWindowInsets(insets);
}
private boolean updateLayoutConsideringCutout() {
DisplayCutout dc = getRootWindowInsets().getDisplayCutout();
if (dc == null) {
updateLayoutParamsNoCutout();
return updateLayoutParamsNoCutout();
} else {
updateLayoutParamsForCutout(dc);
return updateLayoutParamsForCutout(dc);
}
}
private void updateLayoutParamsNoCutout() {
private boolean updateLayoutParamsNoCutout() {
if (mLayoutState == LAYOUT_NO_CUTOUT) {
return;
return false;
}
mLayoutState = LAYOUT_NO_CUTOUT;
@@ -240,11 +245,12 @@ public class KeyguardStatusBarView extends RelativeLayout
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
llp.setMarginStart(getResources().getDimensionPixelSize(
R.dimen.system_icons_super_container_margin_start));
return true;
}
private void updateLayoutParamsForCutout(DisplayCutout dc) {
private boolean updateLayoutParamsForCutout(DisplayCutout dc) {
if (mLayoutState == LAYOUT_CUTOUT) {
return;
return false;
}
mLayoutState = LAYOUT_CUTOUT;
@@ -268,6 +274,7 @@ public class KeyguardStatusBarView extends RelativeLayout
LinearLayout.LayoutParams llp =
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
llp.setMarginStart(0);
return true;
}
//TODO: Something is setting signal_cluster to MATCH_PARENT. Why?

View File

@@ -28,6 +28,7 @@ import android.view.DisplayCutout;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
@@ -37,7 +38,8 @@ import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.util.leak.RotationUtils;
import java.util.Objects;
public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
@@ -98,7 +100,7 @@ public class PhoneStatusBarView extends PanelBar {
// Always have Battery meters in the status bar observe the dark/light modes.
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);
if (updateOrientationAndCutout(getResources().getConfiguration().orientation)) {
postUpdateLayoutForCutout();
updateLayoutForCutout();
}
}
@@ -115,10 +117,20 @@ public class PhoneStatusBarView extends PanelBar {
// May trigger cutout space layout-ing
if (updateOrientationAndCutout(newConfig.orientation)) {
postUpdateLayoutForCutout();
updateLayoutForCutout();
requestLayout();
}
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (updateOrientationAndCutout(mLastOrientation)) {
updateLayoutForCutout();
requestLayout();
}
return super.onApplyWindowInsets(insets);
}
/**
*
* @param newOrientation may pass NO_VALUE for no change
@@ -133,12 +145,9 @@ public class PhoneStatusBarView extends PanelBar {
}
}
if (mDisplayCutout == null) {
DisplayCutout cutout = getRootWindowInsets().getDisplayCutout();
if (cutout != null) {
changed = true;
mDisplayCutout = cutout;
}
if (!Objects.equals(getRootWindowInsets().getDisplayCutout(), mDisplayCutout)) {
changed = true;
mDisplayCutout = getRootWindowInsets().getDisplayCutout();
}
return changed;
@@ -276,17 +285,6 @@ public class PhoneStatusBarView extends PanelBar {
updateSafeInsets();
}
private void postUpdateLayoutForCutout() {
Runnable r = new Runnable() {
@Override
public void run() {
updateLayoutForCutout();
}
};
// Let the cutout emulation draw first
postDelayed(r, 0);
}
private void updateCutoutLocation() {
// Not all layouts have a cutout (e.g., Car)
if (mCutoutSpace == null) {
@@ -310,40 +308,13 @@ public class PhoneStatusBarView extends PanelBar {
// or letterboxing from the right or left sides.
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
if (mDisplayCutout == null) {
lp.leftMargin = 0;
lp.rightMargin = 0;
return;
}
int leftMargin = 0;
int rightMargin = 0;
switch (RotationUtils.getRotation(getContext())) {
/*
* Landscape: <-|
* Seascape: |->
*/
case RotationUtils.ROTATION_LANDSCAPE:
leftMargin = getDisplayCutoutHeight();
break;
case RotationUtils.ROTATION_SEASCAPE:
rightMargin = getDisplayCutoutHeight();
break;
default:
break;
}
lp.leftMargin = leftMargin;
lp.rightMargin = rightMargin;
}
//TODO: Find a better way
private int getDisplayCutoutHeight() {
if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
return 0;
}
Rect r = mDisplayCutout.getBoundingRect();
return r.bottom - r.top;
lp.leftMargin = mDisplayCutout.getSafeInsetLeft();
lp.rightMargin = mDisplayCutout.getSafeInsetRight();
}
}

View File

@@ -207,8 +207,6 @@ public class VolumeDialogImpl implements VolumeDialog {
rescheduleTimeoutH();
return true;
});
VolumeUiLayout uiLayout = VolumeUiLayout.get(mDialogView);
uiLayout.updateRotation();
mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
mRinger = mDialog.findViewById(R.id.ringer);

View File

@@ -1,153 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.volume;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.DisplayCutout;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.util.leak.RotationUtils;
public class VolumeUiLayout extends FrameLayout {
private View mChild;
private int mRotation = ROTATION_NONE;
@Nullable
private DisplayCutout mDisplayCutout;
public VolumeUiLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mDisplayCutout = null;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mChild == null) {
if (getChildCount() != 0) {
mChild = getChildAt(0);
updateRotation();
} else {
return;
}
}
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateRotation();
}
private void setDisplayCutout() {
if (mDisplayCutout == null && getRootWindowInsets() != null) {
DisplayCutout cutout = getRootWindowInsets().getDisplayCutout();
if (cutout != null) {
mDisplayCutout = cutout;
}
}
}
public void updateRotation() {
setDisplayCutout();
if (mChild == null) {
if (getChildCount() != 0) {
mChild = getChildAt(0);
}
}
int rotation = RotationUtils.getRotation(getContext());
if (rotation != mRotation) {
updateSafeInsets(rotation);
mRotation = rotation;
}
}
private void updateSafeInsets(int rotation) {
// Depending on our rotation, we may have to work around letterboxing from the right
// side from the navigation bar or a cutout.
MarginLayoutParams lp = (MarginLayoutParams) mChild.getLayoutParams();
int margin = (int) getResources().getDimension(R.dimen.volume_dialog_base_margin);
switch (rotation) {
/*
* Landscape: <-|. Have to deal with the nav bar
* Seascape: |->. Have to deal with the cutout
*/
case RotationUtils.ROTATION_LANDSCAPE:
margin += getNavBarHeight();
break;
case RotationUtils.ROTATION_SEASCAPE:
margin += getDisplayCutoutHeight();
break;
default:
break;
}
lp.rightMargin = margin;
mChild.setLayoutParams(lp);
}
private int getNavBarHeight() {
return (int) getResources().getDimension(R.dimen.navigation_bar_size);
}
//TODO: Find a better way
private int getDisplayCutoutHeight() {
if (mDisplayCutout == null || mDisplayCutout.isEmpty()) {
return 0;
}
Rect r = mDisplayCutout.getBoundingRect();
return r.bottom - r.top;
}
@Override
public ViewOutlineProvider getOutlineProvider() {
return super.getOutlineProvider();
}
public static VolumeUiLayout get(View v) {
if (v instanceof VolumeUiLayout) return (VolumeUiLayout) v;
if (v.getParent() instanceof View) {
return get((View) v.getParent());
}
return null;
}
}

View File

@@ -5094,11 +5094,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.set(displayFrames.mOverscan);
} else if (canHideNavigationBar()
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) {
&& (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
|| type == TYPE_VOLUME_OVERLAY)) {
// Asking for layout as if the nav bar is hidden, lets the application
// extend into the unrestricted overscan screen area. We only do this for
// application windows to ensure no window that can be above the nav bar can
// do this.
// application windows and certain system windows to ensure no window that
// can be above the nav bar can do this.
df.set(displayFrames.mOverscan);
pf.set(displayFrames.mOverscan);
// We need to tell the app about where the frame inside the overscan is, so
@@ -5158,15 +5159,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
} else if (type == TYPE_VOLUME_OVERLAY) {
// Volume overlay covers everything, including the status and navbar
cf.set(displayFrames.mUnrestricted);
of.set(displayFrames.mUnrestricted);
df.set(displayFrames.mUnrestricted);
pf.set(displayFrames.mUnrestricted);
if (DEBUG_LAYOUT) Slog.v(TAG, String.format(
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
} else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
// The navigation bar has Real Ultimate Power.
of.set(displayFrames.mUnrestricted);
@@ -5250,8 +5242,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
"): normal window");
// Otherwise, a normal window must be placed inside the content
// of all screen decorations.
if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_VOLUME_OVERLAY) {
// Status bar panels and the volume dialog are the only windows who can go on
if (type == TYPE_STATUS_BAR_PANEL) {
// Status bar panels can go on
// top of the status bar. They are protected by the STATUS_BAR_SERVICE
// permission, so they have the same privileges as the status bar itself.
cf.set(displayFrames.mRestricted);