summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java34
-rw-r--r--core/java/android/view/InsetsController.java4
-rw-r--r--core/java/android/view/InsetsFlags.java60
-rw-r--r--core/java/android/view/InsetsState.java30
-rw-r--r--core/java/android/view/WindowInsetsController.java20
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl37
-rw-r--r--core/java/com/android/internal/statusbar/RegisterStatusBarResult.java25
-rw-r--r--core/java/com/android/internal/view/AppearanceRegion.aidl19
-rw-r--r--core/java/com/android/internal/view/AppearanceRegion.java142
-rw-r--r--core/tests/coretests/src/android/view/InsetsFlagsTest.java71
-rw-r--r--core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java8
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java172
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java165
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java162
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java203
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java122
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java143
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java15
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java67
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java135
-rw-r--r--services/core/java/com/android/server/wm/InsetsControlTarget.java7
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java170
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java29
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java23
-rw-r--r--services/core/java/com/android/server/wm/Session.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java48
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java88
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java7
-rw-r--r--tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java1
43 files changed, 1640 insertions, 654 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 35cfe9e591cf..7f717a72b0f9 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -306,6 +306,11 @@ interface IWindowManager
oneway void statusBarVisibilityChanged(int displayId, int visibility);
/**
+ * Called by System UI to notify Window Manager to hide transient bars.
+ */
+ oneway void hideTransientBars(int displayId);
+
+ /**
* When set to {@code true} the system bars will always be shown. This is true even if an app
* requests to be fullscreen by setting the system ui visibility flags. The
* functionality was added for the automotive case as a way to guarantee required content stays
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index e4deffadc966..0fb1c33df2ab 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -146,20 +146,11 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
}
final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
ArrayList<SurfaceParams> params = new ArrayList<>();
- if (offset.left != 0) {
- updateLeashesForSide(INSET_SIDE_LEFT, offset.left, mPendingInsets.left, params, state);
- }
- if (offset.top != 0) {
- updateLeashesForSide(INSET_SIDE_TOP, offset.top, mPendingInsets.top, params, state);
- }
- if (offset.right != 0) {
- updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, mPendingInsets.right, params,
- state);
- }
- if (offset.bottom != 0) {
- updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params,
- state);
- }
+ updateLeashesForSide(INSET_SIDE_LEFT, offset.left, mPendingInsets.left, params, state);
+ updateLeashesForSide(INSET_SIDE_TOP, offset.top, mPendingInsets.top, params, state);
+ updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, mPendingInsets.right, params, state);
+ updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params,
+ state);
SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get();
applier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
mCurrentInsets = mPendingInsets;
@@ -224,6 +215,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private void updateLeashesForSide(@InsetSide int side, int offset, int inset,
ArrayList<SurfaceParams> surfaceParams, InsetsState state) {
ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side);
+ if (items == null) {
+ return;
+ }
// TODO: Implement behavior when inset spans over multiple types
for (int i = items.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer consumer = items.valueAt(i);
@@ -274,9 +268,15 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
SparseSetArray<InsetsSourceConsumer> sideSourcesMap,
SparseArray<InsetsSourceConsumer> consumers) {
for (int i = typeSideMap.size() - 1; i >= 0; i--) {
- int type = typeSideMap.keyAt(i);
- int side = typeSideMap.valueAt(i);
- sideSourcesMap.add(side, consumers.get(type));
+ final int type = typeSideMap.keyAt(i);
+ final int side = typeSideMap.valueAt(i);
+ final InsetsSourceConsumer consumer = consumers.get(type);
+ if (consumer == null) {
+ // If the types that we are controlling are less than the types that the system has,
+ // there can be some null consumers.
+ continue;
+ }
+ sideSourcesMap.add(side, consumer);
}
}
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5bb4f63d62c8..eca6dcb1daac 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -67,9 +67,9 @@ public class InsetsController implements WindowInsetsController {
* Translation animation evaluator.
*/
private static TypeEvaluator<Insets> sEvaluator = (fraction, startValue, endValue) -> Insets.of(
- 0,
+ (int) (startValue.left + fraction * (endValue.left - startValue.left)),
(int) (startValue.top + fraction * (endValue.top - startValue.top)),
- 0,
+ (int) (startValue.right + fraction * (endValue.right - startValue.right)),
(int) (startValue.bottom + fraction * (endValue.bottom - startValue.bottom)));
/**
diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java
index 276e80a772f3..6e459b22e657 100644
--- a/core/java/android/view/InsetsFlags.java
+++ b/core/java/android/view/InsetsFlags.java
@@ -16,10 +16,18 @@
package android.view;
+import static android.view.View.NAVIGATION_BAR_TRANSLUCENT;
+import static android.view.View.NAVIGATION_BAR_TRANSPARENT;
+import static android.view.View.STATUS_BAR_TRANSLUCENT;
+import static android.view.View.STATUS_BAR_TRANSPARENT;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
-import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
@@ -35,9 +43,13 @@ public class InsetsFlags {
@ViewDebug.ExportedProperty(flagMapping = {
@ViewDebug.FlagToString(
- mask = APPEARANCE_OPAQUE_BARS,
- equals = APPEARANCE_OPAQUE_BARS,
- name = "OPAQUE_BARS"),
+ mask = APPEARANCE_OPAQUE_TOP_BAR,
+ equals = APPEARANCE_OPAQUE_TOP_BAR,
+ name = "OPAQUE_TOP_BAR"),
+ @ViewDebug.FlagToString(
+ mask = APPEARANCE_OPAQUE_SIDE_BARS,
+ equals = APPEARANCE_OPAQUE_SIDE_BARS,
+ name = "OPAQUE_SIDE_BARS"),
@ViewDebug.FlagToString(
mask = APPEARANCE_LOW_PROFILE_BARS,
equals = APPEARANCE_LOW_PROFILE_BARS,
@@ -64,4 +76,44 @@ public class InsetsFlags {
name = "SHOW_TRANSIENT_BARS_BY_SWIPE")
})
public @Behavior int behavior;
+
+ /**
+ * Converts system UI visibility to appearance.
+ *
+ * @param systemUiVisibility the system UI visibility to be converted.
+ * @return the outcome {@link Appearance}
+ */
+ public static @Appearance int getAppearance(int systemUiVisibility) {
+ int appearance = 0;
+ appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE,
+ APPEARANCE_LOW_PROFILE_BARS);
+ appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ APPEARANCE_LIGHT_TOP_BAR);
+ appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ APPEARANCE_LIGHT_SIDE_BARS);
+ appearance |= convertNoFlag(systemUiVisibility,
+ STATUS_BAR_TRANSLUCENT | STATUS_BAR_TRANSPARENT, APPEARANCE_OPAQUE_TOP_BAR);
+ appearance |= convertNoFlag(systemUiVisibility,
+ NAVIGATION_BAR_TRANSLUCENT | NAVIGATION_BAR_TRANSPARENT,
+ APPEARANCE_OPAQUE_SIDE_BARS);
+ return appearance;
+ }
+
+ /**
+ * Converts the system UI visibility into an appearance flag if the given visibility contains
+ * the given system UI flag.
+ */
+ private static @Appearance int convertFlag(int systemUiVisibility, int systemUiFlag,
+ @Appearance int appearance) {
+ return (systemUiVisibility & systemUiFlag) != 0 ? appearance : 0;
+ }
+
+ /**
+ * Converts the system UI visibility into an appearance flag if the given visibility doesn't
+ * contains the given system UI flag.
+ */
+ private static @Appearance int convertNoFlag(int systemUiVisibility, int systemUiFlag,
+ @Appearance int appearance) {
+ return (systemUiVisibility & systemUiFlag) == 0 ? appearance : 0;
+ }
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index a04c39b63c85..99502a6c1d72 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -270,10 +270,23 @@ public class InsetsState implements Parcelable {
*
* @param type The {@link InternalInsetType} of the source to remove
*/
- public void removeSource(int type) {
+ public void removeSource(@InternalInsetType int type) {
mSources.remove(type);
}
+ /**
+ * A shortcut for setting the visibility of the source.
+ *
+ * @param type The {@link InternalInsetType} of the source to set the visibility
+ * @param visible {@code true} for visible
+ */
+ public void setSourceVisible(@InternalInsetType int type, boolean visible) {
+ InsetsSource source = mSources.get(type);
+ if (source != null) {
+ source.setVisible(visible);
+ }
+ }
+
public void set(InsetsState other) {
set(other, false /* copySources */);
}
@@ -357,6 +370,19 @@ public class InsetsState implements Parcelable {
}
}
+ public static boolean containsType(@InternalInsetType int[] types,
+ @InternalInsetType int type) {
+ if (types == null) {
+ return false;
+ }
+ for (int t : types) {
+ if (t == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "InsetsState");
for (int i = mSources.size() - 1; i >= 0; i--) {
@@ -364,7 +390,7 @@ public class InsetsState implements Parcelable {
}
}
- public static String typeToString(int type) {
+ public static String typeToString(@InternalInsetType int type) {
switch (type) {
case TYPE_TOP_BAR:
return "TYPE_TOP_BAR";
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 396422ef5c57..b41531988518 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -35,33 +35,39 @@ import java.lang.annotation.RetentionPolicy;
public interface WindowInsetsController {
/**
- * Makes system bars become opaque with solid dark background and light foreground.
+ * Makes the top bars become opaque with solid dark background and light foreground.
* @hide
*/
- int APPEARANCE_OPAQUE_BARS = 1;
+ int APPEARANCE_OPAQUE_TOP_BAR = 1;
+
+ /**
+ * Makes the side bars become opaque with solid dark background and light foreground.
+ * @hide
+ */
+ int APPEARANCE_OPAQUE_SIDE_BARS = 1 << 1;
/**
* Makes items on system bars become less noticeable without changing the layout of the bars.
* @hide
*/
- int APPEARANCE_LOW_PROFILE_BARS = 1 << 1;
+ int APPEARANCE_LOW_PROFILE_BARS = 1 << 2;
/**
* Changes the foreground color for the light top bar so that the items on the bar can be read
* clearly.
*/
- int APPEARANCE_LIGHT_TOP_BAR = 1 << 2;
+ int APPEARANCE_LIGHT_TOP_BAR = 1 << 3;
/**
* Changes the foreground color for the light side bars so that the items on the bar can be read
* clearly.
*/
- int APPEARANCE_LIGHT_SIDE_BARS = 1 << 3;
+ int APPEARANCE_LIGHT_SIDE_BARS = 1 << 4;
/** Determines the appearance of system bars. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {APPEARANCE_OPAQUE_BARS, APPEARANCE_LOW_PROFILE_BARS,
- APPEARANCE_LIGHT_TOP_BAR, APPEARANCE_LIGHT_SIDE_BARS})
+ @IntDef(flag = true, value = {APPEARANCE_OPAQUE_TOP_BAR, APPEARANCE_OPAQUE_SIDE_BARS,
+ APPEARANCE_LOW_PROFILE_BARS, APPEARANCE_LIGHT_TOP_BAR, APPEARANCE_LIGHT_SIDE_BARS})
@interface Appearance {
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c8ba52a63151..d9e2ba3e0975 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -23,6 +23,7 @@ import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
/** @hide */
oneway interface IStatusBar
@@ -56,7 +57,7 @@ oneway interface IStatusBar
int mask, in Rect fullscreenBounds, in Rect dockedBounds,
boolean navbarColorManagedByIme);
- void topAppWindowChanged(int displayId, boolean menuVisible);
+ void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher, boolean isMultiClientImeEnabled);
void setWindowState(int display, int window, int state);
@@ -172,4 +173,38 @@ oneway interface IStatusBar
* Notifies System UI whether the recents animation is running or not.
*/
void onRecentsAnimationStateChanged(boolean running);
+
+ /**
+ * Notifies System UI side of system bar appearance change on the specified display.
+ *
+ * @param displayId the ID of the display to notify
+ * @param appearance the appearance of the focused window. The light top bar appearance is not
+ * controlled here, but primaryAppearance and secondaryAppearance.
+ * @param appearanceRegions a set of appearances which will be only applied in their own bounds.
+ * This is for system bars which across multiple stack, e.g., status
+ * bar, that the bar can have partial appearances in corresponding
+ * stacks.
+ * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
+ */
+ void onSystemBarAppearanceChanged(int displayId, int appearance,
+ in AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme);
+
+ /**
+ * Notifies System UI to show transient bars. The transient bars are system bars, e.g., status
+ * bar and navigation bar which are temporarily visible to the user.
+ *
+ * @param displayId the ID of the display to notify.
+ * @param types the internal insets types of the bars are about to show transiently.
+ */
+ void showTransient(int displayId, in int[] types);
+
+ /**
+ * Notifies System UI to abort the transient state of system bars, which prevents the bars being
+ * hidden automatically. This is usually called when the app wants to show the permanent system
+ * bars again.
+ *
+ * @param displayId the ID of the display to notify.
+ * @param types the internal insets types of the bars are about to abort the transient state.
+ */
+ void abortTransient(int displayId, in int[] types);
}
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 6b0f8b2f5dc9..4c3f04b10892 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -29,7 +29,6 @@ public final class RegisterStatusBarResult implements Parcelable {
public final ArrayMap<String, StatusBarIcon> mIcons;
public final int mDisabledFlags1; // switch[0]
public final int mSystemUiVisibility; // switch[1]
- public final boolean mMenuVisible; // switch[2]
public final int mImeWindowVis; // switch[3]
public final int mImeBackDisposition; // switch[4]
public final boolean mShowImeSwitcher; // switch[5]
@@ -40,16 +39,18 @@ public final class RegisterStatusBarResult implements Parcelable {
public final Rect mFullscreenStackBounds;
public final Rect mDockedStackBounds;
public final boolean mNavbarColorManagedByIme;
+ public final boolean mAppFullscreen;
+ public final boolean mAppImmersive;
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
- int systemUiVisibility, boolean menuVisible, int imeWindowVis, int imeBackDisposition,
+ int systemUiVisibility, int imeWindowVis, int imeBackDisposition,
boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility,
int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds,
- Rect dockedStackBounds, boolean navbarColorManagedByIme) {
+ Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen,
+ boolean appImmersive) {
mIcons = new ArrayMap<>(icons);
mDisabledFlags1 = disabledFlags1;
mSystemUiVisibility = systemUiVisibility;
- mMenuVisible = menuVisible;
mImeWindowVis = imeWindowVis;
mImeBackDisposition = imeBackDisposition;
mShowImeSwitcher = showImeSwitcher;
@@ -60,6 +61,8 @@ public final class RegisterStatusBarResult implements Parcelable {
mFullscreenStackBounds = fullscreenStackBounds;
mDockedStackBounds = dockedStackBounds;
mNavbarColorManagedByIme = navbarColorManagedByIme;
+ mAppFullscreen = appFullscreen;
+ mAppImmersive = appImmersive;
}
@Override
@@ -72,7 +75,6 @@ public final class RegisterStatusBarResult implements Parcelable {
dest.writeTypedArrayMap(mIcons, flags);
dest.writeInt(mDisabledFlags1);
dest.writeInt(mSystemUiVisibility);
- dest.writeBoolean(mMenuVisible);
dest.writeInt(mImeWindowVis);
dest.writeInt(mImeBackDisposition);
dest.writeBoolean(mShowImeSwitcher);
@@ -83,6 +85,8 @@ public final class RegisterStatusBarResult implements Parcelable {
dest.writeTypedObject(mFullscreenStackBounds, flags);
dest.writeTypedObject(mDockedStackBounds, flags);
dest.writeBoolean(mNavbarColorManagedByIme);
+ dest.writeBoolean(mAppFullscreen);
+ dest.writeBoolean(mAppImmersive);
}
/**
@@ -96,7 +100,6 @@ public final class RegisterStatusBarResult implements Parcelable {
source.createTypedArrayMap(StatusBarIcon.CREATOR);
final int disabledFlags1 = source.readInt();
final int systemUiVisibility = source.readInt();
- final boolean menuVisible = source.readBoolean();
final int imeWindowVis = source.readInt();
final int imeBackDisposition = source.readInt();
final boolean showImeSwitcher = source.readBoolean();
@@ -107,11 +110,13 @@ public final class RegisterStatusBarResult implements Parcelable {
final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR);
final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR);
final boolean navbarColorManagedByIme = source.readBoolean();
+ final boolean appFullscreen = source.readBoolean();
+ final boolean appImmersive = source.readBoolean();
return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility,
- menuVisible, imeWindowVis, imeBackDisposition, showImeSwitcher,
- disabledFlags2, fullscreenStackSysUiVisibility,
- dockedStackSysUiVisibility, imeToken, fullscreenStackBounds,
- dockedStackBounds, navbarColorManagedByIme);
+ imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2,
+ fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken,
+ fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme,
+ appFullscreen, appImmersive);
}
@Override
diff --git a/core/java/com/android/internal/view/AppearanceRegion.aidl b/core/java/com/android/internal/view/AppearanceRegion.aidl
new file mode 100644
index 000000000000..1638bf5bbfd6
--- /dev/null
+++ b/core/java/com/android/internal/view/AppearanceRegion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.view;
+
+parcelable AppearanceRegion;
diff --git a/core/java/com/android/internal/view/AppearanceRegion.java b/core/java/com/android/internal/view/AppearanceRegion.java
new file mode 100644
index 000000000000..1a0cb4b0dfbf
--- /dev/null
+++ b/core/java/com/android/internal/view/AppearanceRegion.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.view;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.Parcelable;
+import android.view.InsetsFlags;
+import android.view.ViewDebug;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Specifies which region applies which appearance.
+ */
+@DataClass
+public class AppearanceRegion implements Parcelable {
+
+ private int mAppearance;
+ private @NonNull Rect mBounds;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final AppearanceRegion sa = (AppearanceRegion) o;
+ return mAppearance == sa.mAppearance && mBounds.equals(sa.mBounds);
+ }
+
+ @Override
+ public String toString() {
+ final String appearanceString =
+ ViewDebug.flagsToString(InsetsFlags.class, "appearance", mAppearance);
+ return "AppearanceRegion{" + appearanceString + " bounds=" + mBounds.toShortString() + "}";
+ }
+
+
+
+ // Code below generated by codegen v1.0.7.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/view/AppearanceRegion.java
+
+
+ @DataClass.Generated.Member
+ public AppearanceRegion(
+ int appearance,
+ @NonNull Rect bounds) {
+ this.mAppearance = appearance;
+ this.mBounds = bounds;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBounds);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public int getAppearance() {
+ return mAppearance;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Rect getBounds() {
+ return mBounds;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(mAppearance);
+ dest.writeTypedObject(mBounds, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected AppearanceRegion(android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int appearance = in.readInt();
+ Rect bounds = (Rect) in.readTypedObject(Rect.CREATOR);
+
+ this.mAppearance = appearance;
+ this.mBounds = bounds;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBounds);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<AppearanceRegion> CREATOR
+ = new Parcelable.Creator<AppearanceRegion>() {
+ @Override
+ public AppearanceRegion[] newArray(int size) {
+ return new AppearanceRegion[size];
+ }
+
+ @Override
+ public AppearanceRegion createFromParcel(android.os.Parcel in) {
+ return new AppearanceRegion(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1570909617357L,
+ codegenVersion = "1.0.7",
+ sourceFile = "frameworks/base/core/java/com/android/internal/view/AppearanceRegion.java",
+ inputSignatures = "private int mAppearance\nprivate @android.annotation.NonNull android.graphics.Rect mBounds\npublic @java.lang.Override boolean equals(java.lang.Object)\npublic @java.lang.Override java.lang.String toString()\nclass AppearanceRegion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+ @Deprecated
+ private void __metadata() {}
+
+}
diff --git a/core/tests/coretests/src/android/view/InsetsFlagsTest.java b/core/tests/coretests/src/android/view/InsetsFlagsTest.java
new file mode 100644
index 000000000000..7d4445ba456a
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsFlagsTest.java
@@ -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.
+ */
+
+package android.view;
+
+
+import static android.view.InsetsFlags.getAppearance;
+import static android.view.View.NAVIGATION_BAR_TRANSLUCENT;
+import static android.view.View.NAVIGATION_BAR_TRANSPARENT;
+import static android.view.View.STATUS_BAR_TRANSLUCENT;
+import static android.view.View.STATUS_BAR_TRANSPARENT;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsetsController.Appearance;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link InsetsFlags}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:InsetsFlagsTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class InsetsFlagsTest {
+
+ @Test
+ public void testGetAppearance() {
+ assertContainsAppearance(APPEARANCE_LOW_PROFILE_BARS, SYSTEM_UI_FLAG_LOW_PROFILE);
+ assertContainsAppearance(APPEARANCE_LIGHT_TOP_BAR, SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ assertContainsAppearance(APPEARANCE_LIGHT_SIDE_BARS, SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ assertContainsAppearance(APPEARANCE_OPAQUE_TOP_BAR,
+ 0xffffffff & ~(STATUS_BAR_TRANSLUCENT | STATUS_BAR_TRANSPARENT));
+ assertContainsAppearance(APPEARANCE_OPAQUE_SIDE_BARS,
+ 0xffffffff & ~(NAVIGATION_BAR_TRANSLUCENT | NAVIGATION_BAR_TRANSPARENT));
+ }
+
+ void assertContainsAppearance(@Appearance int appearance, int systemUiVisibility) {
+ assertTrue((getAppearance(systemUiVisibility) & appearance) == appearance);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index b93c3a7a17e2..0be5009f85f0 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -48,7 +48,6 @@ public class RegisterStatusBarResultTest {
final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap,
0x2 /* disabledFlags1 */,
0x4 /* systemUiVisibility */,
- true /* menuVisible */,
0x8 /* imeWindowVis */,
0x10 /* imeBackDisposition */,
false /* showImeSwitcher */,
@@ -58,7 +57,9 @@ public class RegisterStatusBarResultTest {
new Binder() /* imeToken */,
new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */,
new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */,
- true /* navbarColorManagedByIme */);
+ true /* navbarColorManagedByIme */,
+ true /* appFullscreen */,
+ true /* appImmersive */);
final RegisterStatusBarResult copy = clone(original);
@@ -69,7 +70,6 @@ public class RegisterStatusBarResultTest {
assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1);
assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility);
- assertThat(copy.mMenuVisible).isEqualTo(original.mMenuVisible);
assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis);
assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
@@ -82,6 +82,8 @@ public class RegisterStatusBarResultTest {
assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds);
assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds);
assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
+ assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen);
+ assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive);
}
private RegisterStatusBarResult clone(RegisterStatusBarResult original) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
index fe547a0a16fa..b21a9f7c4d05 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -95,9 +95,12 @@ public interface StatusBarStateController {
default void onDozeAmountChanged(float linear, float eased) {}
/**
- * Callback to be notified when the sysui visibility changes
+ * Callback to be notified when the fullscreen or immersive state changes.
+ *
+ * @param isFullscreen if any of the system bar is hidden by the focused window.
+ * @param isImmersive if the navigation bar can stay hidden when the display gets tapped.
*/
- default void onSystemUiVisibilityChanged(int visibility) {}
+ default void onFullscreenStateChanged(boolean isFullscreen, boolean isImmersive) {}
/**
* Callback to be notified when the pulsing state changes
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index d6a8f906197d..c9dc08e78afb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,6 +22,8 @@ import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEF
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -43,12 +45,17 @@ import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
+import android.view.InsetsFlags;
+import android.view.InsetsState.InternalInsetType;
+import android.view.View;
+import android.view.WindowInsetsController.Appearance;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -76,7 +83,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
private static final int MSG_EXPAND_NOTIFICATIONS = 3 << MSG_SHIFT;
private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
- private static final int MSG_SET_SYSTEMUI_VISIBILITY = 6 << MSG_SHIFT;
+ private static final int MSG_SYSTEM_BAR_APPEARANCE_CHANGED = 6 << MSG_SHIFT;
private static final int MSG_DISPLAY_READY = 7 << MSG_SHIFT;
private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
private static final int MSG_TOGGLE_RECENT_APPS = 9 << MSG_SHIFT;
@@ -115,6 +122,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
+ private static final int MSG_SHOW_TRANSIENT = 48 << MSG_SHIFT;
+ private static final int MSG_ABORT_TRANSIENT = 49 << MSG_SHIFT;
+ private static final int MSG_TOP_APP_WINDOW_CHANGED = 50 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -160,28 +170,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
default void animateExpandSettingsPanel(String obj) { }
/**
- * Called to notify visibility flag changes.
- * @see IStatusBar#setSystemUiVisibility(int, int, int, int, int, Rect, Rect).
- *
- * @param displayId The id of the display to notify.
- * @param vis The visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will
- * be reported separately in fullscreenStackVis and dockedStackVis.
- * @param fullscreenStackVis The flags which only apply in the region of the fullscreen
- * stack, which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
- * @param dockedStackVis The flags that only apply in the region of the docked stack, which
- * is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
- * @param mask Which flags to change.
- * @param fullscreenStackBounds The current bounds of the fullscreen stack, in screen
- * coordinates.
- * @param dockedStackBounds The current bounds of the docked stack, in screen coordinates.
- * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
- */
- default void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- }
-
- /**
* Called to notify IME window status changes.
*
* @param displayId The id of the display to notify.
@@ -292,6 +280,28 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
* @see IStatusBar#onRecentsAnimationStateChanged(boolean)
*/
default void onRecentsAnimationStateChanged(boolean running) { }
+
+ /**
+ * @see IStatusBar#onSystemBarAppearanceChanged(int, int, AppearanceRegion[], boolean).
+ */
+ default void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { }
+
+ /**
+ * @see IStatusBar#showTransient(int, int[]).
+ */
+ default void showTransient(int displayId, @InternalInsetType int[] types) { }
+
+ /**
+ * @see IStatusBar#abortTransient(int, int[]).
+ */
+ default void abortTransient(int displayId, @InternalInsetType int[] types) { }
+
+ /**
+ * @see IStatusBar#topAppWindowChanged(int, boolean, boolean).
+ */
+ default void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ }
}
@VisibleForTesting
@@ -456,28 +466,53 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
+ // TODO(b/118118435): Remove this function after migration
@Override
public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
boolean navbarColorManagedByIme) {
synchronized (mLock) {
- // Don't coalesce these, since it might have one time flags set such as
- // STATUS_BAR_UNHIDE which might get lost.
+ final boolean hasDockedStack = !dockedStackBounds.isEmpty();
+ final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
+ final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
+ if (transientStatus && transientNavigation) {
+ showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+ } else if (transientStatus) {
+ showTransient(displayId, new int[]{TYPE_TOP_BAR});
+ abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+ } else if (transientNavigation) {
+ showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+ abortTransient(displayId, new int[]{TYPE_TOP_BAR});
+ } else {
+ abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+ }
SomeArgs args = SomeArgs.obtain();
args.argi1 = displayId;
- args.argi2 = vis;
- args.argi3 = fullscreenStackVis;
- args.argi4 = dockedStackVis;
- args.argi5 = mask;
- args.argi6 = navbarColorManagedByIme ? 1 : 0;
- args.arg1 = fullscreenStackBounds;
- args.arg2 = dockedStackBounds;
- mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
+ args.argi2 = InsetsFlags.getAppearance(vis);
+ args.argi3 = navbarColorManagedByIme ? 1 : 0;
+ final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
+ final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
+ args.arg1 = hasDockedStack
+ ? new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
+ new AppearanceRegion(dockedAppearance, dockedStackBounds)}
+ : new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
+ mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
}
}
@Override
- public void topAppWindowChanged(int displayId, boolean menuVisible) { }
+ public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ synchronized (mLock) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = isFullscreen ? 1 : 0;
+ args.argi3 = isImmersive ? 1 : 0;
+ mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, args).sendToTarget();
+ }
+
+ }
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
@@ -827,6 +862,33 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ synchronized (mLock) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = appearance;
+ args.argi3 = navbarColorManagedByIme ? 1 : 0;
+ args.arg1 = appearanceRegions;
+ mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
+ }
+ }
+
+ @Override
+ public void showTransient(int displayId, int[] types) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, 0, types).sendToTarget();
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, int[] types) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -879,15 +941,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
}
break;
- case MSG_SET_SYSTEMUI_VISIBILITY:
- args = (SomeArgs) msg.obj;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
- args.argi4, args.argi5, (Rect) args.arg1, (Rect) args.arg2,
- args.argi6 == 1);
- }
- args.recycle();
- break;
case MSG_SHOW_IME_BUTTON:
args = (SomeArgs) msg.obj;
handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
@@ -1094,6 +1147,39 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mCallbacks.get(i).onRecentsAnimationStateChanged(msg.arg1 > 0);
}
break;
+ case MSG_SYSTEM_BAR_APPEARANCE_CHANGED:
+ args = (SomeArgs) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onSystemBarAppearanceChanged(args.argi1, args.argi2,
+ (AppearanceRegion[]) args.arg1, args.argi3 == 1);
+ }
+ args.recycle();
+ break;
+ case MSG_SHOW_TRANSIENT: {
+ final int displayId = msg.arg1;
+ final int[] types = (int[]) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showTransient(displayId, types);
+ }
+ break;
+ }
+ case MSG_ABORT_TRANSIENT: {
+ final int displayId = msg.arg1;
+ final int[] types = (int[]) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).abortTransient(displayId, types);
+ }
+ break;
+ }
+ case MSG_TOP_APP_WINDOW_CHANGED: {
+ args = (SomeArgs) msg.obj;
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).topAppWindowChanged(
+ args.argi1, args.argi2 != 0, args.argi3 != 0);
+ }
+ args.recycle();
+ break;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 5144a95a0a51..275475d6d72c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -156,7 +156,7 @@ public class NavigationBarController implements Callbacks {
Dependency.get(NotificationRemoteInputManager.class),
Dependency.get(IWindowManager.class));
navBar.setAutoHideController(autoHideController);
- navBar.restoreSystemUiVisibilityState();
+ navBar.restoreAppearanceAndTransientState();
mNavigationBars.append(displayId, navBar);
if (result != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 8b9268e1888a..e81e5cae5bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -21,7 +21,6 @@ import android.animation.ValueAnimator;
import android.text.format.DateFormat;
import android.util.FloatProperty;
import android.util.Log;
-import android.view.View;
import android.view.animation.Interpolator;
import com.android.internal.annotations.GuardedBy;
@@ -80,9 +79,14 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
private HistoricalState[] mHistoricalRecords = new HistoricalState[HISTORY_SIZE];
/**
- * Current SystemUiVisibility
+ * If any of the system bars is hidden.
*/
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+ private boolean mIsFullscreen = false;
+
+ /**
+ * If the navigation bar can stay hidden when the display gets tapped.
+ */
+ private boolean mIsImmersive = false;
/**
* If the device is currently pulsing (AOD2).
@@ -320,12 +324,13 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
}
@Override
- public void setSystemUiVisibility(int visibility) {
- if (mSystemUiVisibility != visibility) {
- mSystemUiVisibility = visibility;
+ public void setFullscreenState(boolean isFullscreen, boolean isImmersive) {
+ if (mIsFullscreen != isFullscreen || mIsImmersive != isImmersive) {
+ mIsFullscreen = isFullscreen;
+ mIsImmersive = isImmersive;
synchronized (mListeners) {
for (RankedListener rl : new ArrayList<>(mListeners)) {
- rl.mListener.onSystemUiVisibilityChanged(mSystemUiVisibility);
+ rl.mListener.onFullscreenStateChanged(isFullscreen, isImmersive);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
index 2ad979ab64e3..07b35502478f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -111,9 +111,9 @@ public interface SysuiStatusBarStateController extends StatusBarStateController
boolean isKeyguardRequested();
/**
- * Set systemui visibility
+ * Set the fullscreen state
*/
- void setSystemUiVisibility(int visibility);
+ void setFullscreenState(boolean isFullscreen, boolean isImmersive);
/**
* Set pulsing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index 175d072e4c8b..008464e543a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -17,52 +17,39 @@
package com.android.systemui.statusbar.phone;
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import android.content.Context;
-import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
-import android.view.View;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import javax.inject.Inject;
import javax.inject.Named;
/** A controller to control all auto-hide things. */
-public class AutoHideController implements CommandQueue.Callbacks {
+public class AutoHideController {
private static final String TAG = "AutoHideController";
private final IWindowManager mWindowManagerService;
private final Handler mHandler;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final CommandQueue mCommandQueue;
private StatusBar mStatusBar;
private NavigationBarFragment mNavigationBar;
- @VisibleForTesting
- int mDisplayId;
- @VisibleForTesting
- int mSystemUiVisibility;
- // last value sent to window manager
- private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+ private int mDisplayId;
private boolean mAutoHideSuspended;
- private static final long AUTOHIDE_TIMEOUT_MS = 2250;
+ private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
private final Runnable mAutoHide = () -> {
- int requested = mSystemUiVisibility & ~getTransientMask();
- if (mSystemUiVisibility != requested) {
- notifySystemUiVisibilityChanged(requested);
+ if (isAnyTransientBarShown()) {
+ hideTransientBars();
}
};
@@ -70,8 +57,6 @@ public class AutoHideController implements CommandQueue.Callbacks {
public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler,
NotificationRemoteInputManager notificationRemoteInputManager,
IWindowManager iWindowManager) {
- mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
- mCommandQueue.addCallback(this);
mHandler = handler;
mRemoteInputManager = notificationRemoteInputManager;
mWindowManagerService = iWindowManager;
@@ -79,13 +64,6 @@ public class AutoHideController implements CommandQueue.Callbacks {
mDisplayId = context.getDisplayId();
}
- @Override
- public void onDisplayRemoved(int displayId) {
- if (displayId == mDisplayId) {
- mCommandQueue.removeCallback(this);
- }
- }
-
void setStatusBar(StatusBar statusBar) {
mStatusBar = statusBar;
}
@@ -94,50 +72,18 @@ public class AutoHideController implements CommandQueue.Callbacks {
mNavigationBar = navigationBar;
}
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- if (displayId != mDisplayId) {
- return;
- }
- int oldVal = mSystemUiVisibility;
- int newVal = (oldVal & ~mask) | (vis & mask);
- int diff = newVal ^ oldVal;
-
- if (diff != 0) {
- mSystemUiVisibility = newVal;
-
- // ready to unhide
- if (hasStatusBar() && (vis & View.STATUS_BAR_UNHIDE) != 0) {
- mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
- }
-
- if (hasNavigationBar() && (vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
- mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
- }
-
- // Re-send setSystemUiVisibility to update un-hide status.
- if (mSystemUiVisibility != newVal) {
- mCommandQueue.setSystemUiVisibility(mDisplayId, mSystemUiVisibility,
- fullscreenStackVis, dockedStackVis, mask, fullscreenStackBounds,
- dockedStackBounds, navbarColorManagedByIme);
- }
-
- notifySystemUiVisibilityChanged(mSystemUiVisibility);
- }
- }
-
- @VisibleForTesting
- void notifySystemUiVisibilityChanged(int vis) {
+ private void hideTransientBars() {
try {
- if (mLastDispatchedSystemUiVisibility != vis) {
- mWindowManagerService.statusBarVisibilityChanged(mDisplayId, vis);
- mLastDispatchedSystemUiVisibility = vis;
- }
+ mWindowManagerService.hideTransientBars(mDisplayId);
} catch (RemoteException ex) {
Log.w(TAG, "Cannot get WindowManager");
}
+ if (mStatusBar != null) {
+ mStatusBar.clearTransient();
+ }
+ if (mNavigationBar != null) {
+ mNavigationBar.clearTransient();
+ }
}
void resumeSuspendedAutoHide() {
@@ -156,13 +102,12 @@ public class AutoHideController implements CommandQueue.Callbacks {
if (checkBarModesRunnable != null) {
mHandler.removeCallbacks(checkBarModesRunnable);
}
- mAutoHideSuspended = (mSystemUiVisibility & getTransientMask()) != 0;
+ mAutoHideSuspended = isAnyTransientBarShown();
}
void touchAutoHide() {
// update transient bar auto hide
- if ((hasStatusBar() && mStatusBar.getStatusBarMode() == MODE_SEMI_TRANSPARENT)
- || hasNavigationBar() && mNavigationBar.isSemiTransparent()) {
+ if (isAnyTransientBarShown()) {
scheduleAutoHide();
} else {
cancelAutoHide();
@@ -170,9 +115,9 @@ public class AutoHideController implements CommandQueue.Callbacks {
}
private Runnable getCheckBarModesRunnable() {
- if (hasStatusBar()) {
+ if (mStatusBar != null) {
return () -> mStatusBar.checkBarModes();
- } else if (hasNavigationBar()) {
+ } else if (mNavigationBar != null) {
return () -> mNavigationBar.checkNavBarModes();
} else {
return null;
@@ -186,15 +131,14 @@ public class AutoHideController implements CommandQueue.Callbacks {
private void scheduleAutoHide() {
cancelAutoHide();
- mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
+ mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
}
void checkUserAutoHide(MotionEvent event) {
- boolean shouldAutoHide =
- (mSystemUiVisibility & getTransientMask()) != 0 // a transient bar is revealed.
+ boolean shouldAutoHide = isAnyTransientBarShown()
&& event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
&& event.getX() == 0 && event.getY() == 0;
- if (hasStatusBar()) {
+ if (mStatusBar != null) {
// a touch outside both bars
shouldAutoHide &= !mRemoteInputManager.getController().isRemoteInputActive();
}
@@ -208,23 +152,8 @@ public class AutoHideController implements CommandQueue.Callbacks {
mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
}
- private int getTransientMask() {
- int mask = 0;
- if (hasStatusBar()) {
- mask |= View.STATUS_BAR_TRANSIENT;
- }
- if (hasNavigationBar()) {
- mask |= View.NAVIGATION_BAR_TRANSIENT;
- }
- return mask;
- }
-
- boolean hasNavigationBar() {
- return mNavigationBar != null;
- }
-
- @VisibleForTesting
- boolean hasStatusBar() {
- return mStatusBar != null;
+ private boolean isAnyTransientBarShown() {
+ return (mStatusBar != null && mStatusBar.isTransientShown())
+ || mNavigationBar != null && mNavigationBar.isTransientShown();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 211a40a91101..e6731e6b8a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -44,11 +44,11 @@ public class BarTransitions {
private static final boolean DEBUG = false;
private static final boolean DEBUG_COLORS = false;
- public static final int MODE_OPAQUE = 0;
+ public static final int MODE_TRANSPARENT = 0;
public static final int MODE_SEMI_TRANSPARENT = 1;
public static final int MODE_TRANSLUCENT = 2;
public static final int MODE_LIGHTS_OUT = 3;
- public static final int MODE_TRANSPARENT = 4;
+ public static final int MODE_OPAQUE = 4;
public static final int MODE_WARNING = 5;
public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
@@ -72,7 +72,7 @@ public class BarTransitions {
private final View mView;
protected final BarBackgroundDrawable mBarBackground;
- private int mMode;
+ private @TransitionMode int mMode;
private boolean mAlwaysOpaque = false;
public BarTransitions(View view, int gradientResourceId) {
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 442c08991581..c9c38a0ef5f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-import static android.view.View.NAVIGATION_BAR_TRANSIENT;
import android.content.Context;
import android.content.res.Resources;
@@ -133,7 +131,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
private boolean mIsAttached;
private boolean mIsGesturalModeEnabled;
private boolean mIsEnabled;
- private boolean mIsInTransientImmersiveStickyState;
+ private boolean mIsNavBarShownTransiently;
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
@@ -198,10 +196,8 @@ public class EdgeBackGestureHandler implements DisplayListener {
updateCurrentUserResources(currentUserContext.getResources());
}
- public void onSystemUiVisibilityChanged(int systemUiVisibility) {
- mIsInTransientImmersiveStickyState =
- (systemUiVisibility & SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
- && (systemUiVisibility & NAVIGATION_BAR_TRANSIENT) != 0;
+ public void onNavBarTransientStateChanged(boolean isTransient) {
+ mIsNavBarShownTransiently = isTransient;
}
private void disposeInputChannel() {
@@ -316,7 +312,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
}
// Always allow if the user is in a transient sticky immersive state
- if (mIsInTransientImmersiveStickyState) {
+ if (mIsNavBarShownTransiently) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index b0b656a1a951..2e776e39b54c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,15 +16,20 @@
package com.android.systemui.statusbar.phone;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.Rect;
-import android.view.View;
+import android.view.InsetsFlags;
+import android.view.ViewDebug;
+import android.view.WindowInsetsController.Appearance;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -49,13 +54,10 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private BiometricUnlockController mBiometricUnlockController;
private LightBarTransitionsController mNavigationBarController;
- private int mSystemUiVisibility;
- private int mFullscreenStackVisibility;
- private int mDockedStackVisibility;
- private boolean mFullscreenLight;
- private boolean mDockedLight;
- private int mLastStatusBarMode;
- private int mLastNavigationBarMode;
+ private @Appearance int mAppearance;
+ private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+ private int mStatusBarMode;
+ private int mNavigationBarMode;
private final Color mDarkModeColor;
/**
@@ -75,8 +77,6 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
*/
private boolean mForceDarkForScrim;
- private final Rect mLastFullscreenBounds = new Rect();
- private final Rect mLastDockedBounds = new Rect();
private boolean mQsCustomizing;
private boolean mDirectReplying;
@@ -101,45 +101,32 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mBiometricUnlockController = biometricUnlockController;
}
- public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+ void onStatusBarAppearanceChanged(AppearanceRegion[] appearanceRegions, boolean sbModeChanged,
int statusBarMode, boolean navbarColorManagedByIme) {
- int oldFullscreen = mFullscreenStackVisibility;
- int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
- int diffFullscreen = newFullscreen ^ oldFullscreen;
- int oldDocked = mDockedStackVisibility;
- int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
- int diffDocked = newDocked ^ oldDocked;
- if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || sbModeChanged
- || !mLastFullscreenBounds.equals(fullscreenStackBounds)
- || !mLastDockedBounds.equals(dockedStackBounds)) {
-
- mFullscreenLight = isLight(newFullscreen, statusBarMode,
- View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
- mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
- updateStatus(fullscreenStackBounds, dockedStackBounds);
+ final int numStacks = appearanceRegions.length;
+ boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
+ for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
+ stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
+ }
+ if (stackAppearancesChanged || sbModeChanged) {
+ mAppearanceRegions = appearanceRegions;
+ onStatusBarModeChanged(statusBarMode);
}
-
- mFullscreenStackVisibility = newFullscreen;
- mDockedStackVisibility = newDocked;
- mLastStatusBarMode = statusBarMode;
mNavbarColorManagedByIme = navbarColorManagedByIme;
- mLastFullscreenBounds.set(fullscreenStackBounds);
- mLastDockedBounds.set(dockedStackBounds);
}
- public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
+ void onStatusBarModeChanged(int newBarMode) {
+ mStatusBarMode = newBarMode;
+ updateStatus();
+ }
+
+ void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
int navigationBarMode, boolean navbarColorManagedByIme) {
- int oldVis = mSystemUiVisibility;
- int newVis = (oldVis & ~mask) | (vis & mask);
- int diffVis = newVis ^ oldVis;
- if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
- || nbModeChanged) {
- boolean last = mNavigationLight;
- mHasLightNavigationBar = isLight(vis, navigationBarMode,
- View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ int diff = appearance ^ mAppearance;
+ if ((diff & APPEARANCE_LIGHT_SIDE_BARS) != 0 || nbModeChanged) {
+ final boolean last = mNavigationLight;
+ mHasLightNavigationBar = isLight(appearance, navigationBarMode,
+ APPEARANCE_LIGHT_SIDE_BARS);
mNavigationLight = mHasLightNavigationBar
&& (mDirectReplying && mNavbarColorManagedByIme || !mForceDarkForScrim)
&& !mQsCustomizing;
@@ -147,17 +134,20 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
updateNavigation();
}
}
- mSystemUiVisibility = newVis;
- mLastNavigationBarMode = navigationBarMode;
+ mAppearance = appearance;
+ mNavigationBarMode = navigationBarMode;
mNavbarColorManagedByIme = navbarColorManagedByIme;
}
+ void onNavigationBarModeChanged(int newBarMode) {
+ mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_SIDE_BARS);
+ }
+
private void reevaluate() {
- onSystemUiVisibilityChanged(mFullscreenStackVisibility,
- mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
- true /* sbModeChange*/, mLastStatusBarMode, mNavbarColorManagedByIme);
- onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
- mLastNavigationBarMode, mNavbarColorManagedByIme);
+ onStatusBarAppearanceChanged(mAppearanceRegions, true /* sbModeChange */, mStatusBarMode,
+ mNavbarColorManagedByIme);
+ onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+ mNavigationBarMode, mNavbarColorManagedByIme);
}
public void setQsCustomizing(boolean customizing) {
@@ -191,10 +181,10 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
}
}
- private boolean isLight(int vis, int barMode, int flag) {
- boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+ private static boolean isLight(int appearance, int barMode, int flag) {
+ final boolean isTransparentBar = (barMode == MODE_TRANSPARENT
|| barMode == MODE_LIGHTS_OUT_TRANSPARENT);
- boolean light = (vis & flag) != 0;
+ final boolean light = (appearance & flag) != 0;
return isTransparentBar && light;
}
@@ -207,49 +197,49 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
&& unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
}
- private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
- boolean hasDockedStack = !dockedStackBounds.isEmpty();
+ private void updateStatus() {
+ final int numStacks = mAppearanceRegions.length;
+ int numLightStacks = 0;
+
+ // We can only have maximum one light stack.
+ int indexLightStack = -1;
- // If both are light or fullscreen is light and there is no docked stack, all icons get
- // dark.
- if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+ for (int i = 0; i < numStacks; i++) {
+ if (isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+ APPEARANCE_LIGHT_TOP_BAR)) {
+ numLightStacks++;
+ indexLightStack = i;
+ }
+ }
+
+ // If all stacks are light, all icons get dark.
+ if (numLightStacks == numStacks) {
mStatusBarIconController.setIconsDarkArea(null);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
- // If no one is light or the fullscreen is not light and there is no docked stack,
- // all icons become white.
- else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+ // If no one is light, all icons become white.
+ else if (numLightStacks == 0) {
mStatusBarIconController.getTransitionsController().setIconsDark(
false, animateChange());
}
// Not the same for every stack, magic!
else {
- Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
- if (bounds.isEmpty()) {
- mStatusBarIconController.setIconsDarkArea(null);
- } else {
- mStatusBarIconController.setIconsDarkArea(bounds);
- }
+ mStatusBarIconController.setIconsDarkArea(
+ mAppearanceRegions[indexLightStack].getBounds());
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
}
private void updateNavigation() {
if (mNavigationBarController != null) {
- mNavigationBarController.setIconsDark(
- mNavigationLight, animateChange());
+ mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
}
}
@Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
- }
-
- @Override
public void onPowerSaveChanged(boolean isPowerSave) {
reevaluate();
}
@@ -257,24 +247,21 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("LightBarController: ");
- pw.print(" mSystemUiVisibility=0x"); pw.print(
- Integer.toHexString(mSystemUiVisibility));
- pw.print(" mFullscreenStackVisibility=0x"); pw.print(
- Integer.toHexString(mFullscreenStackVisibility));
- pw.print(" mDockedStackVisibility=0x"); pw.println(
- Integer.toHexString(mDockedStackVisibility));
-
- pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
- pw.print(" mDockedLight="); pw.println(mDockedLight);
-
- pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
- pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
+ pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+ InsetsFlags.class, "appearance", mAppearance));
+ final int numStacks = mAppearanceRegions.length;
+ for (int i = 0; i < numStacks; i++) {
+ final boolean isLight = isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+ APPEARANCE_LIGHT_TOP_BAR);
+ pw.print(" stack #"); pw.print(i); pw.print(": ");
+ pw.print(mAppearanceRegions[i].toString()); pw.print(" isLight="); pw.println(isLight);
+ }
pw.print(" mNavigationLight="); pw.print(mNavigationLight);
pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
- pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
- pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
+ pw.print(" mStatusBarMode="); pw.print(mStatusBarMode);
+ pw.print(" mNavigationBarMode="); pw.println(mNavigationBarMode);
pw.print(" mForceDarkForScrim="); pw.print(mForceDarkForScrim);
pw.print(" mQsCustomizing="); pw.print(mQsCustomizing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 38dc5ea4dcd5..7030dfc4c33b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -21,6 +21,10 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -31,7 +35,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OU
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
@@ -52,7 +55,6 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
@@ -67,12 +69,14 @@ import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
+import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
@@ -84,6 +88,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
@@ -128,7 +133,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private static final boolean DEBUG = false;
private static final String EXTRA_DISABLE_STATE = "disabled_state";
private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
- private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
+ private static final String EXTRA_APPEARANCE = "appearance";
+ private static final String EXTRA_TRANSIENT_STATE = "transient_state";
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -165,7 +171,10 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private Locale mLocale;
private int mLayoutDirection;
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ private @Appearance int mAppearance;
+
+ private boolean mTransientShown;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private LightBarController mLightBarController;
private AutoHideController mAutoHideController;
@@ -295,7 +304,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
- mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
+ mAppearance = savedInstanceState.getInt(EXTRA_APPEARANCE, 0);
+ mTransientShown = savedInstanceState.getBoolean(EXTRA_TRANSIENT_STATE, false);
}
mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
@@ -397,7 +407,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
- outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
+ outState.putInt(EXTRA_APPEARANCE, mAppearance);
+ outState.putBoolean(EXTRA_TRANSIENT_STATE, mTransientShown);
if (mNavigationBarView != null) {
mNavigationBarView.getLightTransitionsController().saveState(outState);
}
@@ -518,80 +529,107 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
}
- /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
- public void restoreSystemUiVisibilityState() {
- final int barMode = computeBarMode(0, mSystemUiVisibility);
- if (barMode != -1) {
- mNavigationBarMode = barMode;
- }
+ /** Restores the appearance and the transient saved state to {@link NavigationBarFragment}. */
+ public void restoreAppearanceAndTransientState() {
+ final int barMode = barMode(mTransientShown, mAppearance);
+ mNavigationBarMode = barMode;
checkNavBarModes();
mAutoHideController.touchAutoHide();
- mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
- true /* nbModeChanged */, mNavigationBarMode, false /* navbarColorManagedByIme */);
+ mLightBarController.onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+ barMode, false /* navbarColorManagedByIme */);
}
@Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
if (displayId != mDisplayId) {
return;
}
- final int oldVal = mSystemUiVisibility;
- final int newVal = (oldVal & ~mask) | (vis & mask);
- final int diff = newVal ^ oldVal;
boolean nbModeChanged = false;
- if (diff != 0) {
- mSystemUiVisibility = newVal;
-
- // update navigation bar mode
- final int nbMode = getView() == null
- ? -1 : computeBarMode(oldVal, newVal);
- nbModeChanged = nbMode != -1;
- if (nbModeChanged) {
- if (mNavigationBarMode != nbMode) {
- if (mNavigationBarMode == MODE_TRANSPARENT
- || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
- mNavigationBarView.hideRecentsOnboarding();
- }
- mNavigationBarMode = nbMode;
- checkNavBarModes();
- }
- mAutoHideController.touchAutoHide();
- }
- if (mNavigationBarView != null) {
- mNavigationBarView.onSystemUiVisibilityChanged(mSystemUiVisibility);
+ if (mAppearance != appearance) {
+ mAppearance = appearance;
+ if (getView() == null) {
+ return;
}
+ nbModeChanged = updateBarMode(barMode(mTransientShown, appearance));
+ }
+ mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged,
+ mNavigationBarMode, navbarColorManagedByIme);
+ }
+
+ @Override
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+ return;
+ }
+ if (!mTransientShown) {
+ mTransientShown = true;
+ handleTransientChanged();
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+ return;
+ }
+ clearTransient();
+ }
+
+ void clearTransient() {
+ if (mTransientShown) {
+ mTransientShown = false;
+ handleTransientChanged();
}
- mLightBarController.onNavigationVisibilityChanged(
- vis, mask, nbModeChanged, mNavigationBarMode, navbarColorManagedByIme);
}
- private @TransitionMode int computeBarMode(int oldVis, int newVis) {
- final int oldMode = barMode(oldVis);
- final int newMode = barMode(newVis);
- if (oldMode == newMode) {
- return -1; // no mode change
+ private void handleTransientChanged() {
+ if (getView() == null) {
+ return;
+ }
+ if (mNavigationBarView != null) {
+ mNavigationBarView.onTransientStateChanged(mTransientShown);
+ }
+ final int barMode = barMode(mTransientShown, mAppearance);
+ if (updateBarMode(barMode)) {
+ mLightBarController.onNavigationBarModeChanged(barMode);
}
- return newMode;
}
- private @TransitionMode int barMode(int vis) {
- final int lightsOutTransparent =
- View.SYSTEM_UI_FLAG_LOW_PROFILE | View.NAVIGATION_BAR_TRANSIENT;
- if ((vis & View.NAVIGATION_BAR_TRANSIENT) != 0) {
+ // Returns true if the bar mode is changed.
+ private boolean updateBarMode(int barMode) {
+ if (mNavigationBarMode != barMode) {
+ if (mNavigationBarMode == MODE_TRANSPARENT
+ || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
+ mNavigationBarView.hideRecentsOnboarding();
+ }
+ mNavigationBarMode = barMode;
+ checkNavBarModes();
+ mAutoHideController.touchAutoHide();
+ return true;
+ }
+ return false;
+ }
+
+ private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+ final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_SIDE_BARS;
+ if (isTransient) {
return MODE_SEMI_TRANSPARENT;
- } else if ((vis & View.NAVIGATION_BAR_TRANSLUCENT) != 0) {
- return MODE_TRANSLUCENT;
- } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
- return MODE_LIGHTS_OUT_TRANSPARENT;
- } else if ((vis & View.NAVIGATION_BAR_TRANSPARENT) != 0) {
- return MODE_TRANSPARENT;
- } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
return MODE_LIGHTS_OUT;
- } else {
+ } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((appearance & APPEARANCE_OPAQUE_SIDE_BARS) != 0) {
return MODE_OPAQUE;
+ } else {
+ return MODE_TRANSPARENT;
}
}
@@ -990,8 +1028,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mAutoHideController.setNavigationBar(this);
}
- public boolean isSemiTransparent() {
- return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
+ boolean isTransientShown() {
+ return mTransientShown;
}
private void checkBarModes() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ae18833d99b5..4b4a35bae05d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -366,8 +366,8 @@ public class NavigationBarView extends FrameLayout implements
return super.onTouchEvent(event);
}
- void onSystemUiVisibilityChanged(int systemUiVisibility) {
- mEdgeBackGestureHandler.onSystemUiVisibilityChanged(systemUiVisibility);
+ void onTransientStateChanged(boolean isTransient) {
+ mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
}
void onBarTransition(int newMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8e70d082dbb6..145be4899f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,6 +24,11 @@ import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.view.InsetsFlags.getAppearance;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.BG_HANDLER;
@@ -75,7 +80,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -104,6 +108,7 @@ import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -112,6 +117,7 @@ import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
@@ -124,6 +130,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.internal.view.AppearanceRegion;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -428,10 +435,13 @@ public class StatusBar extends SystemUI implements DemoMode,
private int mDisabled1 = 0;
private int mDisabled2 = 0;
- // tracking calls to View.setSystemUiVisibility()
- private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
- private final Rect mLastFullscreenStackBounds = new Rect();
- private final Rect mLastDockedStackBounds = new Rect();
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ private @Appearance int mAppearance;
+
+ private boolean mTransientShown;
+
+ private boolean mAppFullscreen;
+ private boolean mAppImmersive;
private final DisplayMetrics mDisplayMetrics;
@@ -826,10 +836,22 @@ public class StatusBar extends SystemUI implements DemoMode,
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- setSystemUiVisibility(mDisplayId, result.mSystemUiVisibility,
- result.mFullscreenStackSysUiVisibility, result.mDockedStackSysUiVisibility,
- 0xffffffff, result.mFullscreenStackBounds, result.mDockedStackBounds,
- result.mNavbarColorManagedByIme);
+ if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+ showTransientUnchecked();
+ }
+ final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
+ final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
+ final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
+ ? new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
+ : new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
+ new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
+ onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
+ appearanceRegions, result.mNavbarColorManagedByIme);
+ mAppFullscreen = result.mAppFullscreen;
+ mAppImmersive = result.mAppImmersive;
+
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
result.mImeBackDisposition, result.mShowImeSwitcher);
@@ -2230,49 +2252,104 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- @Override // CommandQueue
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
if (displayId != mDisplayId) {
return;
}
- final int oldVal = mSystemUiVisibility;
- final int newVal = (oldVal&~mask) | (vis&mask);
- final int diff = newVal ^ oldVal;
- if (DEBUG) Log.d(TAG, String.format(
- "setSystemUiVisibility displayId=%d vis=%s mask=%s oldVal=%s newVal=%s diff=%s",
- displayId, Integer.toHexString(vis), Integer.toHexString(mask),
- Integer.toHexString(oldVal), Integer.toHexString(newVal),
- Integer.toHexString(diff)));
- boolean sbModeChanged = false;
- if (diff != 0) {
- mSystemUiVisibility = newVal;
+ boolean barModeChanged = false;
+ final int diff = mAppearance ^ appearance;
+ if (mAppearance != appearance) {
+ mAppearance = appearance;
// update low profile
- if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ if ((diff & APPEARANCE_LOW_PROFILE_BARS) != 0) {
updateAreThereNotifications();
}
+ barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
+ }
+ mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
+ mStatusBarMode, navbarColorManagedByIme);
+ }
- // ready to unhide
- if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
- mNoAnimationOnNextBarModeChange = true;
- }
+ @Override
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_TOP_BAR)) {
+ return;
+ }
+ showTransientUnchecked();
+ }
+
+ private void showTransientUnchecked() {
+ if (!mTransientShown) {
+ mTransientShown = true;
+ mNoAnimationOnNextBarModeChange = true;
+ handleTransientChanged();
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ if (!containsType(types, TYPE_TOP_BAR)) {
+ return;
+ }
+ clearTransient();
+ }
+
+ void clearTransient() {
+ if (mTransientShown) {
+ mTransientShown = false;
+ handleTransientChanged();
+ }
+ }
- // update status bar mode
- final int sbMode = computeStatusBarMode(oldVal, newVal);
+ private void handleTransientChanged() {
+ final int barMode = barMode(mTransientShown, mAppearance);
+ if (updateBarMode(barMode)) {
+ mLightBarController.onStatusBarModeChanged(barMode);
+ }
+ }
- sbModeChanged = sbMode != -1;
- if (sbModeChanged && sbMode != mStatusBarMode) {
- mStatusBarMode = sbMode;
- checkBarModes();
- mAutoHideController.touchAutoHide();
- }
- mStatusBarStateController.setSystemUiVisibility(mSystemUiVisibility);
+ private boolean updateBarMode(int barMode) {
+ if (mStatusBarMode != barMode) {
+ mStatusBarMode = barMode;
+ checkBarModes();
+ mAutoHideController.touchAutoHide();
+ return true;
+ }
+ return false;
+ }
+
+ private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+ final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_TOP_BAR;
+ if (isTransient) {
+ return MODE_SEMI_TRANSPARENT;
+ } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
+ return MODE_LIGHTS_OUT;
+ } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((appearance & APPEARANCE_OPAQUE_TOP_BAR) != 0) {
+ return MODE_OPAQUE;
+ } else {
+ return MODE_TRANSPARENT;
+ }
+ }
+
+ @Override
+ public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ if (displayId != mDisplayId) {
+ return;
}
- mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
- mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
- navbarColorManagedByIme);
+ mAppFullscreen = isFullscreen;
+ mAppImmersive = isImmersive;
+ mStatusBarStateController.setFullscreenState(isFullscreen, isImmersive);
}
@Override
@@ -2303,40 +2380,10 @@ public class StatusBar extends SystemUI implements DemoMode,
setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running);
}
- protected @TransitionMode int computeStatusBarMode(int oldVal, int newVal) {
- return computeBarMode(oldVal, newVal);
- }
-
protected BarTransitions getStatusBarTransitions() {
return mStatusBarView.getBarTransitions();
}
- protected @TransitionMode int computeBarMode(int oldVis, int newVis) {
- final int oldMode = barMode(oldVis);
- final int newMode = barMode(newVis);
- if (oldMode == newMode) {
- return -1; // no mode change
- }
- return newMode;
- }
-
- private @TransitionMode int barMode(int vis) {
- int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.STATUS_BAR_TRANSPARENT;
- if ((vis & View.STATUS_BAR_TRANSIENT) != 0) {
- return MODE_SEMI_TRANSPARENT;
- } else if ((vis & View.STATUS_BAR_TRANSLUCENT) != 0) {
- return MODE_TRANSLUCENT;
- } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
- return MODE_LIGHTS_OUT_TRANSPARENT;
- } else if ((vis & View.STATUS_BAR_TRANSPARENT) != 0) {
- return MODE_TRANSPARENT;
- } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
- return MODE_LIGHTS_OUT;
- } else {
- return MODE_OPAQUE;
- }
- }
-
void checkBarModes() {
if (mDemoMode) return;
if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
@@ -2392,20 +2439,16 @@ public class StatusBar extends SystemUI implements DemoMode,
/** Returns whether the top activity is in fullscreen mode. */
public boolean inFullscreenMode() {
- return 0
- != (mSystemUiVisibility
- & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION));
+ return mAppFullscreen;
}
/** Returns whether the top activity is in immersive mode. */
public boolean inImmersiveMode() {
- return 0
- != (mSystemUiVisibility
- & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY));
+ return mAppImmersive;
}
private boolean areLightsOn() {
- return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ return 0 == (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
}
public static String viewInfo(View v) {
@@ -4729,8 +4772,8 @@ public class StatusBar extends SystemUI implements DemoMode,
void createStatusBar(StatusBar statusbar);
}
- public @TransitionMode int getStatusBarMode() {
- return mStatusBarMode;
+ boolean isTransientShown() {
+ return mTransientShown;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index d04c7bd38320..6b513919e912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -42,6 +43,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
+import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
@@ -74,7 +76,8 @@ public class StatusBarWindowView extends FrameLayout {
}
@Override
- protected boolean fitSystemWindows(Rect insets) {
+ public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
+ final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars());
if (getFitsSystemWindows()) {
boolean paddingChanged = insets.top != getPaddingTop()
|| insets.bottom != getPaddingBottom();
@@ -100,9 +103,6 @@ public class StatusBarWindowView extends FrameLayout {
if (paddingChanged) {
setPadding(0, 0, 0, 0);
}
- insets.left = 0;
- insets.top = 0;
- insets.right = 0;
} else {
if (mRightInset != 0 || mLeftInset != 0) {
mRightInset = 0;
@@ -116,9 +116,8 @@ public class StatusBarWindowView extends FrameLayout {
if (changed) {
setPadding(0, 0, 0, 0);
}
- insets.top = 0;
}
- return false;
+ return windowInsets;
}
private void applyMargins() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 1bd01e166ddb..eb198c6ad4f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -15,6 +15,8 @@
package com.android.systemui.statusbar;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -25,10 +27,12 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
+import android.view.WindowInsetsController.Appearance;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -110,21 +114,56 @@ public class CommandQueueTest extends SysuiTestCase {
}
@Test
- public void testSetSystemUiVisibility() {
- Rect r = new Rect();
- mCommandQueue.setSystemUiVisibility(DEFAULT_DISPLAY, 1, 2, 3, 4, null, r, false);
+ public void testOnSystemBarAppearanceChanged() {
+ doTestOnSystemBarAppearanceChanged(DEFAULT_DISPLAY, 1,
+ new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
+ }
+
+ @Test
+ public void testOnSystemBarAppearanceChangedForSecondaryDisplay() {
+ doTestOnSystemBarAppearanceChanged(SECONDARY_DISPLAY, 1,
+ new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
+ }
+
+ private void doTestOnSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ mCommandQueue.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
+ navbarColorManagedByIme);
+ waitForIdleSync();
+ verify(mCallbacks).onSystemBarAppearanceChanged(eq(displayId), eq(appearance),
+ eq(appearanceRegions), eq(navbarColorManagedByIme));
+ }
+
+ @Test
+ public void testShowTransient() {
+ int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+ mCommandQueue.showTransient(DEFAULT_DISPLAY, types);
+ waitForIdleSync();
+ verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types));
+ }
+
+ @Test
+ public void testShowTransientForSecondaryDisplay() {
+ int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+ mCommandQueue.showTransient(SECONDARY_DISPLAY, types);
+ waitForIdleSync();
+ verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types));
+ }
+
+ @Test
+ public void testAbortTransient() {
+ int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+ mCommandQueue.abortTransient(DEFAULT_DISPLAY, types);
waitForIdleSync();
- verify(mCallbacks).setSystemUiVisibility(eq(DEFAULT_DISPLAY), eq(1), eq(2), eq(3), eq(4),
- eq(null), eq(r), eq(false));
+ verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types));
}
@Test
- public void testSetSystemUiVisibilityForSecondaryDisplay() {
- Rect r = new Rect();
- mCommandQueue.setSystemUiVisibility(SECONDARY_DISPLAY, 1, 2, 3, 4, null, r, false);
+ public void testAbortTransientForSecondaryDisplay() {
+ int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+ mCommandQueue.abortTransient(SECONDARY_DISPLAY, types);
waitForIdleSync();
- verify(mCallbacks).setSystemUiVisibility(eq(SECONDARY_DISPLAY), eq(1), eq(2), eq(3), eq(4),
- eq(null), eq(r), eq(false));
+ verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
deleted file mode 100644
index 16f02d9dd661..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.IWindowManager;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** atest AutoHideControllerTest */
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-@SmallTest
-public class AutoHideControllerTest extends SysuiTestCase {
-
- private AutoHideController mAutoHideController;
-
- private static final int FULL_MASK = 0xffffffff;
-
- @Before
- public void setUp() {
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
- mAutoHideController =
- spy(new AutoHideController(mContext, Dependency.get(Dependency.MAIN_HANDLER),
- mock(NotificationRemoteInputManager.class), mock(IWindowManager.class)));
- mAutoHideController.mDisplayId = DEFAULT_DISPLAY;
- mAutoHideController.mSystemUiVisibility = View.VISIBLE;
- }
-
- @After
- public void tearDown() {
- mAutoHideController = null;
- }
-
- @Test
- public void testSetSystemUiVisibilityEarlyReturnWithDifferentDisplay() {
- mAutoHideController.setSystemUiVisibility(1, 1, 2, 3, 4, null, new Rect(), false);
-
- verify(mAutoHideController, never()).notifySystemUiVisibilityChanged(anyInt());
- }
-
- @Test
- public void testSetSystemUiVisibilityEarlyReturnWithSameVisibility() {
- mAutoHideController
- .setSystemUiVisibility(
- DEFAULT_DISPLAY, View.VISIBLE, 2, 3, 4, null, new Rect(), false);
-
- verify(mAutoHideController, never()).notifySystemUiVisibilityChanged(anyInt());
- }
-
- // Test if status bar unhide status doesn't change without status bar.
- @Test
- public void testSetSystemUiVisibilityWithoutStatusBar() {
- doReturn(false).when(mAutoHideController).hasStatusBar();
- int expectedStatus = View.STATUS_BAR_UNHIDE;
- mAutoHideController.mSystemUiVisibility =
- View.SYSTEM_UI_FLAG_FULLSCREEN | View.STATUS_BAR_UNHIDE;
-
- mAutoHideController.setSystemUiVisibility(
- DEFAULT_DISPLAY, expectedStatus, 2, 3, FULL_MASK, null, new Rect(), false);
-
- assertEquals("System UI visibility should not be changed",
- expectedStatus, mAutoHideController.mSystemUiVisibility);
- verify(mAutoHideController, times(1)).notifySystemUiVisibilityChanged(eq(expectedStatus));
- }
-
- @Test
- public void testSetSystemUiVisibilityWithVisChanged() {
- doReturn(true).when(mAutoHideController).hasStatusBar();
- doReturn(true).when(mAutoHideController).hasNavigationBar();
- mAutoHideController.mSystemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.STATUS_BAR_UNHIDE
- | View.NAVIGATION_BAR_UNHIDE;
-
- mAutoHideController.setSystemUiVisibility(
- DEFAULT_DISPLAY, View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE,
- 2, 3, FULL_MASK, null, new Rect(), false);
-
- int expectedStatus = View.VISIBLE;
- assertEquals(expectedStatus, mAutoHideController.mSystemUiVisibility);
- verify(mAutoHideController).notifySystemUiVisibilityChanged(eq(expectedStatus));
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
new file mode 100644
index 000000000000..6260d531a290
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class LightBarControllerTest extends SysuiTestCase {
+
+ private LightBarTransitionsController mLightBarTransitionsController;
+ private SysuiDarkIconDispatcher mStatusBarIconController;
+ private LightBarController mLightBarController;
+
+ @Before
+ public void setup() {
+ mStatusBarIconController = mock(SysuiDarkIconDispatcher.class);
+ mLightBarTransitionsController = mock(LightBarTransitionsController.class);
+ when(mStatusBarIconController.getTransitionsController()).thenReturn(
+ mLightBarTransitionsController);
+ mLightBarController = new LightBarController(mContext, mStatusBarIconController,
+ mock(BatteryController.class));
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_multipleStacks_allStacksLight() {
+ final Rect firstBounds = new Rect(0, 0, 1, 1);
+ final Rect secondBounds = new Rect(1, 0, 2, 1);
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, firstBounds),
+ new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, secondBounds)
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mStatusBarIconController).setIconsDarkArea(eq(null));
+ verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_multipleStacks_oneStackLightOneStackDark() {
+ final Rect firstBounds = new Rect(0, 0, 1, 1);
+ final Rect secondBounds = new Rect(1, 0, 2, 1);
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, firstBounds),
+ new AppearanceRegion(0 /* appearance */, secondBounds)
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mStatusBarIconController).setIconsDarkArea(eq(firstBounds));
+ verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_multipleStacks_oneStackDarkOneStackLight() {
+ final Rect firstBounds = new Rect(0, 0, 1, 1);
+ final Rect secondBounds = new Rect(1, 0, 2, 1);
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(0 /* appearance */, firstBounds),
+ new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, secondBounds)
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mStatusBarIconController).setIconsDarkArea(eq(secondBounds));
+ verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_multipleStacks_allStacksDark() {
+ final Rect firstBounds = new Rect(0, 0, 1, 1);
+ final Rect secondBounds = new Rect(1, 0, 2, 1);
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(0 /* appearance */, firstBounds),
+ new AppearanceRegion(0 /* appearance */, secondBounds)
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mLightBarTransitionsController).setIconsDark(eq(false), anyBoolean());
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_singleStack_light() {
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, new Rect(0, 0, 1, 1))
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mStatusBarIconController).setIconsDarkArea(eq(null));
+ verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+ }
+
+ @Test
+ public void testOnStatusBarAppearanceChanged_singleStack_dark() {
+ final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+ new AppearanceRegion(0, new Rect(0, 0, 1, 1))
+ };
+ mLightBarController.onStatusBarAppearanceChanged(
+ appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+ false /* navbarColorManagedByIme */);
+ verify(mLightBarTransitionsController).setIconsDark(eq(false), anyBoolean());
+ }
+}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index a93d2b8b6fb9..ec64ee6d52de 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -18,7 +18,10 @@ package com.android.server.statusbar;
import android.graphics.Rect;
import android.os.Bundle;
+import android.view.InsetsState.InternalInsetType;
+import android.view.WindowInsetsController.Appearance;
+import com.android.internal.view.AppearanceRegion;
import com.android.server.notification.NotificationDelegate;
public interface StatusBarManagerInternal {
@@ -75,7 +78,7 @@ public interface StatusBarManagerInternal {
void startAssist(Bundle args);
void onCameraLaunchGestureDetected(int source);
- void topAppWindowChanged(int displayId, boolean menuVisible);
+ void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme,
String cause);
@@ -113,4 +116,14 @@ public interface StatusBarManagerInternal {
* Notifies System UI whether the recents animation is running.
*/
void onRecentsAnimationStateChanged(boolean running);
+
+ /** @see com.android.internal.statusbar.IStatusBar#onSystemBarAppearanceChanged */
+ void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme);
+
+ /** @see com.android.internal.statusbar.IStatusBar#showTransient */
+ void showTransient(int displayId, @InternalInsetType int[] types);
+
+ /** @see com.android.internal.statusbar.IStatusBar#abortTransient */
+ void abortTransient(int displayId, @InternalInsetType int[] types);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 65bb2342d504..3c1a6afccda1 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -47,6 +47,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.WindowInsetsController.Appearance;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -56,6 +57,7 @@ import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.DumpUtils;
+import com.android.internal.view.AppearanceRegion;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationDelegate;
import com.android.server.policy.GlobalActionsProvider;
@@ -256,8 +258,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void topAppWindowChanged(int displayId, boolean menuVisible) {
- StatusBarManagerService.this.topAppWindowChanged(displayId, menuVisible);
+ public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+ StatusBarManagerService.this.topAppWindowChanged(displayId, isFullscreen, isImmersive);
}
@Override
@@ -467,6 +469,36 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
}
+
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ // TODO (b/118118435): save the information to UiState
+ if (mBar != null) {
+ try {
+ mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
+ navbarColorManagedByIme);
+ } catch (RemoteException ex) { }
+ }
+ }
+
+ @Override
+ public void showTransient(int displayId, int[] types) {
+ if (mBar != null) {
+ try {
+ mBar.showTransient(displayId, types);
+ } catch (RemoteException ex) { }
+ }
+ }
+
+ @Override
+ public void abortTransient(int displayId, int[] types) {
+ if (mBar != null) {
+ try {
+ mBar.abortTransient(displayId, types);
+ } catch (RemoteException ex) { }
+ }
+ }
};
private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
@@ -817,23 +849,19 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
/**
- * Hide or show the on-screen Menu key. Only call this from the window manager, typically in
- * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set
- * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}.
+ * Enables System UI to know whether the top app is fullscreen or not, and whether this app is
+ * in immersive mode or not.
*/
- private void topAppWindowChanged(int displayId, final boolean menuVisible) {
+ private void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
enforceStatusBar();
- if (SPEW) {
- Slog.d(TAG, "display#" + displayId + ": "
- + (menuVisible ? "showing" : "hiding") + " MENU key");
- }
synchronized(mLock) {
- getUiState(displayId).setMenuVisible(menuVisible);
+ getUiState(displayId).setFullscreen(isFullscreen);
+ getUiState(displayId).setImmersive(isImmersive);
mHandler.post(() -> {
if (mBar != null) {
try {
- mBar.topAppWindowChanged(displayId, menuVisible);
+ mBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
} catch (RemoteException ex) {
}
}
@@ -942,7 +970,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
private int mDockedStackSysUiVisibility = 0;
private final Rect mFullscreenStackBounds = new Rect();
private final Rect mDockedStackBounds = new Rect();
- private boolean mMenuVisible = false;
+ private boolean mFullscreen = false;
+ private boolean mImmersive = false;
private int mDisabled1 = 0;
private int mDisabled2 = 0;
private int mImeWindowVis = 0;
@@ -964,12 +993,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
mDisabled2 = disabled2;
}
- private boolean isMenuVisible() {
- return mMenuVisible;
+ private void setFullscreen(boolean isFullscreen) {
+ mFullscreen = isFullscreen;
}
- private void setMenuVisible(boolean menuVisible) {
- mMenuVisible = menuVisible;
+ private void setImmersive(boolean immersive) {
+ mImmersive = immersive;
}
private boolean disableEquals(int disabled1, int disabled2) {
@@ -1056,12 +1085,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
// Make it aware of multi-display if needed.
final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
- state.mSystemUiVisibility, state.mMenuVisible, state.mImeWindowVis,
+ state.mSystemUiVisibility, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
gatherDisableActionsLocked(mCurrentUserId, 2),
state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility,
state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme);
+ state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 940e8148444c..aa0b68b9bfc5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3450,6 +3450,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return win != null;
}
+ void hideTransientBars() {
+ // TODO(b/118118435): Remove this after migration
+ final int transientFlags = View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
+ statusBarVisibilityChanged(mLastStatusBarVisibility & ~transientFlags);
+
+ getInsetsPolicy().hideTransient();
+ }
+
void statusBarVisibilityChanged(int visibility) {
mLastStatusBarVisibility = visibility;
visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(visibility);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 150e26eefe4e..8877e4c47da7 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -30,7 +30,11 @@ import static android.view.InsetsState.TYPE_TOP_GESTURES;
import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
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;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+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.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -129,6 +133,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -145,6 +150,7 @@ import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -158,6 +164,7 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.util.function.TriConsumer;
+import com.android.internal.view.AppearanceRegion;
import com.android.internal.widget.PointerLocationView;
import com.android.server.LocalServices;
import com.android.server.UiThread;
@@ -235,7 +242,7 @@ public class DisplayPolicy {
@Px
private int mSideGestureInset;
- private StatusBarManagerInternal getStatusBarManagerInternal() {
+ StatusBarManagerInternal getStatusBarManagerInternal() {
synchronized (mServiceAcquireLock) {
if (mStatusBarManagerInternal == null) {
mStatusBarManagerInternal =
@@ -327,14 +334,18 @@ public class DisplayPolicy {
private int mForceClearedSystemUiFlags = 0;
private int mLastFullscreenStackSysUiFlags;
private int mLastDockedStackSysUiFlags;
+ private int mLastAppearance;
+ private int mLastFullscreenAppearance;
+ private int mLastDockedAppearance;
private final Rect mNonDockedStackBounds = new Rect();
private final Rect mDockedStackBounds = new Rect();
private final Rect mLastNonDockedStackBounds = new Rect();
private final Rect mLastDockedStackBounds = new Rect();
- // What we last reported to system UI about whether the compatibility
- // menu needs to be displayed.
- private boolean mLastFocusNeedsMenu = false;
+ // What we last reported to system UI about whether the focused window is fullscreen/immersive.
+ private boolean mLastFocusIsFullscreen = false;
+ private boolean mLastFocusIsImmersive = false;
+
// If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
private long mPendingPanicGestureUptime;
@@ -3045,19 +3056,38 @@ public class DisplayPolicy {
// Swipe-up for navigation bar is disabled during setup
return;
}
- boolean sb = mStatusBarController.checkShowTransientBarLw();
- boolean nb = mNavigationBarController.checkShowTransientBarLw()
- && !isNavBarEmpty(mLastSystemUiFlags);
- if (sb || nb) {
- // Don't show status bar when swiping on already visible navigation bar
- if (!nb && swipeTarget == mNavigationBar) {
- if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+ if (swipeTarget == mNavigationBar
+ && !getInsetsPolicy().isHidden(InsetsState.TYPE_NAVIGATION_BAR)) {
+ // Don't show status bar when swiping on already visible navigation bar
+ return;
+ }
+ final InsetsControlTarget controlTarget =
+ swipeTarget.getControllableInsetProvider().getControlTarget();
+ if (controlTarget == null) {
return;
}
- if (sb) mStatusBarController.showTransient();
- if (nb) mNavigationBarController.showTransient();
+ if (controlTarget.canShowTransient()) {
+ mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+ new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+ } else {
+ controlTarget.showInsets(WindowInsets.Type.systemBars(), false);
+ }
+ } else {
+ boolean sb = mStatusBarController.checkShowTransientBarLw();
+ boolean nb = mNavigationBarController.checkShowTransientBarLw()
+ && !isNavBarEmpty(mLastSystemUiFlags);
+ if (sb || nb) {
+ // Don't show status bar when swiping on already visible navigation bar
+ if (!nb && swipeTarget == mNavigationBar) {
+ if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
+ return;
+ }
+ if (sb) mStatusBarController.showTransient();
+ if (nb) mNavigationBarController.showTransient();
+ updateSystemUiVisibilityLw();
+ }
mImmersiveModeConfirmation.confirmCurrentPrompt();
- updateSystemUiVisibilityLw();
}
}
}
@@ -3078,6 +3108,10 @@ public class DisplayPolicy {
return mService.mPolicy.isKeyguardOccluded();
}
+ InsetsPolicy getInsetsPolicy() {
+ return mDisplayContent.getInsetsPolicy();
+ }
+
void resetSystemUiVisibilityLw() {
mLastSystemUiFlags = 0;
updateSystemUiVisibilityLw();
@@ -3129,14 +3163,20 @@ public class DisplayPolicy {
&= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
+ final int appearance = win.mAttrs.insetsFlags.appearance;
final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
+ final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
+ mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
+ final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
+ mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
mService.getStackBounds(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
- mService.getStackBounds(mDockedStackBounds.isEmpty()
- ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+ final boolean inSplitScreen = !mDockedStackBounds.isEmpty();
+ mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ : WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
final Pair<Integer, Boolean> result =
updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
@@ -3144,8 +3184,24 @@ public class DisplayPolicy {
final int diff = visibility ^ mLastSystemUiFlags;
final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
- final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
- if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
+ final InsetsPolicy insetsPolicy = getInsetsPolicy();
+ final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
+ || (PolicyControl.getWindowFlags(win, win.mAttrs) & FLAG_FULLSCREEN) != 0
+ || (mStatusBar != null && insetsPolicy.isHidden(TYPE_TOP_BAR))
+ || (mNavigationBar != null && insetsPolicy.isHidden(
+ InsetsState.TYPE_NAVIGATION_BAR));
+ final int behavior = win.mAttrs.insetsFlags.behavior;
+ final boolean isImmersive = (visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
+ || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
+ || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+ if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0
+ && mLastAppearance == appearance
+ && mLastFullscreenAppearance == fullscreenAppearance
+ && mLastDockedAppearance == dockedAppearance
+ && mLastFocusIsFullscreen == isFullscreen
+ && mLastFocusIsImmersive == isImmersive
&& mFocusedApp == win.getAppToken()
&& mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
&& mLastDockedStackBounds.equals(mDockedStackBounds)) {
@@ -3154,21 +3210,39 @@ public class DisplayPolicy {
mLastSystemUiFlags = visibility;
mLastFullscreenStackSysUiFlags = fullscreenVisibility;
mLastDockedStackSysUiFlags = dockedVisibility;
- mLastFocusNeedsMenu = needsMenu;
+ mLastAppearance = appearance;
+ mLastFullscreenAppearance = fullscreenAppearance;
+ mLastDockedAppearance = dockedAppearance;
+ mLastFocusIsFullscreen = isFullscreen;
+ mLastFocusIsImmersive = isImmersive;
mFocusedApp = win.getAppToken();
mLastNonDockedStackBounds.set(mNonDockedStackBounds);
mLastDockedStackBounds.set(mDockedStackBounds);
final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
final Rect dockedStackBounds = new Rect(mDockedStackBounds);
+ final AppearanceRegion[] appearanceRegions = inSplitScreen
+ ? new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
+ new AppearanceRegion(dockedAppearance, dockedStackBounds)}
+ : new AppearanceRegion[]{
+ new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
final boolean isNavbarColorManagedByIme = result.second;
mHandler.post(() -> {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
+ // TODO(b/118118435): disabled flags only
statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
dockedVisibility, 0xffffffff, fullscreenStackBounds,
dockedStackBounds, isNavbarColorManagedByIme, win.toString());
- statusBar.topAppWindowChanged(displayId, needsMenu);
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+ statusBar.onSystemBarAppearanceChanged(displayId, appearance,
+ appearanceRegions, isNavbarColorManagedByIme);
+ }
+ statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
+
+ // TODO(b/118118435): Remove this after removing system UI visibilities.
+ mDisplayContent.statusBarVisibilityChanged(visibility);
}
});
return diff;
@@ -3190,6 +3264,22 @@ public class DisplayPolicy {
return vis;
}
+ private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque,
+ WindowState opaqueOrDimming) {
+ final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
+ final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
+ if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
+ appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR;
+ } else if (statusColorWin != null && statusColorWin.isDimming()) {
+ // Otherwise if it's dimming, clear the light flag.
+ appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
+ }
+ return appearance;
+ }
+
@VisibleForTesting
@Nullable
static WindowState chooseNavigationColorWindowLw(WindowState opaque,
@@ -3511,6 +3601,8 @@ public class DisplayPolicy {
mPendingPanicGestureUptime = SystemClock.uptimeMillis();
if (!isNavBarEmpty(mLastSystemUiFlags)) {
mNavigationBarController.showTransient();
+ mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+ new int[] {InsetsState.TYPE_NAVIGATION_BAR}));
}
}
}
@@ -3588,9 +3680,6 @@ public class DisplayPolicy {
pw.print(" mForceClearedSystemUiFlags=0x");
pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
}
- if (mLastFocusNeedsMenu) {
- pw.print(prefix); pw.print("mLastFocusNeedsMenu="); pw.println(mLastFocusNeedsMenu);
- }
pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 22ba82ace865..c8ce53d444d5 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -42,4 +42,11 @@ interface InsetsControlTarget {
*/
default void hideInsets(@InsetType int types, boolean fromIme) {
}
+
+ /**
+ * Returns {@code true} if the control target allows the system to show transient windows.
+ */
+ default boolean canShowTransient() {
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 2dc50d86eaea..fc51b467c8d4 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -16,13 +16,22 @@
package com.android.server.wm;
+import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import android.annotation.Nullable;
+import android.app.StatusBarManager;
+import android.util.IntArray;
+import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
+import android.view.ViewRootImpl;
/**
* Policy that implements who gets control over the windows generating insets.
@@ -32,6 +41,12 @@ class InsetsPolicy {
private final InsetsStateController mStateController;
private final DisplayContent mDisplayContent;
private final DisplayPolicy mPolicy;
+ private final TransientControlTarget mTransientControlTarget = new TransientControlTarget();
+ private final IntArray mShowingTransientTypes = new IntArray();
+
+ private WindowState mFocusedWin;
+ private BarWindow mTopBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
+ private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
mStateController = stateController;
@@ -41,11 +56,132 @@ class InsetsPolicy {
/** Updates the target which can control system bars. */
void updateBarControlTarget(@Nullable WindowState focusedWin) {
+ mFocusedWin = focusedWin;
mStateController.onBarControlTargetChanged(getTopControlTarget(focusedWin),
- getNavControlTarget(focusedWin));
+ getFakeTopControlTarget(focusedWin),
+ getNavControlTarget(focusedWin),
+ getFakeNavControlTarget(focusedWin));
+ if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
+ return;
+ }
+ mTopBar.setVisible(focusedWin == null
+ || focusedWin != getTopControlTarget(focusedWin)
+ || focusedWin.getClientInsetsState().getSource(TYPE_TOP_BAR).isVisible());
+ mNavBar.setVisible(focusedWin == null
+ || focusedWin != getNavControlTarget(focusedWin)
+ || focusedWin.getClientInsetsState().getSource(TYPE_NAVIGATION_BAR).isVisible());
+ }
+
+ boolean isHidden(@InternalInsetType int type) {
+ final InsetsSourceProvider provider = mStateController.peekSourceProvider(type);
+ return provider != null && provider.hasWindow() && !provider.getSource().isVisible();
+ }
+
+ void showTransient(IntArray types) {
+ boolean changed = false;
+ for (int i = types.size() - 1; i >= 0; i--) {
+ final int type = types.get(i);
+ if (mShowingTransientTypes.indexOf(type) != -1) {
+ continue;
+ }
+ if (!isHidden(type)) {
+ continue;
+ }
+ mShowingTransientTypes.add(type);
+ changed = true;
+ }
+ if (changed) {
+ updateBarControlTarget(mFocusedWin);
+ mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
+ mShowingTransientTypes.toArray());
+ mStateController.notifyInsetsChanged();
+ // TODO(b/118118435): Animation
+ }
+ }
+
+ void hideTransient() {
+ if (mShowingTransientTypes.size() == 0) {
+ return;
+ }
+
+ // TODO(b/118118435): Animation
+ mShowingTransientTypes.clear();
+ updateBarControlTarget(mFocusedWin);
+ mStateController.notifyInsetsChanged();
+ }
+
+ /**
+ * @see InsetsStateController#getInsetsForDispatch
+ */
+ InsetsState getInsetsForDispatch(WindowState target) {
+ InsetsState state = mStateController.getInsetsForDispatch(target);
+ if (mShowingTransientTypes.size() == 0) {
+ return state;
+ }
+ for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ state.setSourceVisible(mShowingTransientTypes.get(i), false);
+ }
+ return state;
+ }
+
+ void onInsetsModified(WindowState windowState, InsetsState state) {
+ mStateController.onInsetsModified(windowState, state);
+ checkAbortTransient(windowState, state);
+ if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
+ return;
+ }
+ if (windowState == getTopControlTarget(mFocusedWin)) {
+ mTopBar.setVisible(state.getSource(TYPE_TOP_BAR).isVisible());
+ }
+ if (windowState == getNavControlTarget(mFocusedWin)) {
+ mNavBar.setVisible(state.getSource(TYPE_NAVIGATION_BAR).isVisible());
+ }
+ }
+
+ /**
+ * Called when a window modified the insets state. If the window set a insets source to visible
+ * while it is shown transiently, we need to abort the transient state.
+ *
+ * @param windowState who changed the insets state.
+ * @param state the modified insets state.
+ */
+ private void checkAbortTransient(WindowState windowState, InsetsState state) {
+ if (mShowingTransientTypes.size() != 0) {
+ IntArray abortTypes = new IntArray();
+ for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ final int type = mShowingTransientTypes.get(i);
+ if (mStateController.isFakeTarget(type, windowState)
+ && state.getSource(type).isVisible()) {
+ mShowingTransientTypes.remove(i);
+ abortTypes.add(type);
+ }
+ }
+ if (abortTypes.size() > 0) {
+ mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
+ abortTypes.toArray());
+ updateBarControlTarget(mFocusedWin);
+ }
+ }
+ }
+
+ private @Nullable InsetsControlTarget getFakeTopControlTarget(@Nullable WindowState focused) {
+ if (mShowingTransientTypes.indexOf(TYPE_TOP_BAR) != -1) {
+ return focused;
+ }
+ return null;
+ }
+
+ private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) {
+ if (mShowingTransientTypes.indexOf(TYPE_NAVIGATION_BAR) != -1) {
+ return focused;
+ }
+ return null;
}
private @Nullable InsetsControlTarget getTopControlTarget(@Nullable WindowState focusedWin) {
+ if (mShowingTransientTypes.indexOf(TYPE_TOP_BAR) != -1) {
+ return mTransientControlTarget;
+ }
if (areSystemBarsForciblyVisible() || isStatusBarForciblyVisible()) {
return null;
}
@@ -53,6 +189,9 @@ class InsetsPolicy {
}
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
+ if (mShowingTransientTypes.indexOf(TYPE_NAVIGATION_BAR) != -1) {
+ return mTransientControlTarget;
+ }
if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) {
return null;
}
@@ -66,7 +205,7 @@ class InsetsPolicy {
}
final int privateFlags = statusBar.mAttrs.privateFlags;
- // TODO: Pretend to the app that it's still able to control it?
+ // TODO(b/118118435): Pretend to the app that it's still able to control it?
if ((privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
return true;
}
@@ -100,4 +239,31 @@ class InsetsPolicy {
return isDockedStackVisible || isFreeformStackVisible || isResizing;
}
+ private class BarWindow {
+
+ private final int mId;
+ private @StatusBarManager.WindowVisibleState int mState =
+ StatusBarManager.WINDOW_STATE_SHOWING;
+
+ BarWindow(int id) {
+ mId = id;
+ }
+
+ private void setVisible(boolean visible) {
+ final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
+ if (mState != state) {
+ mState = state;
+ mPolicy.getStatusBarManagerInternal().setWindowState(
+ mDisplayContent.getDisplayId(), mId, state);
+ }
+ }
+ }
+
+ // TODO(b/118118435): Implement animations for it (with SurfaceAnimator)
+ private class TransientControlTarget implements InsetsControlTarget {
+
+ @Override
+ public void notifyInsetsControlChanged() {
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 3731d3f38800..a7724a11eec2 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -111,7 +111,9 @@ class InsetsSourceProvider {
void setWindow(@Nullable WindowState win,
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
if (mWin != null) {
- mWin.setInsetProvider(null);
+ if (mControllable) {
+ mWin.setControllableInsetProvider(null);
+ }
// The window may be animating such that we can hand out the leash to the control
// target. Revoke the leash by cancelling the animation to correct the state.
// TODO: Ideally, we should wait for the animation to finish so previous window can
@@ -123,8 +125,8 @@ class InsetsSourceProvider {
if (win == null) {
setServerVisible(false);
mSource.setFrame(new Rect());
- } else {
- mWin.setInsetProvider(this);
+ } else if (mControllable) {
+ mWin.setControllableInsetProvider(this);
if (mControlTarget != null) {
updateControlForTarget(mControlTarget, true /* force */);
}
@@ -132,6 +134,13 @@ class InsetsSourceProvider {
}
/**
+ * @return Whether there is a window which backs this source.
+ */
+ boolean hasWindow() {
+ return mWin != null;
+ }
+
+ /**
* Called when a layout pass has occurred.
*/
void onPostLayout() {
@@ -225,6 +234,10 @@ class InsetsSourceProvider {
return null;
}
+ InsetsControlTarget getControlTarget() {
+ return mControlTarget;
+ }
+
boolean isClientVisible() {
return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
}
@@ -241,9 +254,13 @@ class InsetsSourceProvider {
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
OnAnimationFinishedCallback finishCallback) {
- // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed.
- t.setAlpha(animationLeash, 1 /* alpha */);
- t.hide(animationLeash);
+ // TODO(b/118118435): We can remove the type check when implementing the transient bar
+ // animation.
+ if (mSource.getType() == TYPE_IME) {
+ // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed.
+ t.setAlpha(animationLeash, 1 /* alpha */);
+ t.hide(animationLeash);
+ }
mCapturedLeash = animationLeash;
final Rect frame = mWin.getWindowFrames().mFrame;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b0410335c5cd..e0554242fb29 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.view.InsetsState.InternalInsetType;
import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
@@ -31,6 +30,7 @@ import android.util.SparseArray;
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -73,7 +73,7 @@ class InsetsStateController {
* @return The state stripped of the necessary information.
*/
InsetsState getInsetsForDispatch(WindowState target) {
- final InsetsSourceProvider provider = target.getInsetProvider();
+ final InsetsSourceProvider provider = target.getControllableInsetProvider();
if (provider == null) {
return mState;
}
@@ -123,6 +123,13 @@ class InsetsStateController {
}
/**
+ * @return The provider of a specific type or null if we don't have it.
+ */
+ @Nullable InsetsSourceProvider peekSourceProvider(@InternalInsetType int type) {
+ return mProviders.get(type);
+ }
+
+ /**
* Called when a layout pass has occurred.
*/
void onPostLayout() {
@@ -152,6 +159,10 @@ class InsetsStateController {
}
}
+ boolean isFakeTarget(@InternalInsetType int type, InsetsControlTarget target) {
+ return mTypeFakeControlTargetMap.get(type) == target;
+ }
+
void onImeTargetChanged(@Nullable InsetsControlTarget imeTarget) {
onControlChanged(TYPE_IME, imeTarget);
notifyPendingInsetsControlChanged();
@@ -166,9 +177,13 @@ class InsetsStateController {
* and visibility.
*/
void onBarControlTargetChanged(@Nullable InsetsControlTarget topControlling,
- @Nullable InsetsControlTarget navControlling) {
+ @Nullable InsetsControlTarget fakeTopControlling,
+ @Nullable InsetsControlTarget navControlling,
+ @Nullable InsetsControlTarget fakeNavControlling) {
onControlChanged(TYPE_TOP_BAR, topControlling);
onControlChanged(TYPE_NAVIGATION_BAR, navControlling);
+ onControlFakeTargetChanged(TYPE_TOP_BAR, fakeTopControlling);
+ onControlFakeTargetChanged(TYPE_NAVIGATION_BAR, fakeNavControlling);
notifyPendingInsetsControlChanged();
}
@@ -279,7 +294,7 @@ class InsetsStateController {
});
}
- private void notifyInsetsChanged() {
+ void notifyInsetsChanged() {
mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b047d8f8a7b9..06e7d665bb42 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -465,7 +465,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
final WindowState windowState = mService.windowForClientLocked(this, window,
false /* throwOnError */);
if (windowState != null) {
- windowState.getDisplayContent().getInsetsStateController().onInsetsModified(
+ windowState.setClientInsetsState(state);
+ windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
windowState, state);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2dd6d0aaba5b..e90f3da96409 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1663,7 +1663,7 @@ public class WindowManagerService extends IWindowManager.Stub
outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
}
- outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
+ outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -2356,7 +2356,7 @@ public class WindowManagerService extends IWindowManager.Stub
outStableInsets, outOutsets);
outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
- outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
+ outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
if (DEBUG) {
Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth
@@ -5574,6 +5574,20 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public void hideTransientBars(int displayId) {
+ mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.STATUS_BAR,
+ "hideTransientBars()");
+ synchronized (mGlobalLock) {
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent != null) {
+ displayContent.hideTransientBars();
+ } else {
+ Slog.w(TAG, "hideTransientBars with invalid displayId=" + displayId);
+ }
+ }
+ }
+
+ @Override
public void setForceShowSystemBars(boolean show) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c25a71d71175..b9cf29ad7790 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -31,6 +31,7 @@ import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
@@ -191,6 +192,7 @@ import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
+import android.view.InsetsState;
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -633,11 +635,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
private boolean mIsDimming = false;
- private @Nullable InsetsSourceProvider mInsetProvider;
+ private @Nullable InsetsSourceProvider mControllableInsetProvider;
+ private InsetsState mClientInsetsState = new InsetsState();
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
private KeyInterceptionInfo mKeyInterceptionInfo;
+ InsetsState getClientInsetsState() {
+ return mClientInsetsState;
+ }
+
+ void setClientInsetsState(InsetsState state) {
+ mClientInsetsState = state;
+ }
+
void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@Rotation int rotation, boolean requested) {
// Invisible windows and the wallpaper do not participate in the seamless rotation animation
@@ -1493,7 +1504,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy()
// If we don't have a provider, this window isn't used as a window generating
// insets, so nobody can hide it over the inset APIs.
- && (mInsetProvider == null || mInsetProvider.isClientVisible());
+ && (mControllableInsetProvider == null
+ || mControllableInsetProvider.isClientVisible());
}
/**
@@ -3351,7 +3363,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void notifyInsetsChanged() {
try {
mClient.insetsChanged(
- getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
+ getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change", e);
}
@@ -3361,8 +3373,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
public void notifyInsetsControlChanged() {
final InsetsStateController stateController =
getDisplayContent().getInsetsStateController();
+ final InsetsPolicy policy = getDisplayContent().getInsetsPolicy();
try {
- mClient.insetsControlChanged(stateController.getInsetsForDispatch(this),
+ mClient.insetsControlChanged(policy.getInsetsForDispatch(this),
stateController.getControlsForDispatch(this));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change", e);
@@ -3387,6 +3400,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
+ @Override
+ public boolean canShowTransient() {
+ return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
+ }
+
Rect getBackdropFrame(Rect frame) {
// When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
// start even if we haven't received the relayout window, so that the client requests
@@ -4815,7 +4833,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void startAnimation(Animation anim) {
// If we are an inset provider, all our animations are driven by the inset client.
- if (mInsetProvider != null && mInsetProvider.isControllable()) {
+ if (mControllableInsetProvider != null) {
return;
}
@@ -4835,7 +4853,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private void startMoveAnimation(int left, int top) {
// If we are an inset provider, all our animations are driven by the inset client.
- if (mInsetProvider != null && mInsetProvider.isControllable()) {
+ if (mControllableInsetProvider != null) {
return;
}
@@ -5319,12 +5337,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWindowFrames.setContentChanged(false);
}
- void setInsetProvider(InsetsSourceProvider insetProvider) {
- mInsetProvider = insetProvider;
+ /**
+ * Set's an {@link InsetsSourceProvider} to be associated with this window, but only if the
+ * provider itself is controllable, as one window can be the provider of more than one inset
+ * type (i.e. gesture insets). If this window is controllable, all its animations must be
+ * controlled by its control target, and the visibility of this window should be taken account
+ * into the state of the control target.
+ *
+ * @param insetProvider the provider which should not be visible to the client.
+ * @see InsetsStateController#getInsetsForDispatch(WindowState)
+ */
+ void setControllableInsetProvider(InsetsSourceProvider insetProvider) {
+ mControllableInsetProvider = insetProvider;
}
- InsetsSourceProvider getInsetProvider() {
- return mInsetProvider;
+ InsetsSourceProvider getControllableInsetProvider() {
+ return mControllableInsetProvider;
}
private final class MoveAnimationSpec implements AnimationSpec {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index f3a8e1a0bd5e..8c2ae5a7659a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -32,7 +33,9 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import android.platform.test.annotations.Presubmit;
+import android.util.IntArray;
import android.view.InsetsSourceControl;
+import android.view.InsetsState;
import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
@@ -151,6 +154,91 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertEquals(1, controls.length);
}
+ @Test
+ public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
+ addWindow(TYPE_STATUS_BAR, "topBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+ final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ policy.updateBarControlTarget(app);
+ policy.showTransient(
+ IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+ final InsetsSourceControl[] controls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+ // The app must get both fake controls.
+ assertEquals(2, controls.length);
+ for (int i = controls.length - 1; i >= 0; i--) {
+ assertNull(controls[i].getLeash());
+ }
+ }
+
+ @Test
+ public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+ addWindow(TYPE_STATUS_BAR, "topBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ .getControllableInsetProvider().getSource().setVisible(true);
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+ final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ policy.updateBarControlTarget(app);
+ policy.showTransient(
+ IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+ final InsetsSourceControl[] controls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+ // The app must get the fake control of the top bar, and must get the real control of the
+ // navigation bar.
+ assertEquals(2, controls.length);
+ for (int i = controls.length - 1; i >= 0; i--) {
+ final InsetsSourceControl control = controls[i];
+ if (control.getType() == TYPE_TOP_BAR) {
+ assertNull(controls[i].getLeash());
+ } else {
+ assertNotNull(controls[i].getLeash());
+ }
+ }
+ }
+
+ @Test
+ public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
+ addWindow(TYPE_STATUS_BAR, "topBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ addWindow(TYPE_NAVIGATION_BAR, "navBar")
+ .getControllableInsetProvider().getSource().setVisible(false);
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+ final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+ policy.updateBarControlTarget(app);
+ policy.showTransient(
+ IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+ InsetsSourceControl[] controls =
+ mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+ // The app must get both fake controls.
+ assertEquals(2, controls.length);
+ for (int i = controls.length - 1; i >= 0; i--) {
+ assertNull(controls[i].getLeash());
+ }
+
+ final InsetsState state = policy.getInsetsForDispatch(app);
+ state.setSourceVisible(TYPE_TOP_BAR, true);
+ state.setSourceVisible(InsetsState.TYPE_NAVIGATION_BAR, true);
+ policy.onInsetsModified(app, state);
+
+ controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+ // The app must get both real controls.
+ assertEquals(2, controls.length);
+ for (int i = controls.length - 1; i >= 0; i--) {
+ assertNotNull(controls[i].getLeash());
+ }
+ }
+
private WindowState addWindow(int type, String name) {
final WindowState win = createWindow(null, type, name);
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 81ea32bb4f73..011161b4f063 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -66,7 +66,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
- topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
+ topBar.setControllableInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
assertNotNull(getController().getInsetsForDispatch(app).getSource(TYPE_TOP_BAR));
}
@@ -75,7 +75,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
.setWindow(topBar, null);
- topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
+ topBar.setControllableInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
final InsetsState state = getController().getInsetsForDispatch(topBar);
for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
final InsetsSource source = state.sourceAt(i);
@@ -101,7 +101,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
getController().getSourceProvider(TYPE_NAVIGATION_BAR).setWindow(navBar, null);
- getController().onBarControlTargetChanged(app, app);
+ getController().onBarControlTargetChanged(app, null, app, null);
InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
assertEquals(2, controls.length);
}
@@ -111,9 +111,9 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
- getController().onBarControlTargetChanged(app, null);
+ getController().onBarControlTargetChanged(app, null, null, null);
assertNotNull(getController().getControlsForDispatch(app));
- getController().onBarControlTargetChanged(null, null);
+ getController().onBarControlTargetChanged(null, null, null, null);
assertNull(getController().getControlsForDispatch(app));
}
@@ -123,7 +123,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
- getController().onBarControlTargetChanged(app, null);
+ getController().onBarControlTargetChanged(app, null, null, null);
assertNotNull(getController().getControlsForDispatch(app));
topBar.cancelAnimation();
assertNull(getController().getControlsForDispatch(app));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 1a4562b69bd4..98d73bacffb3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -397,14 +397,15 @@ public class WindowStateTests extends WindowTestsBase {
}
@Test
- public void testVisibleWithInsetsProvider() throws Exception {
+ public void testVisibleWithInsetsProvider() {
final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
topBar.mHasSurface = true;
assertTrue(topBar.isVisible());
mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
- .setWindow(topBar, null);
- mDisplayContent.getInsetsStateController().onBarControlTargetChanged(app, app);
+ .setWindow(topBar, null /* frameProvider */);
+ mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
+ app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
.onInsetsModified(app, new InsetsSource(TYPE_TOP_BAR));
waitUntilHandlersIdle();
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index c9e3404e0f1a..957216e17925 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -41,6 +41,7 @@ public final class FrameworksTestsFilter extends SelectTest {
"android.view.DisplayCutoutTest",
"android.view.InsetsAnimationControlImplTest",
"android.view.InsetsControllerTest",
+ "android.view.InsetsFlagsTest",
"android.view.InsetsSourceTest",
"android.view.InsetsSourceConsumerTest",
"android.view.InsetsStateTest",