Merge "Added systemui controller to control system bars." into rvc-qpr-dev am: 32fe6cf1d6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12013479

Change-Id: I48e0177ec6f428dcf5a57006d2411437cc720912
This commit is contained in:
Jian-Yang Liu
2020-07-09 01:45:49 +00:00
committed by Automerger Merge Worker
22 changed files with 1034 additions and 129 deletions

View File

@@ -34,6 +34,7 @@ package android {
public static final class R.bool { public static final class R.bool {
field public static final int config_assistantOnTopOfDream = 17891333; // 0x1110005 field public static final int config_assistantOnTopOfDream = 17891333; // 0x1110005
field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004 field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004
field public static final int config_remoteInsetsControllerControlsSystemBars = 17891334; // 0x1110006
} }
public static final class R.string { public static final class R.string {

View File

@@ -26,6 +26,13 @@ import android.view.InsetsState;
*/ */
oneway interface IDisplayWindowInsetsController { oneway interface IDisplayWindowInsetsController {
/**
* Called when top focused window changes to determine whether or not to take over insets
* control. Won't be called if config_remoteInsetsControllerControlsSystemBars is false.
* @param packageName: Passes the top package name
*/
void topFocusedWindowChanged(String packageName);
/** /**
* @see IWindow#insetsChanged * @see IWindow#insetsChanged
*/ */

View File

@@ -387,16 +387,6 @@ interface IWindowManager
*/ */
oneway void hideTransientBars(int displayId); 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
* on screen at all times.
*
* @hide
*/
oneway void setForceShowSystemBars(boolean show);
/** /**
* Called by System UI to notify of changes to the visibility of Recents. * Called by System UI to notify of changes to the visibility of Recents.
*/ */

View File

@@ -712,10 +712,17 @@
case, this can be disabled (set to false). --> case, this can be disabled (set to false). -->
<bool name="config_enableCarDockHomeLaunch">true</bool> <bool name="config_enableCarDockHomeLaunch">true</bool>
<!-- Control whether to force the display of System UI Bars at all times regardless of <!-- Control whether to force apps to give up control over the display of system bars at all
System Ui Flags. This can be useful in the Automotive case if there's a requirement for times regardless of System Ui Flags.
a UI element to be on screen at all times. --> In the Automotive case, this is helpful if there's a requirement for an UI element to be on
<bool name="config_forceShowSystemBars">false</bool> screen at all times. Setting this to true also gives System UI the ability to override the
visibility controls for the system through the usage of the
"SYSTEM_BAR_VISIBILITY_OVERRIDE" setting.
Ex: Only setting the config to true will force show system bars for the entire system.
Ex: Setting the config to true and the "SYSTEM_BAR_VISIBILITY_OVERRIDE" setting to
"immersive.status=apps" will force show navigation bar for all apps and force hide status
bar for all apps. -->
<bool name="config_remoteInsetsControllerControlsSystemBars">false</bool>
<!-- HDMI behavior --> <!-- HDMI behavior -->

View File

@@ -3024,6 +3024,8 @@
<!-- @hide @TestApi --> <!-- @hide @TestApi -->
<public type="bool" name="config_assistantOnTopOfDream" id="0x01110005" /> <public type="bool" name="config_assistantOnTopOfDream" id="0x01110005" />
<!-- @hide @TestApi -->
<public type="bool" name="config_remoteInsetsControllerControlsSystemBars" id="0x01110006" />
<!-- =============================================================== <!-- ===============================================================
Resources added in version S of the platform Resources added in version S of the platform

View File

@@ -1670,7 +1670,7 @@
<java-symbol type="bool" name="config_enableCarDockHomeLaunch" /> <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
<java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" /> <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
<java-symbol type="bool" name="config_enableLockScreenRotation" /> <java-symbol type="bool" name="config_enableLockScreenRotation" />
<java-symbol type="bool" name="config_forceShowSystemBars" /> <java-symbol type="bool" name="config_remoteInsetsControllerControlsSystemBars" />
<java-symbol type="bool" name="config_lidControlsScreenLock" /> <java-symbol type="bool" name="config_lidControlsScreenLock" />
<java-symbol type="bool" name="config_lidControlsSleep" /> <java-symbol type="bool" name="config_lidControlsSleep" />
<java-symbol type="bool" name="config_lockDayNightMode" /> <java-symbol type="bool" name="config_lockDayNightMode" />

View File

@@ -67,6 +67,8 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.volume.VolumeDialogComponent; import com.android.systemui.volume.VolumeDialogComponent;
import com.android.systemui.wm.DisplayImeController;
import com.android.systemui.wm.DisplaySystemBarsController;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -97,6 +99,10 @@ public abstract class CarSystemUIModule {
groupManager, configurationController); groupManager, configurationController);
} }
@Binds
abstract DisplayImeController bindDisplayImeController(
DisplaySystemBarsController displaySystemBarsController);
@Singleton @Singleton
@Provides @Provides
@Named(LEAK_REPORT_EMAIL_NAME) @Named(LEAK_REPORT_EMAIL_NAME)

View File

@@ -0,0 +1,250 @@
/*
* Copyright (C) 2020 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.wm;
import android.car.settings.CarSettings;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.Slog;
import android.view.WindowInsets;
import androidx.annotation.VisibleForTesting;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* Util class to load PolicyControl and allow for querying if a package matches immersive filters.
* Similar to {@link com.android.server.wm.PolicyControl}, but separate due to CarSystemUI needing
* to set its own policies for system bar visibilities.
*
* This forces immersive mode behavior for one or both system bars (based on a package
* list).
*
* Control by setting {@link Settings.Global#POLICY_CONTROL_AUTO} to one or more name-value pairs.
* e.g.
* to force immersive mode everywhere:
* "immersive.full=*"
* to force hide status bars for com.package1 but not com.package2:
* "immersive.status=com.package1,-com.package2"
*
* Separate multiple name-value pairs with ':'
* e.g. "immersive.status=com.package:immersive.navigation=*"
*/
public class BarControlPolicy {
private static final String TAG = "BarControlPolicy";
private static final boolean DEBUG = false;
private static final String NAME_IMMERSIVE_FULL = "immersive.full";
private static final String NAME_IMMERSIVE_STATUS = "immersive.status";
private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation";
@VisibleForTesting
static String sSettingValue;
@VisibleForTesting
static Filter sImmersiveStatusFilter;
private static Filter sImmersiveNavigationFilter;
/** Loads values from the POLICY_CONTROL setting to set filters. */
static boolean reloadFromSetting(Context context) {
if (DEBUG) Slog.d(TAG, "reloadFromSetting()");
String value = null;
try {
value = Settings.Global.getStringForUser(context.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
UserHandle.USER_CURRENT);
if (sSettingValue == value || sSettingValue != null && sSettingValue.equals(value)) {
return false;
}
setFilters(value);
sSettingValue = value;
} catch (Throwable t) {
Slog.w(TAG, "Error loading policy control, value=" + value, t);
return false;
}
return true;
}
/** Used in testing to reset BarControlPolicy. */
@VisibleForTesting
static void reset() {
sSettingValue = null;
sImmersiveStatusFilter = null;
sImmersiveNavigationFilter = null;
}
/**
* Registers a content observer to listen to updates to the SYSTEM_BAR_VISIBILITY_OVERRIDE flag.
*/
static void registerContentObserver(Context context, Handler handler, FilterListener listener) {
context.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE), false,
new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange) {
if (reloadFromSetting(context)) {
listener.onFilterUpdated();
}
}
}, UserHandle.USER_ALL);
}
/**
* Returns bar visibilities based on POLICY_CONTROL_AUTO filters and window policies.
* @return int[], where the first value is the inset types that should be shown, and the second
* is the inset types that should be hidden.
*/
@WindowInsets.Type.InsetsType
static int[] getBarVisibilities(String packageName) {
int hideTypes = 0;
int showTypes = 0;
if (matchesStatusFilter(packageName)) {
hideTypes |= WindowInsets.Type.statusBars();
} else {
showTypes |= WindowInsets.Type.statusBars();
}
if (matchesNavigationFilter(packageName)) {
hideTypes |= WindowInsets.Type.navigationBars();
} else {
showTypes |= WindowInsets.Type.navigationBars();
}
return new int[] {showTypes, hideTypes};
}
private static boolean matchesStatusFilter(String packageName) {
return sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(packageName);
}
private static boolean matchesNavigationFilter(String packageName) {
return sImmersiveNavigationFilter != null
&& sImmersiveNavigationFilter.matches(packageName);
}
private static void setFilters(String value) {
if (DEBUG) Slog.d(TAG, "setFilters: " + value);
sImmersiveStatusFilter = null;
sImmersiveNavigationFilter = null;
if (value != null) {
String[] nvps = value.split(":");
for (String nvp : nvps) {
int i = nvp.indexOf('=');
if (i == -1) continue;
String n = nvp.substring(0, i);
String v = nvp.substring(i + 1);
if (n.equals(NAME_IMMERSIVE_FULL)) {
Filter f = Filter.parse(v);
sImmersiveStatusFilter = sImmersiveNavigationFilter = f;
} else if (n.equals(NAME_IMMERSIVE_STATUS)) {
Filter f = Filter.parse(v);
sImmersiveStatusFilter = f;
} else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) {
Filter f = Filter.parse(v);
sImmersiveNavigationFilter = f;
}
}
}
if (DEBUG) {
Slog.d(TAG, "immersiveStatusFilter: " + sImmersiveStatusFilter);
Slog.d(TAG, "immersiveNavigationFilter: " + sImmersiveNavigationFilter);
}
}
private static class Filter {
private static final String ALL = "*";
private final ArraySet<String> mWhitelist;
private final ArraySet<String> mBlacklist;
private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) {
mWhitelist = whitelist;
mBlacklist = blacklist;
}
boolean matches(String packageName) {
if (packageName == null) return false;
if (onBlacklist(packageName)) return false;
return onWhitelist(packageName);
}
private boolean onBlacklist(String packageName) {
return mBlacklist.contains(packageName) || mBlacklist.contains(ALL);
}
private boolean onWhitelist(String packageName) {
return mWhitelist.contains(ALL) || mWhitelist.contains(packageName);
}
void dump(PrintWriter pw) {
pw.print("Filter[");
dump("whitelist", mWhitelist, pw); pw.print(',');
dump("blacklist", mBlacklist, pw); pw.print(']');
}
private void dump(String name, ArraySet<String> set, PrintWriter pw) {
pw.print(name); pw.print("=(");
int n = set.size();
for (int i = 0; i < n; i++) {
if (i > 0) pw.print(',');
pw.print(set.valueAt(i));
}
pw.print(')');
}
@Override
public String toString() {
StringWriter sw = new StringWriter();
dump(new PrintWriter(sw, true));
return sw.toString();
}
// value = comma-delimited list of tokens, where token = (package name|*)
// e.g. "com.package1", or "com.android.systemui, com.android.keyguard" or "*"
static Filter parse(String value) {
if (value == null) return null;
ArraySet<String> whitelist = new ArraySet<String>();
ArraySet<String> blacklist = new ArraySet<String>();
for (String token : value.split(",")) {
token = token.trim();
if (token.startsWith("-") && token.length() > 1) {
token = token.substring(1);
blacklist.add(token);
} else {
whitelist.add(token);
}
}
return new Filter(whitelist, blacklist);
}
}
/**
* Interface to listen for updates to the filter triggered by the content observer listening to
* the SYSTEM_BAR_VISIBILITY_OVERRIDE flag.
*/
interface FilterListener {
/** Callback triggered when the content observer updates the filter. */
void onFilterUpdated();
}
private BarControlPolicy() {}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2020 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.wm;
import android.os.Handler;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.IDisplayWindowInsetsController;
import android.view.InsetsController;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.WindowInsets;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.TransactionPool;
import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Controller that maps between displays and {@link IDisplayWindowInsetsController} in order to
* give system bar control to SystemUI.
* {@link R.bool#config_remoteInsetsControllerControlsSystemBars} determines whether this controller
* takes control or not.
*/
@Singleton
public class DisplaySystemBarsController extends DisplayImeController {
private static final String TAG = "DisplaySystemBarsController";
private SparseArray<PerDisplay> mPerDisplaySparseArray;
@Inject
public DisplaySystemBarsController(
SystemWindows syswin,
DisplayController displayController,
@Main Handler mainHandler,
TransactionPool transactionPool) {
super(syswin, displayController, mainHandler, transactionPool);
}
@Override
public void onDisplayAdded(int displayId) {
PerDisplay pd = new PerDisplay(displayId);
try {
mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to set insets controller on display " + displayId);
}
// Lazy loading policy control filters instead of during boot.
if (mPerDisplaySparseArray == null) {
mPerDisplaySparseArray = new SparseArray<>();
BarControlPolicy.reloadFromSetting(mSystemWindows.mContext);
BarControlPolicy.registerContentObserver(mSystemWindows.mContext, mHandler, () -> {
int size = mPerDisplaySparseArray.size();
for (int i = 0; i < size; i++) {
mPerDisplaySparseArray.valueAt(i).modifyDisplayWindowInsets();
}
});
}
mPerDisplaySparseArray.put(displayId, pd);
}
@Override
public void onDisplayRemoved(int displayId) {
try {
mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to remove insets controller on display " + displayId);
}
mPerDisplaySparseArray.remove(displayId);
}
@VisibleForTesting
class PerDisplay extends IDisplayWindowInsetsController.Stub {
int mDisplayId;
InsetsController mInsetsController;
InsetsState mInsetsState = new InsetsState();
String mPackageName;
PerDisplay(int displayId) {
mDisplayId = displayId;
mInsetsController = new InsetsController(
new DisplaySystemBarsInsetsControllerHost(mHandler, this));
}
@Override
public void insetsChanged(InsetsState insetsState) {
if (mInsetsState.equals(insetsState)) {
return;
}
mInsetsState.set(insetsState, true /* copySources */);
mInsetsController.onStateChanged(insetsState);
if (mPackageName != null) {
modifyDisplayWindowInsets();
}
}
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
mInsetsController.onControlsChanged(activeControls);
}
@Override
public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
mInsetsController.hide(types);
}
@Override
public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
mInsetsController.show(types);
}
@Override
public void topFocusedWindowChanged(String packageName) {
// If both package names are null or both package names are equal, return.
if (mPackageName == packageName
|| (mPackageName != null && mPackageName.equals(packageName))) {
return;
}
mPackageName = packageName;
modifyDisplayWindowInsets();
}
private void modifyDisplayWindowInsets() {
if (mPackageName == null) {
return;
}
int[] barVisibilities = BarControlPolicy.getBarVisibilities(mPackageName);
updateInsetsState(barVisibilities[0], /* visible= */ true);
updateInsetsState(barVisibilities[1], /* visible= */ false);
showInsets(barVisibilities[0], /* fromIme= */ false);
hideInsets(barVisibilities[1], /* fromIme= */ false);
try {
mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to update window manager service.");
}
}
private void updateInsetsState(@WindowInsets.Type.InsetsType int types, boolean visible) {
ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
for (int i = internalTypes.size() - 1; i >= 0; i--) {
mInsetsState.getSource(internalTypes.valueAt(i)).setVisible(visible);
}
}
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2020 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.wm;
import android.annotation.NonNull;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.IDisplayWindowInsetsController;
import android.view.InsetsController;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
import java.util.List;
/**
* Implements {@link InsetsController.Host} for usage by
* {@link DisplaySystemBarsController.PerDisplay} instances in {@link DisplaySystemBarsController}.
* @hide
*/
public class DisplaySystemBarsInsetsControllerHost implements InsetsController.Host {
private static final String TAG = DisplaySystemBarsInsetsControllerHost.class.getSimpleName();
private final Handler mHandler;
private final IDisplayWindowInsetsController mController;
private final float[] mTmpFloat9 = new float[9];
public DisplaySystemBarsInsetsControllerHost(
Handler handler, IDisplayWindowInsetsController controller) {
mHandler = handler;
mController = controller;
}
@Override
public Handler getHandler() {
return mHandler;
}
@Override
public void notifyInsetsChanged() {
// no-op
}
@Override
public void dispatchWindowInsetsAnimationPrepare(@NonNull WindowInsetsAnimation animation) {
// no-op
}
@Override
public WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart(
@NonNull WindowInsetsAnimation animation,
@NonNull WindowInsetsAnimation.Bounds bounds) {
return null;
}
@Override
public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
@NonNull List<WindowInsetsAnimation> runningAnimations) {
return null;
}
@Override
public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
// no-op
}
@Override
public void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
for (int i = params.length - 1; i >= 0; i--) {
SyncRtSurfaceTransactionApplier.applyParams(
new SurfaceControl.Transaction(), params[i], mTmpFloat9);
}
}
@Override
public void updateCompatSysUiVisibility(
@InsetsState.InternalInsetsType int type, boolean visible, boolean hasControl) {
// no-op
}
@Override
public void onInsetsModified(InsetsState insetsState) {
try {
mController.insetsChanged(insetsState);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send insets to controller");
}
}
@Override
public boolean hasAnimationCallbacks() {
return false;
}
@Override
public void setSystemBarsAppearance(
@WindowInsetsController.Appearance int appearance,
@WindowInsetsController.Appearance int mask) {
// no-op
}
@Override
public @WindowInsetsController.Appearance int getSystemBarsAppearance() {
return 0;
}
@Override
public void setSystemBarsBehavior(@WindowInsetsController.Behavior int behavior) {
// no-op
}
@Override
public @WindowInsetsController.Behavior int getSystemBarsBehavior() {
return 0;
}
@Override
public void releaseSurfaceControlFromRt(SurfaceControl surfaceControl) {
surfaceControl.release();
}
@Override
public void addOnPreDrawRunnable(Runnable r) {
mHandler.post(r);
}
@Override
public void postInsetsAnimationCallback(Runnable r) {
mHandler.post(r);
}
@Override
public InputMethodManager getInputMethodManager() {
return null;
}
@Override
public String getRootViewTitle() {
return null;
}
@Override
public int dipToPx(int dips) {
return 0;
}
@Override
public IBinder getWindowToken() {
return null;
}
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (C) 2020 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.wm;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static com.google.common.truth.Truth.assertThat;
import android.car.settings.CarSettings;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class BarControlPolicyTest extends SysuiTestCase {
private static final String PACKAGE_NAME = "sample.app";
@Before
public void setUp() {
BarControlPolicy.reset();
}
@After
public void tearDown() {
Settings.Global.clearProviderForTest();
}
@Test
public void reloadFromSetting_notSet_doesNotSetFilters() {
BarControlPolicy.reloadFromSetting(mContext);
assertThat(BarControlPolicy.sImmersiveStatusFilter).isNull();
}
@Test
public void reloadFromSetting_invalidPolicyControlString_doesNotSetFilters() {
String text = "sample text";
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
text
);
BarControlPolicy.reloadFromSetting(mContext);
assertThat(BarControlPolicy.sImmersiveStatusFilter).isNull();
}
@Test
public void reloadFromSetting_validPolicyControlString_setsFilters() {
String text = "immersive.status=" + PACKAGE_NAME;
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
text
);
BarControlPolicy.reloadFromSetting(mContext);
assertThat(BarControlPolicy.sImmersiveStatusFilter).isNotNull();
}
@Test
public void reloadFromSetting_filtersSet_doesNotSetFiltersAgain() {
String text = "immersive.status=" + PACKAGE_NAME;
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
text
);
BarControlPolicy.reloadFromSetting(mContext);
assertThat(BarControlPolicy.reloadFromSetting(mContext)).isFalse();
}
@Test
public void getBarVisibilities_policyControlNotSet_showsSystemBars() {
int[] visibilities = BarControlPolicy.getBarVisibilities(PACKAGE_NAME);
assertThat(visibilities[0]).isEqualTo(statusBars() | navigationBars());
assertThat(visibilities[1]).isEqualTo(0);
}
@Test
public void getBarVisibilities_immersiveStatusForAppAndMatchingApp_hidesStatusBar() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.status=" + PACKAGE_NAME);
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities(PACKAGE_NAME);
assertThat(visibilities[0]).isEqualTo(navigationBars());
assertThat(visibilities[1]).isEqualTo(statusBars());
}
@Test
public void getBarVisibilities_immersiveStatusForAppAndNonMatchingApp_showsSystemBars() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.status=" + PACKAGE_NAME);
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities("sample2.app");
assertThat(visibilities[0]).isEqualTo(statusBars() | navigationBars());
assertThat(visibilities[1]).isEqualTo(0);
}
@Test
public void getBarVisibilities_immersiveStatusForAppsAndNonApp_showsSystemBars() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.status=apps");
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities(PACKAGE_NAME);
assertThat(visibilities[0]).isEqualTo(statusBars() | navigationBars());
assertThat(visibilities[1]).isEqualTo(0);
}
@Test
public void getBarVisibilities_immersiveFullForAppAndMatchingApp_hidesSystemBars() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.full=" + PACKAGE_NAME);
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities(PACKAGE_NAME);
assertThat(visibilities[0]).isEqualTo(0);
assertThat(visibilities[1]).isEqualTo(statusBars() | navigationBars());
}
@Test
public void getBarVisibilities_immersiveFullForAppAndNonMatchingApp_showsSystemBars() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.full=" + PACKAGE_NAME);
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities("sample2.app");
assertThat(visibilities[0]).isEqualTo(statusBars() | navigationBars());
assertThat(visibilities[1]).isEqualTo(0);
}
@Test
public void getBarVisibilities_immersiveFullForAppsAndNonApp_showsSystemBars() {
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
"immersive.full=apps");
BarControlPolicy.reloadFromSetting(mContext);
int[] visibilities = BarControlPolicy.getBarVisibilities(PACKAGE_NAME);
assertThat(visibilities[0]).isEqualTo(statusBars() | navigationBars());
assertThat(visibilities[1]).isEqualTo(0);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2020 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.wm;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import android.car.settings.CarSettings;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.IWindowManager;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.TransactionPool;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class DisplaySystemBarsControllerTest extends SysuiTestCase {
private DisplaySystemBarsController mController;
private static final int DISPLAY_ID = 1;
@Mock
private SystemWindows mSystemWindows;
@Mock
private IWindowManager mIWindowManager;
@Mock
private DisplayController mDisplayController;
@Mock
private Handler mHandler;
@Mock
private TransactionPool mTransactionPool;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mSystemWindows.mContext = mContext;
mSystemWindows.mWmService = mIWindowManager;
mController = new DisplaySystemBarsController(
mSystemWindows,
mDisplayController,
mHandler,
mTransactionPool
);
}
@Test
public void onDisplayAdded_setsDisplayWindowInsetsControllerOnWMService()
throws RemoteException {
mController.onDisplayAdded(DISPLAY_ID);
verify(mIWindowManager).setDisplayWindowInsetsController(
eq(DISPLAY_ID), any(DisplaySystemBarsController.PerDisplay.class));
}
@Test
public void onDisplayAdded_loadsBarControlPolicyFilters() {
String text = "sample text";
Settings.Global.putString(
mContext.getContentResolver(),
CarSettings.Global.SYSTEM_BAR_VISIBILITY_OVERRIDE,
text
);
mController.onDisplayAdded(DISPLAY_ID);
assertThat(BarControlPolicy.sSettingValue).isEqualTo(text);
}
@Test
public void onDisplayRemoved_unsetsDisplayWindowInsetsControllerInWMService()
throws RemoteException {
mController.onDisplayAdded(DISPLAY_ID);
mController.onDisplayRemoved(DISPLAY_ID);
verify(mIWindowManager).setDisplayWindowInsetsController(
DISPLAY_ID, /* displayWindowInsetsController= */ null);
}
}

