Merge "Clean up status bar, system bar, navigation bar management."

This commit is contained in:
Dianne Hackborn
2012-04-05 11:47:02 -07:00
committed by Android (Google) Code Review
25 changed files with 450 additions and 408 deletions

View File

@ -62,8 +62,8 @@ interface IWindowManager
void setForcedDisplaySize(int longDimen, int shortDimen); void setForcedDisplaySize(int longDimen, int shortDimen);
void clearForcedDisplaySize(); void clearForcedDisplaySize();
// Is device configured with a hideable status bar or a tablet system bar? // Is the device configured to have a full system bar for larger screens?
boolean canStatusBarHide(); boolean hasSystemNavBar();
// These can only be called when injecting events to your own window, // These can only be called when injecting events to your own window,
// or by holding the INJECT_EVENTS permission. These methods may block // or by holding the INJECT_EVENTS permission. These methods may block
@ -171,8 +171,10 @@ interface IWindowManager
* @param alwaysSendConfiguration Flag to force a new configuration to * @param alwaysSendConfiguration Flag to force a new configuration to
* be evaluated. This can be used when there are other parameters in * be evaluated. This can be used when there are other parameters in
* configuration that are changing. * configuration that are changing.
* @param forceRelayout If true, the window manager will always do a relayout
* of its windows even if the rotation hasn't changed.
*/ */
void updateRotation(boolean alwaysSendConfiguration); void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout);
/** /**
* Retrieve the current screen orientation, constants as per * Retrieve the current screen orientation, constants as per

View File

@ -315,7 +315,7 @@ public class ViewConfiguration {
if (!sHasPermanentMenuKeySet) { if (!sHasPermanentMenuKeySet) {
IWindowManager wm = Display.getWindowManager(); IWindowManager wm = Display.getWindowManager();
try { try {
sHasPermanentMenuKey = wm.canStatusBarHide() && !wm.hasNavigationBar(); sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
sHasPermanentMenuKeySet = true; sHasPermanentMenuKeySet = true;
} catch (RemoteException ex) { } catch (RemoteException ex) {
sHasPermanentMenuKey = false; sHasPermanentMenuKey = false;

View File

@ -326,6 +326,11 @@ public interface WindowManagerPolicy {
* Returns true if {@link #hideLw} was last called for the window. * Returns true if {@link #hideLw} was last called for the window.
*/ */
public boolean showLw(boolean doAnimation); public boolean showLw(boolean doAnimation);
/**
* Check whether the process hosting this window is currently alive.
*/
public boolean isAlive();
} }
/** /**
@ -447,7 +452,7 @@ public interface WindowManagerPolicy {
* Called by window manager once it has the initial, default native * Called by window manager once it has the initial, default native
* display dimensions. * display dimensions.
*/ */
public void setInitialDisplaySize(int width, int height); public void setInitialDisplaySize(Display display, int width, int height);
/** /**
* Check permissions when adding a window. * Check permissions when adding a window.
@ -514,10 +519,10 @@ public interface WindowManagerPolicy {
public int getMaxWallpaperLayer(); public int getMaxWallpaperLayer();
/** /**
* Return true if the policy allows the status bar to hide. Otherwise, * Return true if the policy desires a full unified system nav bar. Otherwise,
* it is a tablet-style system bar. * it is a phone-style status bar with optional nav bar.
*/ */
public boolean canStatusBarHide(); public boolean hasSystemNavBar();
/** /**
* Return the display width available after excluding any screen * Return the display width available after excluding any screen

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the bottom of the screen is entering. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_quad">
<translate android:fromYDelta="75%" android:toYDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the bottom of the screen is exiting. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad">
<translate android:fromYDelta="0" android:toYDelta="75%"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the left of the screen is entering. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_quad">
<translate android:fromXDelta="-75%" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the right of the screen is exiting. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad">
<translate android:fromXDelta="0" android:toXDelta="-75%"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the right of the screen is entering. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_quad">
<translate android:fromXDelta="75%" android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* Copyright 2012, 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.
*/
-->
<!-- Animation for when a dock window at the right of the screen is exiting. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad">
<translate android:fromXDelta="0" android:toXDelta="75%"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
</set>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
/* //device/apps/common/res/anim/options_panel_enter.xml /* Copyright 2007, The Android Open Source Project
**
** Copyright 2007, The Android Open Source Project
** **
** Licensed under the Apache License, Version 2.0 (the "License"); ** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License. ** you may not use this file except in compliance with the License.
@ -18,10 +16,11 @@
*/ */
--> -->
<!-- Animation for when a dock window at the top of the screen is entering. -->
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_quad"> android:interpolator="@android:interpolator/decelerate_quad">
<translate android:fromYDelta="-75%" android:toYDelta="0" <translate android:fromYDelta="-75%" android:toYDelta="0"
android:duration="@android:integer/config_mediumAnimTime"/> android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="@android:integer/config_mediumAnimTime" /> android:duration="@android:integer/config_mediumAnimTime" />
</set> </set>

View File

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
/* //device/apps/common/res/anim/options_panel_exit.xml /* Copyright 2007, The Android Open Source Project
**
** Copyright 2007, The Android Open Source Project
** **
** Licensed under the Apache License, Version 2.0 (the "License"); ** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License. ** you may not use this file except in compliance with the License.
@ -18,10 +16,11 @@
*/ */
--> -->
<!-- Animation for when a dock window at the top of the screen is exiting. -->
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/accelerate_quad"> android:interpolator="@android:interpolator/accelerate_quad">
<translate android:fromYDelta="0" android:toYDelta="-75%" <translate android:fromYDelta="0" android:toYDelta="-75%"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/> android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" /> android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
</set> </set>

