summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyrylo Mikos <kiril.mik.os@gmail.com>2014-11-17 13:56:05 +0200
committerClark Scheff <clark@cyngn.com>2015-11-11 08:12:41 -0800
commitcad38223498ab06b33112039d9b5590092ba2264 (patch)
tree9680ef76fd9911fd5815578831e616d40532397f
parentbb017c0be026101f31ed09c8ccfac48036ca8f0e (diff)
downloadframeworks_base-cad38223498ab06b33112039d9b5590092ba2264.zip
frameworks_base-cad38223498ab06b33112039d9b5590092ba2264.tar.gz
frameworks_base-cad38223498ab06b33112039d9b5590092ba2264.tar.bz2
Squashed commit for expanded desktop
Bringup expanded desktop and implement per-user configuration. Change-Id: I90d834d788b3050a3f4c11dda9b6d1a7d79546cc Create configurable default expanded desktop style. Change-Id: I90c7f8544cda9b91fb9b700fcf146f4e58b15a26
-rw-r--r--core/java/android/provider/Settings.java12
-rw-r--r--core/java/android/view/WindowManager.java17
-rw-r--r--core/java/android/view/WindowManagerPolicy.java2
-rw-r--r--core/java/android/view/WindowManagerPolicyControl.java451
-rw-r--r--services/core/java/com/android/server/policy/BarController.java3
-rw-r--r--services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java3
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java91
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java5
8 files changed, 564 insertions, 20 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index abf89b1..997fb5a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8331,11 +8331,12 @@ public final class Settings {
/**
* Defines global runtime overrides to window policy.
*
- * See {@link com.android.server.policy.PolicyControl} for value format.
+ * See {@link android.view.WindowManagerPolicyControl} for value format.
*
* @hide
*/
public static final String POLICY_CONTROL = "policy_control";
+ public static final String POLICY_CONTROL_SELECTED = "policy_control_selected";
/**
* @hide
@@ -8344,6 +8345,15 @@ public final class Settings {
"zen_disable_ducking_during_media_playback";
/**
+ * Defines global runtime overrides to window policy style.
+ *
+ * See {@link android.view.WindowManagerPolicyControl} for value definitions.
+ *
+ * @hide
+ */
+ public static final String POLICY_CONTROL_STYLE = "policy_control_style";
+
+ /**
* Defines global zen mode. ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
* or ZEN_MODE_NO_INTERRUPTIONS.
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6cb27cc..3ff8844 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1128,6 +1128,23 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000;
/**
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_STATUS_HIDE_FORCED = 0x00800000;
+
+ /**
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_NAV_HIDE_FORCED = 0x01000000;
+
+ /**
+ * The window had not set FULLSCREEN flag so don't handle it as fullscreen in layoutWindowLw
+ *
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_WAS_NOT_FULLSCREEN = 0x02000000;
+
+ /**
* Window flag: Overrides default power key behavior
* {@hide}
*/
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 42cb816..a962f2a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -453,6 +453,8 @@ public interface WindowManagerPolicy {
/** Unregister a system listener for touch events */
void unregisterPointerEventListener(PointerEventListener listener);
+
+ void addSystemUIVisibilityFlag(int flags);
}
public interface PointerEventListener {
diff --git a/core/java/android/view/WindowManagerPolicyControl.java b/core/java/android/view/WindowManagerPolicyControl.java
new file mode 100644
index 0000000..cdba239
--- /dev/null
+++ b/core/java/android/view/WindowManagerPolicyControl.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2014 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 android.app.ActivityManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy.WindowState;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Iterator;
+
+/**
+ * Runtime adjustments applied to the global window policy.
+ *
+ * This includes forcing immersive mode behavior for one or both system bars (based on a package
+ * list) and permanently disabling immersive mode confirmations for specific packages.
+ *
+ * Control by setting {@link Settings.Global.POLICY_CONTROL} to one or more name-value pairs.
+ * e.g.
+ * to force immersive mode everywhere:
+ * "immersive.full=*"
+ * to force transient status for all apps except a specific package:
+ * "immersive.status=apps,-com.package"
+ * to disable the immersive mode confirmations for specific packages:
+ * "immersive.preconfirms=com.package.one,com.package.two"
+ *
+ * Separate multiple name-value pairs with ':'
+ * e.g. "immersive.status=apps:immersive.preconfirms=*"
+ *
+ * @hide
+ */
+public class WindowManagerPolicyControl {
+ private static String TAG = "PolicyControl";
+ private static 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";
+ private static final String NAME_IMMERSIVE_PRECONFIRMATIONS = "immersive.preconfirms";
+
+ private static int sDefaultImmersiveStyle;
+ private static String sSettingValue;
+ private static Filter sImmersivePreconfirmationsFilter;
+ private static Filter sImmersiveStatusFilter;
+ private static Filter sImmersiveNavigationFilter;
+
+ /**
+ * Accessible constants for Settings
+ */
+ public final static class ImmersiveDefaultStyles {
+ public final static int IMMERSIVE_FULL = 0;
+ public final static int IMMERSIVE_STATUS = 1;
+ public final static int IMMERSIVE_NAVIGATION = 2;
+ }
+
+ public static int getSystemUiVisibility(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int vis = win != null ? win.getSystemUiVisibility() : attrs.systemUiVisibility;
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_STATUS)) {
+ vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.STATUS_BAR_TRANSLUCENT);
+ }
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION)) {
+ vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.NAVIGATION_BAR_TRANSLUCENT);
+ }
+ return vis;
+ }
+
+ public static int getWindowFlags(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int flags = attrs.flags;
+
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_STATUS)) {
+ flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ flags &= ~(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ }
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)
+ && (sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_FULL ||
+ sDefaultImmersiveStyle == ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION)) {
+ flags &= ~WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+ }
+ return flags;
+ }
+
+ public static int getPrivateWindowFlags(WindowState win, LayoutParams attrs) {
+ attrs = attrs != null ? attrs : win.getAttrs();
+ int privateFlags = attrs.privateFlags;
+
+ if (sImmersiveStatusFilter != null && sImmersiveNavigationFilter != null &&
+ sImmersiveStatusFilter.isEnabledForAll()
+ && sImmersiveNavigationFilter.isEnabledForAll()) {
+
+ if ((attrs.flags & LayoutParams.FLAG_FULLSCREEN) == 0) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_WAS_NOT_FULLSCREEN;
+ }
+
+ switch (sDefaultImmersiveStyle) {
+ case ImmersiveDefaultStyles.IMMERSIVE_FULL:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ return privateFlags;
+ case ImmersiveDefaultStyles.IMMERSIVE_STATUS:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ return privateFlags;
+ case ImmersiveDefaultStyles.IMMERSIVE_NAVIGATION:
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ return privateFlags;
+ }
+ }
+
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
+ if ((attrs.flags & LayoutParams.FLAG_FULLSCREEN) == 0) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_WAS_NOT_FULLSCREEN;
+ }
+ privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_HIDE_FORCED;
+ }
+
+ if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) {
+ privateFlags |= LayoutParams.PRIVATE_FLAG_NAV_HIDE_FORCED;
+ }
+
+ return privateFlags;
+ }
+
+ public static boolean immersiveStatusFilterMatches(String packageName) {
+ return sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(packageName);
+ }
+
+ public static boolean immersiveNavigationFilterMatches(String packageName) {
+ return sImmersiveNavigationFilter != null
+ && sImmersiveNavigationFilter.matches(packageName);
+ }
+
+ public static int adjustClearableFlags(WindowState win, int clearableFlags) {
+ final LayoutParams attrs = win != null ? win.getAttrs() : null;
+ if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
+ clearableFlags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
+ }
+ return clearableFlags;
+ }
+
+ public static boolean disableImmersiveConfirmation(String pkg) {
+ return (sImmersivePreconfirmationsFilter != null
+ && sImmersivePreconfirmationsFilter.matches(pkg))
+ || ActivityManager.isRunningInTestHarness();
+ }
+
+ public static void reloadFromSetting(Context context) {
+ reloadStyleFromSetting(context, Settings.Global.POLICY_CONTROL_STYLE);
+ reloadFromSetting(context, Settings.Global.POLICY_CONTROL);
+ }
+
+ public static void reloadFromSetting(Context context, String key) {
+ if (DEBUG) Slog.d(TAG, "reloadFromSetting()");
+ String value = null;
+ try {
+ value = Settings.Global.getStringForUser(context.getContentResolver(),
+ key,
+ UserHandle.USER_CURRENT);
+ if (sSettingValue != null && sSettingValue.equals(value)) return;
+ setFilters(value);
+ sSettingValue = value;
+ } catch (Throwable t) {
+ Slog.w(TAG, "Error loading policy control, value=" + value, t);
+ }
+ }
+
+ public static void reloadStyleFromSetting(Context context, String key) {
+ sDefaultImmersiveStyle = Settings.Global.getInt(context.getContentResolver(),
+ key, WindowManagerPolicyControl.ImmersiveDefaultStyles.IMMERSIVE_FULL);
+ if (DEBUG) Slog.d(TAG, "reloadStyleFromSetting " + sDefaultImmersiveStyle);
+ }
+
+ public static void saveToSettings(Context context) {
+ saveToSettings(context, Settings.Global.POLICY_CONTROL);
+ }
+
+ public static void saveToSettings(Context context, String key) {
+ StringBuilder value = new StringBuilder();
+ boolean needSemicolon = false;
+ if (sImmersiveStatusFilter != null) {
+ writeFilter(NAME_IMMERSIVE_STATUS, sImmersiveStatusFilter, value);
+ needSemicolon = true;
+ }
+ if (sImmersiveNavigationFilter != null) {
+ if (needSemicolon) {
+ value.append(":");
+ }
+ writeFilter(NAME_IMMERSIVE_NAVIGATION, sImmersiveNavigationFilter, value);
+ }
+
+ Settings.Global.putString(context.getContentResolver(), key, value.toString());
+ }
+
+ public static void saveStyleToSettings(Context context, int value) {
+ Settings.Global.putInt(context.getContentResolver(),
+ Settings.Global.POLICY_CONTROL_STYLE, value);
+ sDefaultImmersiveStyle = value;
+ }
+
+ public static void addToStatusWhiteList(String packageName) {
+ if (sImmersiveStatusFilter == null) {
+ sImmersiveStatusFilter = new Filter(new ArraySet<String>(), new ArraySet<String>());
+ }
+
+ if (!sImmersiveStatusFilter.mWhitelist.contains(packageName)) {
+ sImmersiveStatusFilter.mWhitelist.add(packageName);
+ }
+ }
+
+ public static void addToNavigationWhiteList(String packageName) {
+ if (sImmersiveNavigationFilter == null) {
+ sImmersiveNavigationFilter = new Filter(new ArraySet<String>(), new ArraySet<String>());
+ }
+
+ if (!sImmersiveNavigationFilter.mWhitelist.contains(packageName)) {
+ sImmersiveNavigationFilter.mWhitelist.add(packageName);
+ }
+ }
+
+ public static void removeFromWhiteLists(String packageName) {
+ if (sImmersiveStatusFilter != null) {
+ sImmersiveStatusFilter.mWhitelist.remove(packageName);
+ }
+ if (sImmersiveNavigationFilter != null) {
+ sImmersiveNavigationFilter.mWhitelist.remove(packageName);
+ }
+ }
+
+ public static ArraySet<String> getWhiteLists() {
+ ArraySet<String> result = new ArraySet<>();
+
+ if (sImmersiveStatusFilter != null) {
+ result.addAll(sImmersiveStatusFilter.mWhitelist);
+ }
+ if (sImmersiveNavigationFilter != null
+ && sImmersiveNavigationFilter != sImmersiveStatusFilter) {
+ result.addAll(sImmersiveNavigationFilter.mWhitelist);
+ }
+
+ return result;
+ }
+
+ private static void writeFilter(String name, Filter filter, StringBuilder stringBuilder) {
+ if (filter.mWhitelist.isEmpty() && filter.mBlacklist.isEmpty()) {
+ return;
+ }
+ stringBuilder.append(name);
+ stringBuilder.append("=");
+
+ boolean needComma = false;
+ if (!filter.mWhitelist.isEmpty()) {
+ writePackages(filter.mWhitelist, stringBuilder, false);
+ needComma = true;
+ }
+ if (!filter.mBlacklist.isEmpty()) {
+ if (needComma) {
+ stringBuilder.append(",");
+ }
+ writePackages(filter.mBlacklist, stringBuilder, true);
+ }
+ }
+
+ private static void writePackages(ArraySet<String> set, StringBuilder stringBuilder,
+ boolean isBlackList) {
+ Iterator<String> iterator = set.iterator();
+ while (iterator.hasNext()) {
+ if (isBlackList) {
+ stringBuilder.append("-");
+ }
+ String name = iterator.next();
+ stringBuilder.append(name);
+ if (iterator.hasNext()) {
+ stringBuilder.append(",");
+ }
+ }
+ }
+
+ public static boolean isImmersiveFiltersActive() {
+ return sImmersiveStatusFilter != null || sImmersiveNavigationFilter != null;
+ }
+
+ public static void dump(String prefix, PrintWriter pw) {
+ dump("sImmersiveStatusFilter", sImmersiveStatusFilter, prefix, pw);
+ dump("sImmersiveNavigationFilter", sImmersiveNavigationFilter, prefix, pw);
+ dump("sImmersivePreconfirmationsFilter", sImmersivePreconfirmationsFilter, prefix, pw);
+ }
+
+ private static void dump(String name, Filter filter, String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("PolicyControl."); pw.print(name); pw.print('=');
+ if (filter == null) {
+ pw.println("null");
+ } else {
+ filter.dump(pw); pw.println();
+ }
+ }
+
+ private static void setFilters(String value) {
+ if (DEBUG) Slog.d(TAG, "setFilters: " + value);
+ sImmersiveStatusFilter = null;
+ sImmersiveNavigationFilter = null;
+ sImmersivePreconfirmationsFilter = 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;
+ if (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = 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 (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = f;
+ }
+ } else if (n.equals(NAME_IMMERSIVE_PRECONFIRMATIONS)) {
+ Filter f = Filter.parse(v);
+ sImmersivePreconfirmationsFilter = f;
+ }
+ }
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "immersiveStatusFilter: " + sImmersiveStatusFilter);
+ Slog.d(TAG, "immersiveNavigationFilter: " + sImmersiveNavigationFilter);
+ Slog.d(TAG, "immersivePreconfirmationsFilter: " + sImmersivePreconfirmationsFilter);
+ }
+ }
+
+ private static class Filter {
+ private static final String ALL = "*";
+ private static final String APPS = "apps";
+
+ private final ArraySet<String> mWhitelist;
+ private final ArraySet<String> mBlacklist;
+
+ private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) {
+ mWhitelist = whitelist;
+ mBlacklist = blacklist;
+ }
+
+ boolean matches(LayoutParams attrs) {
+ if (attrs == null) return false;
+ boolean isApp = attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+ if (isApp && mBlacklist.contains(APPS)) return false;
+ if (onBlacklist(attrs.packageName)) return false;
+ if (isApp && mWhitelist.contains(APPS)) return true;
+ return onWhitelist(attrs.packageName);
+ }
+
+ boolean matches(String packageName) {
+ return !onBlacklist(packageName) && onWhitelist(packageName);
+ }
+
+ public boolean isEnabledForAll() {
+ return mWhitelist.contains(ALL);
+ }
+
+ 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("=(");
+ final 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|apps|*)
+ // e.g. "com.package1", or "apps, 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);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 9095f57..7a20e40 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -26,6 +26,7 @@ import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerPolicy.WindowState;
+import android.view.WindowManagerPolicyControl;
import com.android.internal.statusbar.IStatusBarService;
import java.io.PrintWriter;
@@ -119,7 +120,7 @@ public class BarController {
if (mWin != null) {
if (win != null && (win.getAttrs().privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) {
- int fl = PolicyControl.getWindowFlags(win, null);
+ int fl = WindowManagerPolicyControl.getWindowFlags(win, null);
if ((fl & mTranslucentWmFlag) != 0) {
vis |= mTranslucentFlag;
} else {
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 160d44c..da9312c 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -44,6 +44,7 @@ import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.FrameLayout;
+import android.view.WindowManagerPolicyControl;
import com.android.internal.R;
/**
@@ -116,7 +117,7 @@ public class ImmersiveModeConfirmation {
boolean userSetupComplete) {
mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) {
- final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
+ final boolean disabled = WindowManagerPolicyControl.disableImmersiveConfirmation(pkg);
if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
disabled, mConfirmed));
if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed) && userSetupComplete) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2f15dab..68534ce 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -124,6 +124,7 @@ import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.widget.Toast;
+import android.view.WindowManagerPolicyControl;
import com.android.internal.R;
import com.android.internal.policy.IKeyguardService;
import com.android.internal.statusbar.IStatusBarService;
@@ -526,6 +527,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// fullscreen window flag, these are the stable dimensions without the status bar.
int mStableFullscreenLeft, mStableFullscreenTop;
int mStableFullscreenRight, mStableFullscreenBottom;
+ // For force immersive mode
+ int mForceImmersiveLeft, mForceImmersiveTop;
+ int mForceImmersiveRight, mForceImmersiveBottom;
// During layout, the current screen borders with all outer decoration
// (status bar, input method dock) accounted for.
int mCurLeft, mCurTop, mCurRight, mCurBottom;
@@ -737,6 +741,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mWifiDisplayCustomRotation = -1;
private boolean mHasPermanentMenuKey;
+ private boolean mClearedBecauseOfForceShow;
+ private boolean mTopWindowIsKeyguard;
private class PolicyHandler extends Handler {
@Override
@@ -2239,7 +2245,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
- PolicyControl.reloadFromSetting(mContext);
+ WindowManagerPolicyControl.reloadFromSetting(mContext);
}
if (updateRotation) {
updateRotation(true);
@@ -3999,8 +4005,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void getInsetHintLw(WindowManager.LayoutParams attrs, int displayRotation,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets) {
- final int fl = PolicyControl.getWindowFlags(null, attrs);
- final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(null, attrs);
+ final int sysuiVis = WindowManagerPolicyControl.getSystemUiVisibility(null, attrs);
final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl);
@@ -4119,13 +4125,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth;
mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight;
mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft
- = mCurLeft = mUnrestrictedScreenLeft;
+ = mCurLeft = mForceImmersiveLeft = mUnrestrictedScreenLeft;
mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop
- = mCurTop = mUnrestrictedScreenTop;
+ = mCurTop = mForceImmersiveTop = mUnrestrictedScreenTop;
mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight
- = mCurRight = displayWidth - overscanRight;
+ = mCurRight = mForceImmersiveRight = displayWidth - overscanRight;
mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom
- = mCurBottom = displayHeight - overscanBottom;
+ = mCurBottom = mForceImmersiveBottom = displayHeight - overscanBottom;
mDockLayer = 0x10000000;
mStatusBarLayer = -1;
@@ -4429,6 +4435,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
? attached.getFrameLw() : df);
}
+ private void applyForceImmersiveMode(int pfl, Rect r) {
+ if ((pfl & PRIVATE_FLAG_STATUS_HIDE_FORCED) != 0) {
+ r.top = mForceImmersiveTop;
+ }
+ if ((pfl & PRIVATE_FLAG_NAV_HIDE_FORCED) != 0) {
+ if (mNavigationBarOnBottom) {
+ r.bottom = mForceImmersiveBottom;
+ } else {
+ r.right = mForceImmersiveRight;
+ }
+ }
+ }
+
private void applyStableConstraints(int sysui, int fl, Rect r) {
if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
// If app is requesting a stable layout, don't let the
@@ -4473,9 +4492,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
offsetInputMethodWindowLw(mLastInputMethodWindow);
}
- final int fl = PolicyControl.getWindowFlags(win, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(win, attrs);
+ final int pfl = WindowManagerPolicyControl.getPrivateWindowFlags(win, attrs);
final int sim = attrs.softInputMode;
- final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
+ final int sysUiFl = WindowManagerPolicyControl.getSystemUiVisibility(win, null);
final Rect pf = mTmpParentFrame;
final Rect df = mTmpDisplayFrame;
@@ -4656,7 +4676,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
}
- if ((fl & FLAG_FULLSCREEN) == 0) {
+ if ((fl & FLAG_FULLSCREEN) == 0
+ || (pfl & PRIVATE_FLAG_WAS_NOT_FULLSCREEN) != 0) {
if (win.isVoiceInteraction()) {
cf.left = mVoiceContentLeft;
cf.top = mVoiceContentTop;
@@ -4674,6 +4695,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
cf.right = mContentRight;
cf.bottom = mContentBottom;
}
+
+ applyForceImmersiveMode(pfl, cf);
}
} else {
// Full screen windows are always given a layout that is as if the
@@ -4694,6 +4717,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
}
} else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
& (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@@ -4808,6 +4833,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
} else if (attached != null) {
if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() +
"): attached to " + attached);
@@ -4865,6 +4892,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
vf.set(cf);
}
+
+ applyForceImmersiveMode(pfl, vf);
}
}
}
@@ -4936,6 +4965,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mContentBottom > top) {
mContentBottom = top;
}
+ if (mForceImmersiveBottom > top) {
+ mForceImmersiveBottom = top;
+ }
if (mVoiceContentBottom > top) {
mVoiceContentBottom = top;
}
@@ -4993,7 +5025,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState attached) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
- final int fl = PolicyControl.getWindowFlags(win, attrs);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(win, attrs);
if (mTopFullscreenOpaqueWindowState == null
&& win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
mForcingShowNavBar = true;
@@ -5178,7 +5210,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mLastSystemUiFlags, mLastSystemUiFlags);
}
} else if (mTopFullscreenOpaqueWindowState != null) {
- final int fl = PolicyControl.getWindowFlags(null, lp);
+ final int fl = WindowManagerPolicyControl.getWindowFlags(null, lp);
if (localLOGV) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
+ " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
@@ -7431,13 +7463,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
+ int tmpVisibility = WindowManagerPolicyControl.getSystemUiVisibility(win, null)
& ~mResettingSystemUiFlags
& ~mForceClearedSystemUiFlags;
+ boolean wasCleared = mClearedBecauseOfForceShow;
if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
- tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
+ tmpVisibility &=
+ ~WindowManagerPolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
+ mClearedBecauseOfForceShow = true;
+ } else {
+ mClearedBecauseOfForceShow = false;
+ }
+
+ // The window who requested navbar force showing disappeared and next window wants
+ // to hide navbar. Instead of hiding we will make it transient. SystemUI will take care
+ // about hiding after timeout. This should not happen if next window is keyguard because
+ // transient state have more priority than translucent (why?) and cause bad UX
+ if (wasCleared && !mClearedBecauseOfForceShow
+ && (tmpVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ mNavigationBarController.showTransient();
+ tmpVisibility |= View.NAVIGATION_BAR_TRANSIENT;
+ mWindowManagerFuncs.addSystemUIVisibilityFlag(View.NAVIGATION_BAR_TRANSIENT);
}
- tmpVisibility = updateLightStatusBarLw(tmpVisibility);
+
+ boolean topWindowWasKeyguard = mTopWindowIsKeyguard;
+ mTopWindowIsKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+ if (topWindowWasKeyguard && !mTopWindowIsKeyguard
+ && (tmpVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
+ mStatusBarController.showTransient();
+ tmpVisibility |= View.STATUS_BAR_TRANSIENT;
+ mWindowManagerFuncs.addSystemUIVisibilityFlag(View.STATUS_BAR_TRANSIENT);
+ }
+
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
@@ -7519,7 +7576,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
(vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
boolean hideStatusBarWM =
mTopFullscreenOpaqueWindowState != null &&
- (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
+ (WindowManagerPolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null)
& WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
boolean hideStatusBarSysui =
(vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
@@ -7857,7 +7914,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mGlobalKeyManager.dump(prefix, pw);
mStatusBarController.dump(pw, prefix);
mNavigationBarController.dump(pw, prefix);
- PolicyControl.dump(prefix, pw);
+ WindowManagerPolicyControl.dump(prefix, pw);
if (mWakeGestureListener != null) {
mWakeGestureListener.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 69decfd..60ddd85 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5670,6 +5670,11 @@ public class WindowManagerService extends IWindowManager.Stub
mPointerEventDispatcher.unregisterInputEventListener(listener);
}
+ @Override
+ public void addSystemUIVisibilityFlag(int flags) {
+ mLastStatusBarVisibility |= flags;
+ }
+
// Called by window manager policy. Not exposed externally.
@Override
public int getLidState() {