View File

@@ -251,6 +251,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */)); mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */));
} }
@Override
public void topFocusedWindowChanged(String packageName) {
// no-op
}
/** /**
* Sends the local visibility state back to window manager. Needed for legacy adjustForIme. * Sends the local visibility state back to window manager. Needed for legacy adjustForIme.
*/ */

View File

@@ -5760,6 +5760,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mRemoteInsetsController = controller; mRemoteInsetsController = controller;
} }
/**
* Notifies the remote insets controller that the top focused window has changed.
*
* @param packageName The name of the package that is open in the top focused window.
*/
void topFocusedWindowChanged(String packageName) {
try {
mRemoteInsetsController.topFocusedWindowChanged(packageName);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver package in top focused window change", e);
}
}
void notifyInsetsChanged() { void notifyInsetsChanged() {
try { try {
mRemoteInsetsController.insetsChanged( mRemoteInsetsController.insetsChanged(

View File

@@ -386,11 +386,6 @@ public class DisplayPolicy {
private int mForcingShowNavBarLayer; private int mForcingShowNavBarLayer;
private boolean mForceShowSystemBars; private boolean mForceShowSystemBars;
/**
* Force the display of system bars regardless of other settings.
*/
private boolean mForceShowSystemBarsFromExternal;
private boolean mShowingDream; private boolean mShowingDream;
private boolean mLastShowingDream; private boolean mLastShowingDream;
private boolean mDreamingLockscreen; private boolean mDreamingLockscreen;
@@ -480,7 +475,6 @@ public class DisplayPolicy {
final Resources r = mContext.getResources(); final Resources r = mContext.getResources();
mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer); mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
mAccessibilityManager = (AccessibilityManager) mContext.getSystemService( mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
Context.ACCESSIBILITY_SERVICE); Context.ACCESSIBILITY_SERVICE);
@@ -698,17 +692,6 @@ public class DisplayPolicy {
return mDockMode; return mDockMode;
} }
/**
* @see WindowManagerService.setForceShowSystemBars
*/
void setForceShowSystemBars(boolean forceShowSystemBars) {
mForceShowSystemBarsFromExternal = forceShowSystemBars;
}
boolean getForceShowSystemBars() {
return mForceShowSystemBarsFromExternal;
}
public boolean hasNavigationBar() { public boolean hasNavigationBar() {
return mHasNavigationBar; return mHasNavigationBar;
} }
@@ -3540,8 +3523,7 @@ public class DisplayPolicy {
// We need to force system bars when the docked stack is visible, when the freeform stack // We need to force system bars when the docked stack is visible, when the freeform stack
// is focused but also when we are resizing for the transitions when docked stack // is focused but also when we are resizing for the transitions when docked stack
// visibility changes. // visibility changes.
mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing;
|| mForceShowSystemBarsFromExternal;
final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing(); final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing();
// apply translucent bar vis flags // apply translucent bar vis flags
@@ -3916,8 +3898,8 @@ public class DisplayPolicy {
} }
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal="); pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars");
pw.print(mForceShowSystemBarsFromExternal); pw.print(mDisplayContent.getInsetsPolicy().getRemoteInsetsControllerControlsSystemBars());
pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
mStatusBarController.dump(pw, prefix); mStatusBarController.dump(pw, prefix);
mNavigationBarController.dump(pw, prefix); mNavigationBarController.dump(pw, prefix);

View File

@@ -46,7 +46,9 @@ import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation; import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds; import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowInsetsAnimationControlListener; import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.DisplayThread; import com.android.server.DisplayThread;
@@ -97,12 +99,31 @@ class InsetsPolicy {
private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
private boolean mAnimatingShown; private boolean mAnimatingShown;
/**
* Let remote insets controller control system bars regardless of other settings.
*/
private boolean mRemoteInsetsControllerControlsSystemBars;
private final float[] mTmpFloat9 = new float[9]; private final float[] mTmpFloat9 = new float[9];
InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) { InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
mStateController = stateController; mStateController = stateController;
mDisplayContent = displayContent; mDisplayContent = displayContent;
mPolicy = displayContent.getDisplayPolicy(); mPolicy = displayContent.getDisplayPolicy();
mRemoteInsetsControllerControlsSystemBars = mPolicy.getContext().getResources().getBoolean(
R.bool.config_remoteInsetsControllerControlsSystemBars);
}
boolean getRemoteInsetsControllerControlsSystemBars() {
return mRemoteInsetsControllerControlsSystemBars;
}
/**
* Used only for testing.
*/
@VisibleForTesting
void setRemoteInsetsControllerControlsSystemBars(boolean controlsSystemBars) {
mRemoteInsetsControllerControlsSystemBars = controlsSystemBars;
} }
/** Updates the target which can control system bars. */ /** Updates the target which can control system bars. */
@@ -256,6 +277,11 @@ class InsetsPolicy {
// Notification shade has control anyways, no reason to force anything. // Notification shade has control anyways, no reason to force anything.
return focusedWin; return focusedWin;
} }
if (remoteInsetsControllerControlsSystemBars(focusedWin)) {
mDisplayContent.mRemoteInsetsControlTarget.topFocusedWindowChanged(
focusedWin.mAttrs.packageName);
return mDisplayContent.mRemoteInsetsControlTarget;
}
if (forceShowsSystemBarsForWindowingMode) { if (forceShowsSystemBarsForWindowingMode) {
// Status bar is forcibly shown for the windowing mode which is a steady state. // Status bar is forcibly shown for the windowing mode which is a steady state.
// We don't want the client to control the status bar, and we will dispatch the real // We don't want the client to control the status bar, and we will dispatch the real
@@ -285,6 +311,11 @@ class InsetsPolicy {
// Notification shade has control anyways, no reason to force anything. // Notification shade has control anyways, no reason to force anything.
return focusedWin; return focusedWin;
} }
if (remoteInsetsControllerControlsSystemBars(focusedWin)) {
mDisplayContent.mRemoteInsetsControlTarget.topFocusedWindowChanged(
focusedWin.mAttrs.packageName);
return mDisplayContent.mRemoteInsetsControlTarget;
}
if (forceShowsSystemBarsForWindowingMode) { if (forceShowsSystemBarsForWindowingMode) {
// Navigation bar is forcibly shown for the windowing mode which is a steady state. // Navigation bar is forcibly shown for the windowing mode which is a steady state.
// We don't want the client to control the navigation bar, and we will dispatch the real // We don't want the client to control the navigation bar, and we will dispatch the real
@@ -300,6 +331,28 @@ class InsetsPolicy {
return focusedWin; return focusedWin;
} }
/**
* Determines whether the remote insets controller should take control of system bars for all
* windows.
*/
boolean remoteInsetsControllerControlsSystemBars(@Nullable WindowState focusedWin) {
if (focusedWin == null) {
return false;
}
if (!mRemoteInsetsControllerControlsSystemBars) {
return false;
}
if (mDisplayContent == null || mDisplayContent.mRemoteInsetsControlTarget == null) {
// No remote insets control target to take control of insets.
return false;
}
// If necessary, auto can control application windows when
// config_remoteInsetsControllerControlsSystemBars is set to true. This is useful in cases
// where we want to dictate system bar inset state for applications.
return focusedWin.getAttrs().type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& focusedWin.getAttrs().type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
}
private boolean forceShowsStatusBarTransiently() { private boolean forceShowsStatusBarTransiently() {
final WindowState win = mPolicy.getStatusBar(); final WindowState win = mPolicy.getStatusBar();
return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
@@ -321,10 +374,7 @@ class InsetsPolicy {
// We need to force system bars when the docked stack is visible, when the freeform stack // We need to force system bars when the docked stack is visible, when the freeform stack
// is visible but also when we are resizing for the transitions when docked stack // is visible but also when we are resizing for the transitions when docked stack
// visibility changes. // visibility changes.
return isDockedStackVisible return isDockedStackVisible || isFreeformStackVisible || isResizing;
|| isFreeformStackVisible
|| isResizing
|| mPolicy.getForceShowSystemBars();
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -5827,27 +5827,6 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
@Override
public void setForceShowSystemBars(boolean show) {
boolean isAutomotive = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
if (!isAutomotive) {
throw new UnsupportedOperationException("Force showing system bars is only supported"
+ "for Automotive use cases.");
}
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller does not hold permission "
+ android.Manifest.permission.STATUS_BAR);
}
synchronized (mGlobalLock) {
final PooledConsumer c = PooledLambda.obtainConsumer(
DisplayPolicy::setForceShowSystemBars, PooledLambda.__(), show);
mRoot.forAllDisplayPolicies(c);
c.recycle();
}
}
public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) { public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
!= PackageManager.PERMISSION_GRANTED) { != PackageManager.PERMISSION_GRANTED) {

View File

@@ -96,13 +96,10 @@ import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.DisplayCutout; import android.view.DisplayCutout;
import android.view.Gravity; import android.view.Gravity;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowRotationCallback; import android.view.IDisplayWindowRotationCallback;
import android.view.IDisplayWindowRotationController; import android.view.IDisplayWindowRotationController;
import android.view.ISystemGestureExclusionListener; import android.view.ISystemGestureExclusionListener;
import android.view.IWindowManager; import android.view.IWindowManager;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceControl.Transaction; import android.view.SurfaceControl.Transaction;
@@ -918,28 +915,6 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget()); assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
} }
private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
return new IDisplayWindowInsetsController.Stub() {
@Override
public void insetsChanged(InsetsState insetsState) throws RemoteException {
}
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] insetsSourceControls) throws RemoteException {
}
@Override
public void showInsets(int i, boolean b) throws RemoteException {
}
@Override
public void hideInsets(int i, boolean b) throws RemoteException {
}
};
}
@Test @Test
public void testUpdateSystemGestureExclusion() throws Exception { public void testUpdateSystemGestureExclusion() throws Exception {
final DisplayContent dc = createNewDisplay(); final DisplayContent dc = createNewDisplay();

View File

@@ -67,7 +67,6 @@ import android.view.WindowManager;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.WmDisplayCutout; import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before; import org.junit.Before;
@@ -806,27 +805,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
new ToStringComparatorWrapper<>(simulatedInsetsState)); new ToStringComparatorWrapper<>(simulatedInsetsState));
} }
@Test
public void forceShowSystemBars_clearsSystemUIFlags() {
mDisplayPolicy.mLastSystemUiFlags |= SYSTEM_UI_FLAG_FULLSCREEN;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mSystemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN;
mDisplayPolicy.setForceShowSystemBars(true);
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
// triggers updateSystemUiVisibilityLw which will reset the flags as needed
int finishPostLayoutPolicyLw = mDisplayPolicy.focusChangedLw(mWindow, mWindow);
assertEquals(WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT, finishPostLayoutPolicyLw);
assertEquals(0, mDisplayPolicy.mLastSystemUiFlags);
assertEquals(0, mWindow.mAttrs.systemUiVisibility);
assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
}
@Test @Test
public void testScreenDecorWindows() { public void testScreenDecorWindows() {
final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow"); final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow");

View File

@@ -172,8 +172,9 @@ public class InsetsPolicyTest extends WindowTestsBase {
} }
@Test @Test
public void testControlsForDispatch_forceShowSystemBarsFromExternal_appHasNoControl() { public void testControlsForDispatch_remoteInsetsControllerControlsBars_appHasNoControl() {
mDisplayContent.getDisplayPolicy().setForceShowSystemBars(true); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(true);
addWindow(TYPE_STATUS_BAR, "statusBar"); addWindow(TYPE_STATUS_BAR, "statusBar");
addWindow(TYPE_NAVIGATION_BAR, "navBar"); addWindow(TYPE_NAVIGATION_BAR, "navBar");

View File

@@ -60,24 +60,6 @@ public class WindowManagerServiceTests extends WindowTestsBase {
@Rule @Rule
public ExpectedException mExpectedException = ExpectedException.none(); public ExpectedException mExpectedException = ExpectedException.none();
@Test
public void testForceShowSystemBarsThrowsExceptionForNonAutomotive() {
if (!isAutomotive()) {
mExpectedException.expect(UnsupportedOperationException.class);
mWm.setForceShowSystemBars(true);
}
}
@Test
public void testForceShowSystemBarsDoesNotThrowExceptionForAutomotiveWithStatusBarPermission() {
if (isAutomotive()) {
mExpectedException.none();
mWm.setForceShowSystemBars(true);
}
}
private boolean isAutomotive() { private boolean isAutomotive() {
return getInstrumentation().getTargetContext().getPackageManager().hasSystemFeature( return getInstrumentation().getTargetContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE); PackageManager.FEATURE_AUTOMOTIVE);

View File

@@ -41,11 +41,15 @@ import static org.mockito.Mockito.mock;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log; import android.util.Log;
import android.view.Display; import android.view.Display;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import android.view.IDisplayWindowInsetsController;
import android.view.IWindow; import android.view.IWindow;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.SurfaceControl.Transaction; import android.view.SurfaceControl.Transaction;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@@ -123,7 +127,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
mChildAppWindowBelow = createCommonWindow(mAppWindow, mChildAppWindowBelow = createCommonWindow(mAppWindow,
TYPE_APPLICATION_MEDIA_OVERLAY, TYPE_APPLICATION_MEDIA_OVERLAY,
"mChildAppWindowBelow"); "mChildAppWindowBelow");
mDisplayContent.getDisplayPolicy().setForceShowSystemBars(false); mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(false);
// Adding a display will cause freezing the display. Make sure to wait until it's // Adding a display will cause freezing the display. Make sure to wait until it's
// unfrozen to not run into race conditions with the tests. // unfrozen to not run into race conditions with the tests.
@@ -344,6 +348,32 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createNewDisplay(displayInfo, false /* supportIme */); return createNewDisplay(displayInfo, false /* supportIme */);
} }
IDisplayWindowInsetsController createDisplayWindowInsetsController() {
return new IDisplayWindowInsetsController.Stub() {
@Override
public void insetsChanged(InsetsState insetsState) throws RemoteException {
}
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] insetsSourceControls) throws RemoteException {
}
@Override
public void showInsets(int i, boolean b) throws RemoteException {
}
@Override
public void hideInsets(int i, boolean b) throws RemoteException {
}
@Override
public void topFocusedWindowChanged(String packageName) {
}
};
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */ /** Sets the default minimum task size to 1 so that tests can use small task sizes */
void removeGlobalMinSizeRestriction() { void removeGlobalMinSizeRestriction() {
mWm.mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp = 1; mWm.mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp = 1;