View File

@ -32,11 +32,9 @@
<dimen name="toast_y_offset">64dip</dimen> <dimen name="toast_y_offset">64dip</dimen>
<!-- Height of the status bar --> <!-- Height of the status bar -->
<dimen name="status_bar_height">25dip</dimen> <dimen name="status_bar_height">25dip</dimen>
<!-- Height of the system bar (combined status + navigation, used on large screens) --> <!-- Height of the bottom navigation / system bar. -->
<dimen name="system_bar_height">48dip</dimen>
<!-- Height of the horizontal navigation bar on devices that require it -->
<dimen name="navigation_bar_height">48dp</dimen> <dimen name="navigation_bar_height">48dp</dimen>
<!-- Width of the vertical navigation bar on devices that require it --> <!-- Width of the navigation bar when it is placed vertically on the screen -->
<dimen name="navigation_bar_width">42dp</dimen> <dimen name="navigation_bar_width">42dp</dimen>
<!-- Height of notification icons in the status bar --> <!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">24dip</dimen> <dimen name="status_bar_icon_size">24dip</dimen>

View File

@ -1128,6 +1128,14 @@
<!-- From android.policy --> <!-- From android.policy -->
<java-symbol type="anim" name="app_starting_exit" /> <java-symbol type="anim" name="app_starting_exit" />
<java-symbol type="anim" name="lock_screen_behind_enter" /> <java-symbol type="anim" name="lock_screen_behind_enter" />
<java-symbol type="anim" name="dock_top_enter" />
<java-symbol type="anim" name="dock_top_exit" />
<java-symbol type="anim" name="dock_bottom_enter" />
<java-symbol type="anim" name="dock_bottom_exit" />
<java-symbol type="anim" name="dock_left_enter" />
<java-symbol type="anim" name="dock_left_exit" />
<java-symbol type="anim" name="dock_right_enter" />
<java-symbol type="anim" name="dock_right_exit" />
<java-symbol type="array" name="config_keyboardTapVibePattern" /> <java-symbol type="array" name="config_keyboardTapVibePattern" />
<java-symbol type="array" name="config_longPressVibePattern" /> <java-symbol type="array" name="config_longPressVibePattern" />
<java-symbol type="array" name="config_safeModeDisabledVibePattern" /> <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
@ -1153,7 +1161,6 @@
<java-symbol type="dimen" name="navigation_bar_height" /> <java-symbol type="dimen" name="navigation_bar_height" />
<java-symbol type="dimen" name="navigation_bar_width" /> <java-symbol type="dimen" name="navigation_bar_width" />
<java-symbol type="dimen" name="status_bar_height" /> <java-symbol type="dimen" name="status_bar_height" />
<java-symbol type="dimen" name="system_bar_height" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" /> <java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" /> <java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" /> <java-symbol type="drawable" name="ic_jog_dial_unlock" />

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="@android:integer/config_longAnimTime"
android:interpolator="@anim/hydraulic_brake_interpolator"
/>
<alpha android:fromAlpha="0.5" android:toAlpha="1.0"
android:duration="@android:integer/config_longAnimTime"
/>
</set>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
<translate android:toYDelta="100%p" android:fromYDelta="0"
android:duration="@android:integer/config_longAnimTime"
android:interpolator="@anim/hydraulic_brake_interpolator"
/>
<alpha android:toAlpha="0.5" android:fromAlpha="1.0"
android:duration="@android:integer/config_longAnimTime"
/>
</set>

View File

@ -67,8 +67,6 @@
<!-- Standard animations for hiding and showing the status bar. --> <!-- Standard animations for hiding and showing the status bar. -->
<style name="Animation.StatusBar"> <style name="Animation.StatusBar">
<item name="android:windowEnterAnimation">@anim/status_bar_enter</item>
<item name="android:windowExitAnimation">@anim/status_bar_exit</item>
</style> </style>
<style name="Animation.StatusBar.IntruderAlert"> <style name="Animation.StatusBar.IntruderAlert">

View File

@ -69,9 +69,9 @@ public class SystemUIService extends Service {
IWindowManager wm = IWindowManager.Stub.asInterface( IWindowManager wm = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE)); ServiceManager.getService(Context.WINDOW_SERVICE));
try { try {
SERVICES[0] = wm.canStatusBarHide() SERVICES[0] = wm.hasSystemNavBar()
? R.string.config_statusBarComponent ? R.string.config_systemBarComponent
: R.string.config_systemBarComponent; : R.string.config_statusBarComponent;
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.w(TAG, "Failing checking whether status bar can hide", e); Slog.w(TAG, "Failing checking whether status bar can hide", e);
} }

View File

