Plumb lights out mode through from the window manager to the status bar running in the system ui process.
Lights out mode itself isn't implemented.
Change-Id: Ieeef0eb9ae5be23000f770e74e8ee66472f4c673
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 4501bd7..e884af8 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -30,5 +30,6 @@
void disable(int state);
void animateExpand();
void animateCollapse();
+ void setLightsOn(boolean on);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 2307669..07cc43e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -30,11 +30,13 @@
void setIcon(String slot, String iconPackage, int iconId, int iconLevel);
void setIconVisibility(String slot, boolean visible);
void removeIcon(String slot);
+ void setActiveWindowIsFullscreen(boolean fullscreen);
// ---- Methods below are for use by the status bar policy services ----
// You need the STATUS_BAR_SERVICE permission
void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
- out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
+ out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
+ out boolean[] lightsOn);
void onPanelRevealed();
void onNotificationClick(String pkg, String tag, int id);
void onNotificationError(String pkg, String tag, int id,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 2c0af65..3ef12f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -52,6 +52,8 @@
private static final int OP_EXPAND = 1;
private static final int OP_COLLAPSE = 2;
+ private static final int MSG_SET_LIGHTS_ON = 0x00070000;
+
private StatusBarIconList mList;
private Callbacks mCallbacks;
private Handler mHandler = new H();
@@ -75,6 +77,7 @@
public void disable(int state);
public void animateExpand();
public void animateCollapse();
+ public void setLightsOn(boolean on);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -143,6 +146,13 @@
}
}
+ public void setLightsOn(boolean on) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_SET_LIGHTS_ON);
+ mHandler.obtainMessage(MSG_SET_LIGHTS_ON, on ? 1 : 0, 0, null).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -194,6 +204,10 @@
} else {
mCallbacks.animateCollapse();
}
+ break;
+ case MSG_SET_LIGHTS_ON:
+ mCallbacks.setLightsOn(msg.arg1 != 0);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index 48243ff..e945981 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -1011,6 +1011,15 @@
return false;
}
+ public void setLightsOn(boolean on) {
+ if (!on) {
+ // All we do for "lights out" mode on a phone is hide the status bar,
+ // which the window manager does. But we do need to hide the windowshade
+ // on our own.
+ animateCollapse();
+ }
+ }
+
private class Launcher implements View.OnClickListener {
private PendingIntent mIntent;
private String mPkg;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index a64c3e7..695fdba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -72,12 +72,16 @@
mCommandQueue = new CommandQueue(this, iconList);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ boolean[] lightsOn = new boolean[1];
try {
- mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications);
+ mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
+ lightsOn);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
+ setLightsOn(lightsOn[0]);
+
// Set up the initial icon state
int N = iconList.size();
int viewIndex = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 6f74924..b33af99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -56,8 +56,6 @@
private static final int MAX_IMAGE_LEVEL = 10000;
-
-
int mIconSize;
H mHandler = new H();
@@ -493,6 +491,14 @@
mHandler.sendEmptyMessage(H.MSG_CLOSE_SYSTEM_PANEL);
}
+ public void setLightsOn(boolean on) {
+ //Slog.d(TAG, "setLightsOn on=" + on);
+ if (!on) {
+ animateCollapse();
+ }
+ // TODO: implement lights out mode
+ }
+
public void notificationIconsClicked(View v) {
if (DEBUG) Slog.d(TAG, "clicked notification icons");
mHandler.removeMessages(H.MSG_CLOSE_SYSTEM_PANEL);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6e5db2b..7009c65 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -177,6 +177,7 @@
Context mContext;
IWindowManager mWindowManager;
LocalPowerManager mPowerManager;
+ IStatusBarService mStatusBarService;
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
// Vibrator pattern for haptic feedback of a long press.
@@ -263,6 +264,7 @@
static final Rect mTmpVisibleFrame = new Rect();
WindowState mTopFullscreenOpaqueWindowState;
+ boolean mTopIsFullscreen;
boolean mForceStatusBar;
boolean mHideLockScreen;
boolean mDismissKeyguard;
@@ -1555,8 +1557,8 @@
/** {@inheritDoc} */
public int finishAnimationLw() {
int changes = 0;
-
- boolean hiding = false;
+
+ boolean topIsFullscreen = false;
if (mStatusBar != null) {
if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar
+ " top=" + mTopFullscreenOpaqueWindowState);
@@ -1564,18 +1566,22 @@
if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
} else if (mTopFullscreenOpaqueWindowState != null) {
- //Log.i(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
- // + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
- //Log.i(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs());
- WindowManager.LayoutParams lp =
- mTopFullscreenOpaqueWindowState.getAttrs();
- boolean hideStatusBar =
- (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
- if (hideStatusBar) {
+ final WindowManager.LayoutParams lp = mTopFullscreenOpaqueWindowState.getAttrs();
+ if (localLOGV) {
+ Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
+ + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
+ Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
+ + " lp.flags=0x" + Integer.toHexString(lp.flags));
+ }
+ topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
+ // The subtle difference between the window for mTopFullscreenOpaqueWindowState
+ // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
+ // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
+ // case though.
+ if (topIsFullscreen) {
if (mStatusBarCanHide) {
if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar");
if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
- hiding = true;
} else if (localLOGV) {
Log.v(TAG, "Preventing status bar from hiding by policy");
}
@@ -1586,21 +1592,36 @@
}
}
- if (changes != 0 && hiding) {
- IStatusBarService sbs = IStatusBarService.Stub.asInterface(ServiceManager.getService("statusbar"));
- if (sbs != null) {
- try {
- // Make sure the window shade is hidden.
- sbs.collapse();
- } catch (RemoteException e) {
- }
- }
+ if (topIsFullscreen != mTopIsFullscreen) {
+ final boolean topIsFullscreenF = topIsFullscreen;
+ mTopIsFullscreen = topIsFullscreen;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (mStatusBarService == null) {
+ // This is the one that can not go away, but it doesn't come up
+ // before the window manager does, so don't fail if it doesn't
+ // exist. This works as long as no fullscreen windows come up
+ // before the status bar service does.
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService("statusbar"));
+ }
+ final IStatusBarService sbs = mStatusBarService;
+ if (mStatusBarService != null) {
+ try {
+ sbs.setActiveWindowIsFullscreen(topIsFullscreenF);
+ } catch (RemoteException e) {
+ // This should be impossible because we're in the same process.
+ mStatusBarService = null;
+ }
+ }
+ }
+ });
}
// Hide the key guard if a visible window explicitly specifies that it wants to be displayed
// when the screen is locked
if (mKeyguard != null) {
- if (localLOGV) Log.v(TAG, "finishLayoutLw::mHideKeyguard="+mHideLockScreen);
+ if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
if (mKeyguard.hideLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 717c309..dc86eeb 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -68,6 +68,10 @@
ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
int mDisabled = 0;
+ Object mLock = new Object();
+ // We usually call it lights out mode, but double negatives are annoying
+ boolean mLightsOn = true;
+
private class DisableRecord implements IBinder.DeathRecipient {
String pkg;
int what;
@@ -242,6 +246,30 @@
}
}
+ public void setActiveWindowIsFullscreen(boolean fullscreen) {
+ // We could get away with a separate permission here, but STATUS_BAR is
+ // signatureOrSystem which is probably good enough. There is no public API
+ // for this, so the question is a security issue, not an API compatibility issue.
+ enforceStatusBar();
+
+ final boolean lightsOn = !fullscreen;
+ synchronized (mLock) {
+ if (mLightsOn != lightsOn) {
+ mLightsOn = lightsOn;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (mBar != null) {
+ try {
+ mBar.setLightsOn(lightsOn);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
@@ -262,7 +290,8 @@
// Callbacks from the status bar service.
// ================================================================================
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
- List<IBinder> notificationKeys, List<StatusBarNotification> notifications) {
+ List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
+ boolean lightsOn[]) {
enforceStatusBarService();
Slog.i(TAG, "registerStatusBar bar=" + bar);
@@ -276,6 +305,9 @@
notifications.add(e.getValue());
}
}
+ synchronized (mLock) {
+ lightsOn[0] = mLightsOn;
+ }
}
/**
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b6a090f..94b010b 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -7038,6 +7039,9 @@
frame.right >= mCompatibleScreenFrame.right &&
frame.bottom >= mCompatibleScreenFrame.bottom;
} else {
+ if ((mAttrs.flags & FLAG_FULLSCREEN) != 0) {
+ return true;
+ }
return frame.left <= 0 && frame.top <= 0
&& frame.right >= screenWidth
&& frame.bottom >= screenHeight;
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index b665d2f..e31711e 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -60,20 +60,19 @@
}
private Test[] mTests = new Test[] {
- new Test("Hide") {
+ new Test("Hide (FLAG_FULLSCREEN)") {
public void run() {
Window win = getWindow();
- WindowManager.LayoutParams winParams = win.getAttributes();
- winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
- win.setAttributes(winParams);
+ win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ Log.d(TAG, "flags=" + Integer.toHexString(win.getAttributes().flags));
}
},
- new Test("Show") {
+ new Test("Show (~FLAG_FULLSCREEN)") {
public void run() {
Window win = getWindow();
- WindowManager.LayoutParams winParams = win.getAttributes();
- winParams.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
- win.setAttributes(winParams);
+ win.setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ Log.d(TAG, "flags=" + Integer.toHexString(win.getAttributes().flags));
}
},
new Test("Immersive: Enter") {