@ -1766,11 +1766,6 @@ public class PhoneStatusBar extends BaseStatusBar {
// HWComposer is unable to handle SW-rendered RGBX_8888 layers. // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
PixelFormat.RGB_565); PixelFormat.RGB_565);
// the status bar should be in an overlay if possible
final Display defaultDisplay
= ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
// We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies
// very little screen real-estate and is updated fairly frequently. By using CPU rendering // very little screen real-estate and is updated fairly frequently. By using CPU rendering
// for the status bar, we prevent the GPU from having to wake up just to do these small // for the status bar, we prevent the GPU from having to wake up just to do these small
@ -1779,9 +1774,7 @@ public class PhoneStatusBar extends BaseStatusBar {
lp.gravity = getStatusBarGravity(); lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar"); lp.setTitle("StatusBar");
lp.packageName = mContext.getPackageName(); lp.packageName = mContext.getPackageName();
lp.windowAnimations = R.style.Animation_StatusBar;
WindowManagerImpl.getDefault().addView(makeStatusBarView(), lp); WindowManagerImpl.getDefault().addView(makeStatusBarView(), lp);
} }
void addExpandedWindow() { void addExpandedWindow() {

View File

@ -1,114 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.tablet;
import java.util.ArrayList;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.Display;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
public class HeightReceiver extends BroadcastReceiver {
private static final String TAG = "StatusBar.HeightReceiver";
public interface OnBarHeightChangedListener {
public void onBarHeightChanged(int height);
}
Context mContext;
ArrayList<OnBarHeightChangedListener> mListeners = new ArrayList<OnBarHeightChangedListener>();
WindowManager mWindowManager;
int mHeight;
boolean mPlugged;
public HeightReceiver(Context context) {
mContext = context;
mWindowManager = WindowManagerImpl.getDefault();
}
public void addOnBarHeightChangedListener(OnBarHeightChangedListener l) {
mListeners.add(l);
l.onBarHeightChanged(mHeight);
}
public void removeOnBarHeightChangedListener(OnBarHeightChangedListener l) {
mListeners.remove(l);
}
@Override
public void onReceive(Context context, Intent intent) {
final boolean plugged
= intent.getBooleanExtra(WindowManagerPolicy.EXTRA_HDMI_PLUGGED_STATE, false);
setPlugged(plugged);
}
public void registerReceiver() {
final IntentFilter filter = new IntentFilter();
filter.addAction(WindowManagerPolicy.ACTION_HDMI_PLUGGED);
final Intent val = mContext.registerReceiver(this, filter);
onReceive(mContext, val);
}
private void setPlugged(boolean plugged) {
mPlugged = plugged;
updateHeight();
}
public void updateHeight() {
final Resources res = mContext.getResources();
int height = -1;
if (mPlugged) {
final DisplayMetrics metrics = new DisplayMetrics();
Display display = mWindowManager.getDefaultDisplay();
display.getRealMetrics(metrics);
//Slog.i(TAG, "updateHeight: display metrics=" + metrics);
final int shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
final int externalShortSide = Math.min(display.getRawExternalWidth(),
display.getRawExternalHeight());
height = shortSide - externalShortSide;
}
final int minHeight
= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
if (height < minHeight) {
height = minHeight;
}
Slog.i(TAG, "Resizing status bar plugged=" + mPlugged + " height="
+ height + " old=" + mHeight);
mHeight = height;
final int N = mListeners.size();
for (int i=0; i<N; i++) {
mListeners.get(i).onBarHeightChanged(height);
}
}
public int getHeight() {
return mHeight;
}
}

View File

@ -87,7 +87,6 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.Prefs; import com.android.systemui.statusbar.policy.Prefs;
public class TabletStatusBar extends BaseStatusBar implements public class TabletStatusBar extends BaseStatusBar implements
HeightReceiver.OnBarHeightChangedListener,
InputMethodsPanel.OnHardKeyboardEnabledChangeListener, InputMethodsPanel.OnHardKeyboardEnabledChangeListener,
RecentsPanelView.OnRecentsPanelVisibilityChangedListener { RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
public static final boolean DEBUG = false; public static final boolean DEBUG = false;
@ -162,7 +161,6 @@ public class TabletStatusBar extends BaseStatusBar implements
ViewGroup mPile; ViewGroup mPile;
HeightReceiver mHeightReceiver;
BatteryController mBatteryController; BatteryController mBatteryController;
BluetoothController mBluetoothController; BluetoothController mBluetoothController;
LocationController mLocationController; LocationController mLocationController;
@ -204,12 +202,11 @@ public class TabletStatusBar extends BaseStatusBar implements
private void addStatusBarWindow() { private void addStatusBarWindow() {
final View sb = makeStatusBarView(); final View sb = makeStatusBarView();
final int height = getStatusBarHeight();
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
height, ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_STATUS_BAR, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
@ -218,20 +215,14 @@ public class TabletStatusBar extends BaseStatusBar implements
// HWComposer is unable to handle SW-rendered RGBX_8888 layers. // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
PixelFormat.RGB_565); PixelFormat.RGB_565);
// the status bar should be in an overlay if possible
final Display defaultDisplay
= ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
// We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies
// very little screen real-estate and is updated fairly frequently. By using CPU rendering // very little screen real-estate and is updated fairly frequently. By using CPU rendering
// for the status bar, we prevent the GPU from having to wake up just to do these small // for the status bar, we prevent the GPU from having to wake up just to do these small
// updates, which should help keep power consumption down. // updates, which should help keep power consumption down.
lp.gravity = getStatusBarGravity(); lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar"); lp.setTitle("SystemBar");
lp.packageName = mContext.getPackageName(); lp.packageName = mContext.getPackageName();
lp.windowAnimations = R.style.Animation_StatusBar;
WindowManagerImpl.getDefault().addView(sb, lp); WindowManagerImpl.getDefault().addView(sb, lp);
} }
@ -414,7 +405,6 @@ public class TabletStatusBar extends BaseStatusBar implements
@Override @Override
protected void onConfigurationChanged(Configuration newConfig) { protected void onConfigurationChanged(Configuration newConfig) {
mHeightReceiver.updateHeight(); // display size may have changed
loadDimens(); loadDimens();
mNotificationPanelParams.height = getNotificationPanelHeight(); mNotificationPanelParams.height = getNotificationPanelHeight();
WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel, WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
@ -426,7 +416,7 @@ public class TabletStatusBar extends BaseStatusBar implements
final Resources res = mContext.getResources(); final Resources res = mContext.getResources();
mNaturalBarHeight = res.getDimensionPixelSize( mNaturalBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.system_bar_height); com.android.internal.R.dimen.navigation_bar_height);
int newIconSize = res.getDimensionPixelSize( int newIconSize = res.getDimensionPixelSize(
com.android.internal.R.dimen.system_bar_icon_size); com.android.internal.R.dimen.system_bar_icon_size);
@ -478,10 +468,6 @@ public class TabletStatusBar extends BaseStatusBar implements
mWindowManager = IWindowManager.Stub.asInterface( mWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE)); ServiceManager.getService(Context.WINDOW_SERVICE));
// This guy will listen for HDMI plugged broadcasts so we can resize the
// status bar as appropriate.
mHeightReceiver = new HeightReceiver(mContext);
mHeightReceiver.registerReceiver();
loadDimens(); loadDimens();
final TabletStatusBarView sb = (TabletStatusBarView)View.inflate( final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
@ -637,8 +623,6 @@ public class TabletStatusBar extends BaseStatusBar implements
// set the initial view visibility // set the initial view visibility
setAreThereNotifications(); setAreThereNotifications();
mHeightReceiver.addOnBarHeightChangedListener(this);
// receive broadcasts // receive broadcasts
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@ -674,7 +658,9 @@ public class TabletStatusBar extends BaseStatusBar implements
} }
public int getStatusBarHeight() { public int getStatusBarHeight() {
return mHeightReceiver.getHeight(); return mStatusBarView != null ? mStatusBarView.getHeight()
: mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_height);
} }
protected int getStatusBarGravity() { protected int getStatusBarGravity() {

View File

@ -1,5 +1,4 @@
/* /*
* Copyright (C) 2006 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -72,6 +71,7 @@ import android.util.EventLog;
import android.util.Log; import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.Display;
import android.view.Gravity; import android.view.Gravity;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.IApplicationToken; import android.view.IApplicationToken;
@ -299,11 +299,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mHeadless; boolean mHeadless;
boolean mSafeMode; boolean mSafeMode;
WindowState mStatusBar = null; WindowState mStatusBar = null;
boolean mStatusBarCanHide; boolean mHasSystemNavBar;
int mStatusBarHeight; int mStatusBarHeight;
final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>(); final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
WindowState mNavigationBar = null; WindowState mNavigationBar = null;
boolean mHasNavigationBar = false; boolean mHasNavigationBar = false;
boolean mCanHideNavigationBar = false;
boolean mNavigationBarOnBottom = true;
int mNavigationBarWidth = 0, mNavigationBarHeight = 0; int mNavigationBarWidth = 0, mNavigationBarHeight = 0;
WindowState mKeyguard = null; WindowState mKeyguard = null;
@ -329,6 +331,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mSystemReady; boolean mSystemReady;
boolean mSystemBooted; boolean mSystemBooted;
boolean mHdmiPlugged; boolean mHdmiPlugged;
int mExternalDisplayWidth;
int mExternalDisplayHeight;
int mUiMode; int mUiMode;
int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
int mLidOpenRotation; int mLidOpenRotation;
@ -464,6 +468,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
int mIncallPowerBehavior; int mIncallPowerBehavior;
Display mDisplay;
int mLandscapeRotation = 0; // default landscape rotation int mLandscapeRotation = 0; // default landscape rotation
int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
int mPortraitRotation = 0; // default portrait rotation int mPortraitRotation = 0; // default portrait rotation
@ -927,10 +933,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
} }
public void setInitialDisplaySize(int width, int height) { public void setInitialDisplaySize(Display display, int width, int height) {
int shortSize; mDisplay = display;
int shortSize, longSize;
if (width > height) { if (width > height) {
shortSize = height; shortSize = height;
longSize = width;
mLandscapeRotation = Surface.ROTATION_0; mLandscapeRotation = Surface.ROTATION_0;
mSeascapeRotation = Surface.ROTATION_180; mSeascapeRotation = Surface.ROTATION_180;
if (mContext.getResources().getBoolean( if (mContext.getResources().getBoolean(
@ -943,6 +952,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
} else { } else {
shortSize = width; shortSize = width;
longSize = height;
mPortraitRotation = Surface.ROTATION_0; mPortraitRotation = Surface.ROTATION_0;
mUpsideDownRotation = Surface.ROTATION_180; mUpsideDownRotation = Surface.ROTATION_180;
if (mContext.getResources().getBoolean( if (mContext.getResources().getBoolean(
@ -955,36 +965,61 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
} }
mExternalDisplayWidth = mDisplay.getRawExternalWidth();
mExternalDisplayHeight = mDisplay.getRawExternalHeight();
mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
mNavigationBarHeight = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_height);
mNavigationBarWidth = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_width);
// Determine whether the status bar can hide based on the size // Determine whether the status bar can hide based on the size
// of the screen. We assume sizes > 600dp are tablets where we // of the screen. We assume sizes > 600dp are tablets where we
// will use the system bar. // will use the system bar.
int shortSizeDp = shortSize int shortSizeDp = shortSize
* DisplayMetrics.DENSITY_DEFAULT * DisplayMetrics.DENSITY_DEFAULT
/ DisplayMetrics.DENSITY_DEVICE; / DisplayMetrics.DENSITY_DEVICE;
mStatusBarCanHide = shortSizeDp < 600; mHasSystemNavBar = shortSizeDp > 600;
mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
mStatusBarCanHide
? com.android.internal.R.dimen.status_bar_height
: com.android.internal.R.dimen.system_bar_height);
mHasNavigationBar = mContext.getResources().getBoolean( if (!mHasSystemNavBar) {
com.android.internal.R.bool.config_showNavigationBar); mHasNavigationBar = mContext.getResources().getBoolean(
// Allow a system property to override this. Used by the emulator. com.android.internal.R.bool.config_showNavigationBar);
// See also hasNavigationBar(). // Allow a system property to override this. Used by the emulator.
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); // See also hasNavigationBar().
if (! "".equals(navBarOverride)) { String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
if (navBarOverride.equals("1")) mHasNavigationBar = false; if (! "".equals(navBarOverride)) {
else if (navBarOverride.equals("0")) mHasNavigationBar = true; if (navBarOverride.equals("1")) mHasNavigationBar = false;
else if (navBarOverride.equals("0")) mHasNavigationBar = true;
}
} else {
mHasNavigationBar = false;
} }
mNavigationBarHeight = mHasNavigationBar if (mHasSystemNavBar) {
? mContext.getResources().getDimensionPixelSize( // The system bar is always at the bottom. If you are watching
com.android.internal.R.dimen.navigation_bar_height) // a video in landscape, we don't need to hide it if we can still
: 0; // show a 16:9 aspect ratio with it.
mNavigationBarWidth = mHasNavigationBar int longSizeDp = longSize
? mContext.getResources().getDimensionPixelSize( * DisplayMetrics.DENSITY_DEFAULT
com.android.internal.R.dimen.navigation_bar_width) / DisplayMetrics.DENSITY_DEVICE;
: 0; int barHeightDp = mNavigationBarHeight
* DisplayMetrics.DENSITY_DEFAULT
/ DisplayMetrics.DENSITY_DEVICE;
int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
// We have computed the aspect ratio with the bar height taken
// out to be 16:aspect. If this is less than 9, then hiding
// the navigation bar will provide more useful space for wide
// screen movies.
mCanHideNavigationBar = aspect < 9;
} else if (mHasNavigationBar) {
// The navigation bar is at the right in landscape; it seems always
// useful to hide it for showing a video.
mCanHideNavigationBar = true;
} else {
mCanHideNavigationBar = false;
}
if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
mHdmiRotation = mPortraitRotation; mHdmiRotation = mPortraitRotation;
@ -1318,13 +1353,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return STATUS_BAR_LAYER; return STATUS_BAR_LAYER;
} }
public boolean canStatusBarHide() { public boolean hasSystemNavBar() {
return mStatusBarCanHide; return mHasSystemNavBar;
} }
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) { public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
// Assumes that the navigation bar appears on the side of the display in landscape. // Assumes that the navigation bar appears on the side of the display in landscape.
if (fullWidth > fullHeight) { if (mHasNavigationBar && fullWidth > fullHeight) {
return fullWidth - mNavigationBarWidth; return fullWidth - mNavigationBarWidth;
} }
return fullWidth; return fullWidth;
@ -1333,8 +1368,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) { public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
// Assumes the navigation bar appears on the bottom of the display in portrait. // Assumes the navigation bar appears on the bottom of the display in portrait.
return fullHeight return fullHeight
- (mStatusBarCanHide ? 0 : mStatusBarHeight) - (mHasSystemNavBar ? mNavigationBarHeight : 0)
- ((fullWidth > fullHeight) ? 0 : mNavigationBarHeight); - ((mHasNavigationBar && fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
} }
public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) { public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
@ -1348,7 +1383,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// exclude it since applications can't generally use that part of the // exclude it since applications can't generally use that part of the
// screen. // screen.
return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation)
- (mStatusBarCanHide ? mStatusBarHeight : 0); - (mHasSystemNavBar ? 0 : mStatusBarHeight);
} }
public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@ -1357,6 +1392,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
&& attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
&& attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER; && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
} }
@ -1495,10 +1531,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE, android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager"); "PhoneWindowManager");
// TODO: Need to handle the race condition of the status bar proc
// dying and coming back before the removeWindowLw cleanup has happened.
if (mStatusBar != null) { if (mStatusBar != null) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; if (mStatusBar.isAlive()) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
} }
mStatusBar = win; mStatusBar = win;
break; break;
@ -1506,6 +1542,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE, android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager"); "PhoneWindowManager");
if (mNavigationBar != null) {
if (mNavigationBar.isAlive()) {
return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
}
}
mNavigationBar = win; mNavigationBar = win;
if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar); if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break; break;
@ -1550,7 +1591,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public int selectAnimationLw(WindowState win, int transit) { public int selectAnimationLw(WindowState win, int transit) {
if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
+ ": transit=" + transit); + ": transit=" + transit);
if (transit == TRANSIT_PREVIEW_DONE) { if (win == mStatusBar) {
if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
return R.anim.dock_top_exit;
} else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
return R.anim.dock_top_enter;
}
} else if (win == mNavigationBar) {
// This can be on either the bottom or the right.
if (mNavigationBarOnBottom) {
if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
return R.anim.dock_bottom_exit;
} else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
return R.anim.dock_bottom_enter;
}
} else {
if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
return R.anim.dock_right_exit;
} else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
return R.anim.dock_right_enter;
}
}
} if (transit == TRANSIT_PREVIEW_DONE) {
if (win.hasAppShownWindows()) { if (win.hasAppShownWindows()) {
if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
return com.android.internal.R.anim.app_starting_exit; return com.android.internal.R.anim.app_starting_exit;
@ -2036,7 +2098,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
int availRight, availBottom; int availRight, availBottom;
if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { if (mCanHideNavigationBar &&
(attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
} else { } else {
@ -2082,8 +2145,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.right = df.right = vf.right = mDockRight; pf.right = df.right = vf.right = mDockRight;
pf.bottom = df.bottom = vf.bottom = mDockBottom; pf.bottom = df.bottom = vf.bottom = mDockBottom;
final boolean navVisible = (mNavigationBar == null || mNavigationBar.isVisibleLw()) && // For purposes of putting out fake window up to steal focus, we will
(mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; // drive nav being hidden only by whether it is requested.
boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
// When the navigation bar isn't visible, we put up a fake // When the navigation bar isn't visible, we put up a fake
// input window to catch all touch events. This way we can // input window to catch all touch events. This way we can
@ -2101,57 +2165,71 @@ public class PhoneWindowManager implements WindowManagerPolicy {
0, false, false, true); 0, false, false, true);
} }
// decide where the status bar goes ahead of time // For purposes of positioning and showing the nav bar, if we have
if (mStatusBar != null) { // decided that it can't be hidden (because of the screen aspect ratio),
if (mNavigationBar != null) { // then take that into account.
// Force the navigation bar to its appropriate place and navVisible |= !mCanHideNavigationBar;
// size. We need to do this directly, instead of relying on
// it to bubble up from the nav bar, because this needs to if (mNavigationBar != null) {
// change atomically with screen rotations. // Force the navigation bar to its appropriate place and
if (displayWidth < displayHeight) { // size. We need to do this directly, instead of relying on
// Portrait screen; nav bar goes on bottom. // it to bubble up from the nav bar, because this needs to
mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight, // change atomically with screen rotations.
displayWidth, displayHeight); mNavigationBarOnBottom = !mHasNavigationBar || displayWidth < displayHeight;
mStableBottom = mTmpNavigationFrame.top; if (mNavigationBarOnBottom) {
if (navVisible) { // It's a system nav bar or a portrait screen; nav bar goes on bottom.
mDockBottom = mTmpNavigationFrame.top; int top = displayHeight - mNavigationBarHeight;
mRestrictedScreenHeight = mDockBottom - mDockTop; if (mHdmiPlugged) {
} else { if (top > mExternalDisplayHeight) {
// We currently want to hide the navigation UI. Do this by just top = mExternalDisplayHeight;
// moving it off the screen, so it can still receive input events
// to know when to be re-shown.
mTmpNavigationFrame.offset(0, mNavigationBarHeight);
}
} else {
// Landscape screen; nav bar goes to the right.
mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
displayWidth, displayHeight);
mStableRight = mTmpNavigationFrame.left;
if (navVisible) {
mDockRight = mTmpNavigationFrame.left;
mRestrictedScreenWidth = mDockRight - mDockLeft;
} else {
// We currently want to hide the navigation UI. Do this by just
// moving it off the screen, so it can still receive input events
// to know when to be re-shown.
mTmpNavigationFrame.offset(mNavigationBarWidth, 0);
} }
} }
// Make sure the content and current rectangles are updated to mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
// account for the restrictions from the navigation bar. mStableBottom = mTmpNavigationFrame.top;
mContentTop = mCurTop = mDockTop; if (navVisible) {
mContentBottom = mCurBottom = mDockBottom; mNavigationBar.showLw(true);
mContentLeft = mCurLeft = mDockLeft; mDockBottom = mTmpNavigationFrame.top;
mContentRight = mCurRight = mDockRight; mRestrictedScreenHeight = mDockBottom - mDockTop;
// And compute the final frame. } else {
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, // We currently want to hide the navigation UI.
mTmpNavigationFrame, mTmpNavigationFrame); mNavigationBar.hideLw(true);
if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); }
} else {
// Landscape screen; nav bar goes to the right.
int left = displayWidth - mNavigationBarWidth;
if (mHdmiPlugged) {
if (left > mExternalDisplayWidth) {
left = mExternalDisplayWidth;
}
}
mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
mStableRight = mTmpNavigationFrame.left;
if (navVisible) {
mNavigationBar.showLw(true);
mDockRight = mTmpNavigationFrame.left;
mRestrictedScreenWidth = mDockRight - mDockLeft;
} else {
// We currently want to hide the navigation UI.
mNavigationBar.hideLw(true);
}
} }
if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", // Make sure the content and current rectangles are updated to
mDockLeft, mDockTop, mDockRight, mDockBottom)); // account for the restrictions from the navigation bar.
mContentTop = mCurTop = mDockTop;
mContentBottom = mCurBottom = mDockBottom;
mContentLeft = mCurLeft = mDockLeft;
mContentRight = mCurRight = mDockRight;
// And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
mTmpNavigationFrame, mTmpNavigationFrame);
if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
}
if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
mDockLeft, mDockTop, mDockRight, mDockBottom));
// apply navigation bar insets // decide where the status bar goes ahead of time
if (mStatusBar != null) {
// apply any navigation bar insets
pf.left = df.left = vf.left = mDockLeft; pf.left = df.left = vf.left = mDockLeft;
pf.top = df.top = vf.top = mDockTop; pf.top = df.top = vf.top = mDockTop;
pf.right = df.right = vf.right = mDockRight; pf.right = df.right = vf.right = mDockRight;
@ -2161,57 +2239,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Rect r = mStatusBar.getFrameLw(); final Rect r = mStatusBar.getFrameLw();
// Compute the stable dimensions whether or not the status bar is hidden. // Compute the stable dimensions whether or not the status bar is hidden.
if (mStatusBarCanHide) { if (mDockTop == r.top) mStableTop = r.bottom;
if (mDockTop == r.top) mStableTop = r.bottom; else if (mDockBottom == r.bottom) mStableBottom = r.top;
else if (mDockBottom == r.bottom) mStableBottom = r.top;
} else {
if (mStableTop == r.top) {
mStableTop = r.bottom;
} else if (mStableBottom == r.bottom) {
mStableBottom = r.top;
}
}
// If the status bar is hidden, we don't want to cause
// windows behind it to scroll.
if (mStatusBar.isVisibleLw()) { if (mStatusBar.isVisibleLw()) {
// If the status bar is hidden, we don't want to cause // Status bar may go away, so the screen area it occupies
// windows behind it to scroll. // is available to apps but just covering them when the
if (mStatusBarCanHide) { // status bar is visible.
// Status bar may go away, so the screen area it occupies if (mDockTop == r.top) mDockTop = r.bottom;
// is available to apps but just covering them when the else if (mDockBottom == r.bottom) mDockBottom = r.top;
// status bar is visible.
if (mDockTop == r.top) mDockTop = r.bottom; mContentTop = mCurTop = mDockTop;
else if (mDockBottom == r.bottom) mDockBottom = r.top; mContentBottom = mCurBottom = mDockBottom;
mContentLeft = mCurLeft = mDockLeft;
mContentTop = mCurTop = mDockTop; mContentRight = mCurRight = mDockRight;
mContentBottom = mCurBottom = mDockBottom;
mContentLeft = mCurLeft = mDockLeft;
mContentRight = mCurRight = mDockRight;
if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " + if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
String.format( String.format(
"dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
mDockLeft, mDockTop, mDockRight, mDockBottom, mDockLeft, mDockTop, mDockRight, mDockBottom,
mContentLeft, mContentTop, mContentRight, mContentBottom, mContentLeft, mContentTop, mContentRight, mContentBottom,
mCurLeft, mCurTop, mCurRight, mCurBottom)); mCurLeft, mCurTop, mCurRight, mCurBottom));
} else {
// Status bar can't go away; the part of the screen it
// covers does not exist for anything behind it.
if (mRestrictedScreenTop == r.top) {
mRestrictedScreenTop = r.bottom;
mRestrictedScreenHeight -= (r.bottom-r.top);
} else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
mRestrictedScreenHeight -= (r.bottom-r.top);
}
mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
mContentBottom = mCurBottom = mDockBottom
= mRestrictedScreenTop + mRestrictedScreenHeight;
if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: restricted screen area: ("
+ mRestrictedScreenLeft + ","
+ mRestrictedScreenTop + ","
+ (mRestrictedScreenLeft + mRestrictedScreenWidth) + ","
+ (mRestrictedScreenTop + mRestrictedScreenHeight) + ")");
}
} }
} }
} }
@ -2333,7 +2383,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
"Laying out status bar window: (%d,%d - %d,%d)", "Laying out status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom)); pf.left, pf.top, pf.right, pf.bottom));
} }
} else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 } else if (mCanHideNavigationBar
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
// Asking for layout as if the nav bar is hidden, lets the // Asking for layout as if the nav bar is hidden, lets the
@ -2426,7 +2477,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
pf.bottom = df.bottom = cf.bottom pf.bottom = df.bottom = cf.bottom
= mUnrestrictedScreenTop+mUnrestrictedScreenHeight; = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
} else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 } else if (mCanHideNavigationBar
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
// Asking for layout as if the nav bar is hidden, lets the // Asking for layout as if the nav bar is hidden, lets the
@ -2623,19 +2675,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
// case though. // case though.
if (topIsFullscreen) { if (topIsFullscreen) {
if (mStatusBarCanHide) { if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar"); if (mStatusBar.hideLw(true)) {
if (mStatusBar.hideLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT;
changes |= FINISH_LAYOUT_REDO_LAYOUT;
mHandler.post(new Runnable() { public void run() { mHandler.post(new Runnable() { public void run() {
if (mStatusBarService != null) { if (mStatusBarService != null) {
try { try {
mStatusBarService.collapse(); mStatusBarService.collapse();
} catch (RemoteException ex) {} } catch (RemoteException ex) {}
} }
}}); }});
}
} else if (DEBUG_LAYOUT) { } else if (DEBUG_LAYOUT) {
Log.v(TAG, "Preventing status bar from hiding by policy"); Log.v(TAG, "Preventing status bar from hiding by policy");
} }
@ -2699,30 +2749,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// behind it. // behind it.
return false; return false;
} }
if (false) { if (mStatusBar != null && mStatusBar.isVisibleLw()) {
// Don't do this on the tablet, since the system bar never completely RectF rect = new RectF(mStatusBar.getShownFrameLw());
// covers the screen, and with all its transparency this will for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
// incorrectly think it does cover it when it doesn't. We'll revisit WindowState w = mStatusBarPanels.get(i);
// this later when we re-do the phone status bar. if (w.isVisibleLw()) {
if (mStatusBar != null && mStatusBar.isVisibleLw()) { rect.union(w.getShownFrameLw());
RectF rect = new RectF(mStatusBar.getShownFrameLw());
for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
WindowState w = mStatusBarPanels.get(i);
if (w.isVisibleLw()) {
rect.union(w.getShownFrameLw());
}
}
final int insetw = mRestrictedScreenWidth/10;
final int inseth = mRestrictedScreenHeight/10;
if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
mRestrictedScreenHeight-inseth)) {
// All of the status bar windows put together cover the
// screen, so the app can't be seen. (Note this test doesn't
// work if the rects of these windows are at off offsets or
// sizes, causing gaps in the rect union we have computed.)
return false;
} }
} }
final int insetw = mRestrictedScreenWidth/10;
final int inseth = mRestrictedScreenHeight/10;
if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
mRestrictedScreenHeight-inseth)) {
// All of the status bar windows put together cover the
// screen, so the app can't be seen. (Note this test doesn't
// work if the rects of these windows are at odd offsets or
// sizes, causing gaps in the rect union we have computed.)
return false;
}
} }
return true; return true;
} }
@ -2776,7 +2820,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
void setHdmiPlugged(boolean plugged) { void setHdmiPlugged(boolean plugged) {
if (mHdmiPlugged != plugged) { if (mHdmiPlugged != plugged) {
mHdmiPlugged = plugged; mHdmiPlugged = plugged;
updateRotation(true); if (plugged && mDisplay != null) {
mExternalDisplayWidth = mDisplay.getRawExternalWidth();
mExternalDisplayHeight = mDisplay.getRawExternalHeight();
}
updateRotation(true, true);
Intent intent = new Intent(ACTION_HDMI_PLUGGED); Intent intent = new Intent(ACTION_HDMI_PLUGGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
@ -3871,7 +3919,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
void updateRotation(boolean alwaysSendConfiguration) { void updateRotation(boolean alwaysSendConfiguration) {
try { try {
//set orientation on WindowManager //set orientation on WindowManager
mWindowManager.updateRotation(alwaysSendConfiguration); mWindowManager.updateRotation(alwaysSendConfiguration, false);
} catch (RemoteException e) {
// Ignore
}
}
void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
try {
//set orientation on WindowManager
mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
} catch (RemoteException e) { } catch (RemoteException e) {
// Ignore // Ignore
} }

View File

@ -5109,7 +5109,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.enableScreenAfterBoot(); mPolicy.enableScreenAfterBoot();
// Make sure the last requested orientation has been applied. // Make sure the last requested orientation has been applied.
updateRotationUnchecked(false); updateRotationUnchecked(false, false);
} }
public void showBootMessage(final CharSequence msg, final boolean always) { public void showBootMessage(final CharSequence msg, final boolean always) {
@ -5383,7 +5383,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
rotation == -1 ? mRotation : rotation); rotation == -1 ? mRotation : rotation);
updateRotationUnchecked(false); updateRotationUnchecked(false, false);
} }
/** /**
@ -5399,7 +5399,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used
updateRotationUnchecked(false); updateRotationUnchecked(false, false);
} }
/** /**
@ -5409,8 +5409,8 @@ public class WindowManagerService extends IWindowManager.Stub
* such that the current rotation might need to be updated, such as when the * such that the current rotation might need to be updated, such as when the
* device is docked or rotated into a new posture. * device is docked or rotated into a new posture.
*/ */
public void updateRotation(boolean alwaysSendConfiguration) { public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
updateRotationUnchecked(alwaysSendConfiguration); updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
} }
/** /**
@ -5440,8 +5440,7 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
public void updateRotationUnchecked( public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
boolean alwaysSendConfiguration) {
if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
+ "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
@ -5449,6 +5448,10 @@ public class WindowManagerService extends IWindowManager.Stub
boolean changed; boolean changed;
synchronized(mWindowMap) { synchronized(mWindowMap) {
changed = updateRotationUncheckedLocked(false); changed = updateRotationUncheckedLocked(false);
if (!changed || forceRelayout) {
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
}
} }
if (changed || alwaysSendConfiguration) { if (changed || alwaysSendConfiguration) {
@ -6641,7 +6644,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
mDisplay.getRawWidth(), mDisplay.getRawHeight(), mDisplay.getRawWidth(), mDisplay.getRawHeight(),
mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight); mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
} }
try { try {
@ -7361,7 +7364,7 @@ public class WindowManagerService extends IWindowManager.Stub
mBaseDisplayWidth = width; mBaseDisplayWidth = width;
mBaseDisplayHeight = height; mBaseDisplayHeight = height;
} }
mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight); mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight);
mLayoutNeeded = true; mLayoutNeeded = true;
@ -7393,8 +7396,8 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
public boolean canStatusBarHide() { public boolean hasSystemNavBar() {
return mPolicy.canStatusBarHide(); return mPolicy.hasSystemNavBar();
} }
// ------------------------------------------------------------- // -------------------------------------------------------------

View File

@ -870,6 +870,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true; return true;
} }
@Override
public boolean hideLw(boolean doAnimation) { public boolean hideLw(boolean doAnimation) {
return hideLw(doAnimation, true); return hideLw(doAnimation, true);
} }
@ -912,6 +913,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true; return true;
} }
@Override
public boolean isAlive() {
return mClient.asBinder().isBinderAlive();
}
private static void applyInsets(Region outRegion, Rect frame, Rect inset) { private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
outRegion.set( outRegion.set(
frame.left + inset.left, frame.top + inset.top, frame.left + inset.left, frame.top + inset.top,

View File

@ -412,7 +412,7 @@ public class WindowManagerPermissionTests extends TestCase {
@SmallTest @SmallTest
public void testSET_ORIENTATION() { public void testSET_ORIENTATION() {
try { try {
mWm.updateRotation(true); mWm.updateRotation(true, false);
mWm.getSwitchState(0); mWm.getSwitchState(0);
fail("IWindowManager.updateRotation did not throw SecurityException as" fail("IWindowManager.updateRotation did not throw SecurityException as"
+ " expected"); + " expected");

View File

@ -88,7 +88,7 @@ public class BridgeWindowManager implements IWindowManager {
// ---- unused implementation of IWindowManager ---- // ---- unused implementation of IWindowManager ----
@Override @Override
public boolean canStatusBarHide() throws RemoteException { public boolean hasSystemNavBar() throws RemoteException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@ -468,9 +468,8 @@ public class BridgeWindowManager implements IWindowManager {
} }
@Override @Override
public void updateRotation(boolean arg0) throws RemoteException { public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override @Override