From c652de8141f5b8e3c6bcf8916842b6e106413b1a Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 15 Feb 2013 16:32:56 -0800 Subject: Implement display overscan support. The window manager now keeps track of the overscan of each display, with an API to set it. The overscan impacts how it positions windows in the display. There is a new set of APIs for windows to say they would like to go into the overscan region. There is a call into the window manager to set the overscan region for a display, and it now has a concept of display settings that it stores presistently. Also added a new "wm" command, moving the window manager specific commands from the "am" command to there and adding a new now to set the overscan region. Change-Id: Id2c8092db64fd0a982274fedac7658d82f30f9ff --- api/current.txt | 9 + cmds/am/src/com/android/commands/am/Am.java | 90 +------- cmds/wm/Android.mk | 28 +++ cmds/wm/MODULE_LICENSE_APACHE2 | 0 cmds/wm/NOTICE | 190 ++++++++++++++++ cmds/wm/src/com/android/commands/wm/Wm.java | 241 +++++++++++++++++++++ cmds/wm/wm | 6 + core/java/android/view/Display.java | 14 ++ core/java/android/view/DisplayInfo.java | 101 ++++++++- core/java/android/view/IWindowManager.aidl | 2 + core/java/android/view/WindowManager.java | 16 +- core/java/android/view/WindowManagerPolicy.java | 6 + core/res/res/values/attrs.xml | 3 + core/res/res/values/public.xml | 14 ++ core/res/res/values/themes.xml | 43 ++++ core/res/res/values/themes_device_defaults.xml | 14 +- .../android/internal/policy/impl/PhoneWindow.java | 12 +- .../internal/policy/impl/PhoneWindowManager.java | 233 ++++++++++++-------- .../server/display/DisplayManagerService.java | 12 + .../com/android/server/display/LogicalDisplay.java | 13 ++ .../java/com/android/server/wm/DisplayContent.java | 5 +- .../com/android/server/wm/DisplaySettings.java | 224 +++++++++++++++++++ .../android/server/wm/WindowManagerService.java | 92 +++++++- 23 files changed, 1156 insertions(+), 212 deletions(-) create mode 100644 cmds/wm/Android.mk create mode 100644 cmds/wm/MODULE_LICENSE_APACHE2 create mode 100644 cmds/wm/NOTICE create mode 100644 cmds/wm/src/com/android/commands/wm/Wm.java create mode 100755 cmds/wm/wm create mode 100644 services/java/com/android/server/wm/DisplaySettings.java diff --git a/api/current.txt b/api/current.txt index 50438e6..a6119b6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1174,6 +1174,7 @@ package android { field public static final int windowMinWidthMinor = 16843607; // 0x1010357 field public static final int windowNoDisplay = 16843294; // 0x101021e field public static final int windowNoTitle = 16842838; // 0x1010056 + field public static final int windowOverscan = 16843727; // 0x10103cf field public static final int windowShowAnimation = 16842934; // 0x10100b6 field public static final int windowShowWallpaper = 16843410; // 0x1010292 field public static final int windowSoftInputMode = 16843307; // 0x101022b @@ -1693,6 +1694,7 @@ package android { field public static final int Theme_Black = 16973832; // 0x1030008 field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009 field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a + field public static final int Theme_Black_NoTitleBar_Overscan = 16974303; // 0x10301df field public static final int Theme_DeviceDefault = 16974120; // 0x1030128 field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136 @@ -1711,9 +1713,11 @@ package android { field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth = 16974133; // 0x1030135 field public static final int Theme_DeviceDefault_Light_NoActionBar = 16974124; // 0x103012c field public static final int Theme_DeviceDefault_Light_NoActionBar_Fullscreen = 16974125; // 0x103012d + field public static final int Theme_DeviceDefault_Light_NoActionBar_Overscan = 16974307; // 0x10301e3 field public static final int Theme_DeviceDefault_Light_Panel = 16974139; // 0x103013b field public static final int Theme_DeviceDefault_NoActionBar = 16974121; // 0x1030129 field public static final int Theme_DeviceDefault_NoActionBar_Fullscreen = 16974122; // 0x103012a + field public static final int Theme_DeviceDefault_NoActionBar_Overscan = 16974306; // 0x10301e2 field public static final int Theme_DeviceDefault_Panel = 16974138; // 0x103013a field public static final int Theme_DeviceDefault_Wallpaper = 16974140; // 0x103013c field public static final int Theme_DeviceDefault_Wallpaper_NoTitleBar = 16974141; // 0x103013d @@ -1736,9 +1740,11 @@ package android { field public static final int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076 field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0 field public static final int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1 + field public static final int Theme_Holo_Light_NoActionBar_Overscan = 16974305; // 0x10301e1 field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d + field public static final int Theme_Holo_NoActionBar_Overscan = 16974304; // 0x10301e0 field public static final int Theme_Holo_Panel = 16973947; // 0x103007b field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e @@ -1746,12 +1752,14 @@ package android { field public static final int Theme_Light = 16973836; // 0x103000c field public static final int Theme_Light_NoTitleBar = 16973837; // 0x103000d field public static final int Theme_Light_NoTitleBar_Fullscreen = 16973838; // 0x103000e + field public static final int Theme_Light_NoTitleBar_Overscan = 16974302; // 0x10301de field public static final int Theme_Light_Panel = 16973914; // 0x103005a field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062 field public static final int Theme_NoDisplay = 16973909; // 0x1030055 field public static final int Theme_NoTitleBar = 16973830; // 0x1030006 field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007 field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a + field public static final int Theme_NoTitleBar_Overscan = 16974301; // 0x10301dd field public static final int Theme_Panel = 16973913; // 0x1030059 field public static final int Theme_Translucent = 16973839; // 0x103000f field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010 @@ -26245,6 +26253,7 @@ package android.view { field public static final int FLAG_IGNORE_CHEEK_PRESSES = 32768; // 0x8000 field public static final int FLAG_KEEP_SCREEN_ON = 128; // 0x80 field public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000 + field public static final int FLAG_LAYOUT_IN_OVERSCAN = 33554432; // 0x2000000 field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100 field public static final int FLAG_LAYOUT_NO_LIMITS = 512; // 0x200 field public static final int FLAG_NOT_FOCUSABLE = 8; // 0x8 diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 3c1fbfe..9fa7dbb 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -26,7 +26,6 @@ import android.app.IInstrumentationWatcher; import android.app.Instrumentation; import android.app.UiAutomationConnection; import android.content.ComponentName; -import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; import android.content.pm.IPackageManager; @@ -39,7 +38,6 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.util.AndroidException; -import android.view.Display; import android.view.IWindowManager; import java.io.BufferedReader; @@ -134,10 +132,6 @@ public class Am { runMonitor(); } else if (op.equals("screen-compat")) { runScreenCompat(); - } else if (op.equals("display-size")) { - runDisplaySize(); - } else if (op.equals("display-density")) { - runDisplayDensity(); } else if (op.equals("to-uri")) { runToUri(false); } else if (op.equals("to-intent-uri")) { @@ -1201,82 +1195,6 @@ public class Am { } while (packageName != null); } - private void runDisplaySize() throws Exception { - String size = nextArgRequired(); - int w, h; - if ("reset".equals(size)) { - w = h = -1; - } else { - int div = size.indexOf('x'); - if (div <= 0 || div >= (size.length()-1)) { - System.err.println("Error: bad size " + size); - return; - } - String wstr = size.substring(0, div); - String hstr = size.substring(div+1); - try { - w = Integer.parseInt(wstr); - h = Integer.parseInt(hstr); - } catch (NumberFormatException e) { - System.err.println("Error: bad number " + e); - return; - } - } - - IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.checkService( - Context.WINDOW_SERVICE)); - if (wm == null) { - System.err.println(NO_SYSTEM_ERROR_CODE); - throw new AndroidException("Can't connect to window manager; is the system running?"); - } - - try { - if (w >= 0 && h >= 0) { - // TODO(multidisplay): For now Configuration only applies to main screen. - wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); - } else { - wm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); - } - } catch (RemoteException e) { - } - } - - private void runDisplayDensity() throws Exception { - String densityStr = nextArgRequired(); - int density; - if ("reset".equals(densityStr)) { - density = -1; - } else { - try { - density = Integer.parseInt(densityStr); - } catch (NumberFormatException e) { - System.err.println("Error: bad number " + e); - return; - } - if (density < 72) { - System.err.println("Error: density must be >= 72"); - return; - } - } - - IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.checkService( - Context.WINDOW_SERVICE)); - if (wm == null) { - System.err.println(NO_SYSTEM_ERROR_CODE); - throw new AndroidException("Can't connect to window manager; is the system running?"); - } - - try { - if (density > 0) { - // TODO(multidisplay): For now Configuration only applies to main screen. - wm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); - } else { - wm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); - } - } catch (RemoteException e) { - } - } - private void runToUri(boolean intentScheme) throws Exception { Intent intent = makeIntent(UserHandle.USER_CURRENT); System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0)); @@ -1454,8 +1372,6 @@ public class Am { " am clear-debug-app\n" + " am monitor [--gdb ]\n" + " am screen-compat [on|off] \n" + - " am display-size [reset|WxH]\n" + - " am display-density [reset|DENSITY]\n" + " am to-uri [INTENT]\n" + " am to-intent-uri [INTENT]\n" + " am switch-user \n" + @@ -1524,17 +1440,13 @@ public class Am { "am clear-debug-app: clear the previously set-debug-app.\n" + "\n" + "am bug-report: request bug report generation; will launch UI\n" + - " when done to select where it should be delivered." + + " when done to select where it should be delivered.\n" + "\n" + "am monitor: start monitoring for crashes or ANRs.\n" + " --gdb: start gdbserv on the given port at crash/ANR\n" + "\n" + "am screen-compat: control screen compatibility mode of .\n" + "\n" + - "am display-size: override display size.\n" + - "\n" + - "am display-density: override display density.\n" + - "\n" + "am to-uri: print the given Intent specification as a URI.\n" + "\n" + "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + diff --git a/cmds/wm/Android.mk b/cmds/wm/Android.mk new file mode 100644 index 0000000..a255cae --- /dev/null +++ b/cmds/wm/Android.mk @@ -0,0 +1,28 @@ +# Copyright 2013 The Android Open Source Project +# +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_MODULE := wm +include $(BUILD_JAVA_LIBRARY) + +include $(CLEAR_VARS) + +NOTICE_FILE := NOTICE +files_noticed := bin/wm + +# Generate rules for a single file. The argument is the file path relative to +# the installation root +define make-notice-file + +$(TARGET_OUT_NOTICE_FILES)/src/$(1).txt: $(LOCAL_PATH)/$(NOTICE_FILE) + @echo Notice file: $$< -- $$@ + @mkdir -p $$(dir $$@) + @cat $$< >> $$@ + +$(TARGET_OUT_NOTICE_FILES)/hash-timestamp: $(TARGET_OUT_NOTICE_FILES)/src/$(1).txt + +endef + +$(foreach file,$(files_noticed),$(eval $(call make-notice-file,$(file)))) diff --git a/cmds/wm/MODULE_LICENSE_APACHE2 b/cmds/wm/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 diff --git a/cmds/wm/NOTICE b/cmds/wm/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/cmds/wm/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java new file mode 100644 index 0000000..f48764f --- /dev/null +++ b/cmds/wm/src/com/android/commands/wm/Wm.java @@ -0,0 +1,241 @@ +/* +** +** Copyright 2013, 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.commands.wm; + +import android.content.Context; +import android.graphics.Rect; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.AndroidException; +import android.view.Display; +import android.view.IWindowManager; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Wm { + + private IWindowManager mWm; + private String[] mArgs; + private int mNextArg; + private String mCurArgData; + + // These are magic strings understood by the Eclipse plugin. + private static final String FATAL_ERROR_CODE = "Error type 1"; + private static final String NO_SYSTEM_ERROR_CODE = "Error type 2"; + private static final String NO_CLASS_ERROR_CODE = "Error type 3"; + + /** + * Command-line entry point. + * + * @param args The command-line arguments + */ + public static void main(String[] args) { + try { + (new Wm()).run(args); + } catch (IllegalArgumentException e) { + showUsage(); + System.err.println("Error: " + e.getMessage()); + } catch (Exception e) { + e.printStackTrace(System.err); + System.exit(1); + } + } + + private void run(String[] args) throws Exception { + if (args.length < 1) { + showUsage(); + return; + } + + mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( + Context.WINDOW_SERVICE)); + if (mWm == null) { + System.err.println(NO_SYSTEM_ERROR_CODE); + throw new AndroidException("Can't connect to window manager; is the system running?"); + } + + mArgs = args; + String op = args[0]; + mNextArg = 1; + + if (op.equals("size")) { + runDisplaySize(); + } else if (op.equals("density")) { + runDisplayDensity(); + } else if (op.equals("overscan")) { + runDisplayOverscan(); + } else { + throw new IllegalArgumentException("Unknown command: " + op); + } + } + + private void runDisplaySize() throws Exception { + String size = nextArgRequired(); + int w, h; + if ("reset".equals(size)) { + w = h = -1; + } else { + int div = size.indexOf('x'); + if (div <= 0 || div >= (size.length()-1)) { + System.err.println("Error: bad size " + size); + return; + } + String wstr = size.substring(0, div); + String hstr = size.substring(div+1); + try { + w = Integer.parseInt(wstr); + h = Integer.parseInt(hstr); + } catch (NumberFormatException e) { + System.err.println("Error: bad number " + e); + return; + } + } + + try { + if (w >= 0 && h >= 0) { + // TODO(multidisplay): For now Configuration only applies to main screen. + mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); + } else { + mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); + } + } catch (RemoteException e) { + } + } + + private void runDisplayDensity() throws Exception { + String densityStr = nextArgRequired(); + int density; + if ("reset".equals(densityStr)) { + density = -1; + } else { + try { + density = Integer.parseInt(densityStr); + } catch (NumberFormatException e) { + System.err.println("Error: bad number " + e); + return; + } + if (density < 72) { + System.err.println("Error: density must be >= 72"); + return; + } + } + + try { + if (density > 0) { + // TODO(multidisplay): For now Configuration only applies to main screen. + mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); + } else { + mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); + } + } catch (RemoteException e) { + } + } + + private void runDisplayOverscan() throws Exception { + String overscanStr = nextArgRequired(); + Rect rect = new Rect(); + int density; + if ("reset".equals(overscanStr)) { + rect.set(0, 0, 0, 0); + } else { + final Pattern FLATTENED_PATTERN = Pattern.compile( + "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)"); + Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr); + if (!matcher.matches()) { + System.err.println("Error: bad rectangle arg: " + overscanStr); + return; + } + rect.left = Integer.parseInt(matcher.group(1)); + rect.top = Integer.parseInt(matcher.group(2)); + rect.right = Integer.parseInt(matcher.group(3)); + rect.bottom = Integer.parseInt(matcher.group(4)); + } + + try { + mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom); + } catch (RemoteException e) { + } + } + + private String nextOption() { + if (mCurArgData != null) { + String prev = mArgs[mNextArg - 1]; + throw new IllegalArgumentException("No argument expected after \"" + prev + "\""); + } + if (mNextArg >= mArgs.length) { + return null; + } + String arg = mArgs[mNextArg]; + if (!arg.startsWith("-")) { + return null; + } + mNextArg++; + if (arg.equals("--")) { + return null; + } + if (arg.length() > 1 && arg.charAt(1) != '-') { + if (arg.length() > 2) { + mCurArgData = arg.substring(2); + return arg.substring(0, 2); + } else { + mCurArgData = null; + return arg; + } + } + mCurArgData = null; + return arg; + } + + private String nextArg() { + if (mCurArgData != null) { + String arg = mCurArgData; + mCurArgData = null; + return arg; + } else if (mNextArg < mArgs.length) { + return mArgs[mNextArg++]; + } else { + return null; + } + } + + private String nextArgRequired() { + String arg = nextArg(); + if (arg == null) { + String prev = mArgs[mNextArg - 1]; + throw new IllegalArgumentException("Argument expected after \"" + prev + "\""); + } + return arg; + } + + private static void showUsage() { + System.err.println( + "usage: wm [subcommand] [options]\n" + + " wm size [reset|WxH]\n" + + " wm density [reset|DENSITY]\n" + + " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" + + "\n" + + "wm size: override display size.\n" + + "\n" + + "wm density: override display density.\n" + + "\n" + + "wm overscan: set overscan area for display.\n" + ); + } +} diff --git a/cmds/wm/wm b/cmds/wm/wm new file mode 100755 index 0000000..f7a5bc7 --- /dev/null +++ b/cmds/wm/wm @@ -0,0 +1,6 @@ +# Script to start "wm" on the device, which has a very rudimentary +# shell. +# +base=/system +export CLASSPATH=$base/framework/wm.jar +exec app_process $base/bin com.android.commands.wm.Wm "$@" diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 758abb5..e6a7950 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -437,6 +437,20 @@ public final class Display { } /** + * @hide + * Return a rectangle defining the insets of the overscan region of the display. + * Each field of the rectangle is the number of pixels the overscan area extends + * into the display on that side. + */ + public void getOverscanInsets(Rect outRect) { + synchronized (this) { + updateDisplayInfoLocked(); + outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop, + mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom); + } + } + + /** * Returns the rotation of the screen from its "natural" orientation. * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 305fd5c..9fcd9b1 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -109,6 +109,30 @@ public final class DisplayInfo implements Parcelable { public int logicalHeight; /** + * @hide + * Number of overscan pixels on the left side of the display. + */ + public int overscanLeft; + + /** + * @hide + * Number of overscan pixels on the top side of the display. + */ + public int overscanTop; + + /** + * @hide + * Number of overscan pixels on the right side of the display. + */ + public int overscanRight; + + /** + * @hide + * Number of overscan pixels on the bottom side of the display. + */ + public int overscanBottom; + + /** * The rotation of the display relative to its natural orientation. * May be one of {@link android.view.Surface#ROTATION_0}, * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, @@ -196,6 +220,10 @@ public final class DisplayInfo implements Parcelable { && largestNominalAppHeight == other.largestNominalAppHeight && logicalWidth == other.logicalWidth && logicalHeight == other.logicalHeight + && overscanLeft == other.overscanLeft + && overscanTop == other.overscanTop + && overscanRight == other.overscanRight + && overscanBottom == other.overscanBottom && rotation == other.rotation && refreshRate == other.refreshRate && logicalDensityDpi == other.logicalDensityDpi @@ -222,6 +250,10 @@ public final class DisplayInfo implements Parcelable { largestNominalAppHeight = other.largestNominalAppHeight; logicalWidth = other.logicalWidth; logicalHeight = other.logicalHeight; + overscanLeft = other.overscanLeft; + overscanTop = other.overscanTop; + overscanRight = other.overscanRight; + overscanBottom = other.overscanBottom; rotation = other.rotation; refreshRate = other.refreshRate; logicalDensityDpi = other.logicalDensityDpi; @@ -243,6 +275,10 @@ public final class DisplayInfo implements Parcelable { largestNominalAppHeight = source.readInt(); logicalWidth = source.readInt(); logicalHeight = source.readInt(); + overscanLeft = source.readInt(); + overscanTop = source.readInt(); + overscanRight = source.readInt(); + overscanBottom = source.readInt(); rotation = source.readInt(); refreshRate = source.readFloat(); logicalDensityDpi = source.readInt(); @@ -265,6 +301,10 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(largestNominalAppHeight); dest.writeInt(logicalWidth); dest.writeInt(logicalHeight); + dest.writeInt(overscanLeft); + dest.writeInt(overscanTop); + dest.writeInt(overscanRight); + dest.writeInt(overscanBottom); dest.writeInt(rotation); dest.writeFloat(refreshRate); dest.writeInt(logicalDensityDpi); @@ -318,18 +358,55 @@ public final class DisplayInfo implements Parcelable { // For debugging purposes @Override public String toString() { - return "DisplayInfo{\"" + name + "\", app " + appWidth + " x " + appHeight - + ", real " + logicalWidth + " x " + logicalHeight - + ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight - + ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight - + ", " + refreshRate + " fps" - + ", rotation " + rotation - + ", density " + logicalDensityDpi - + ", " + physicalXDpi + " x " + physicalYDpi + " dpi" - + ", layerStack " + layerStack - + ", type " + Display.typeToString(type) - + ", address " + address - + flagsToString(flags) + "}"; + StringBuilder sb = new StringBuilder(); + sb.append("DisplayInfo{\""); + sb.append(name); + sb.append("\", app "); + sb.append(appWidth); + sb.append(" x "); + sb.append(appHeight); + sb.append(", real "); + sb.append(logicalWidth); + sb.append(" x "); + sb.append(logicalHeight); + if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) { + sb.append(", overscan ("); + sb.append(overscanLeft); + sb.append(","); + sb.append(overscanTop); + sb.append(","); + sb.append(overscanRight); + sb.append(","); + sb.append(overscanBottom); + sb.append(")"); + } + sb.append(", largest app "); + sb.append(largestNominalAppWidth); + sb.append(" x "); + sb.append(largestNominalAppHeight); + sb.append(", smallest app "); + sb.append(smallestNominalAppWidth); + sb.append(" x "); + sb.append(smallestNominalAppHeight); + sb.append(", "); + sb.append(refreshRate); + sb.append(" fps, rotation"); + sb.append(rotation); + sb.append(", density "); + sb.append(logicalDensityDpi); + sb.append(" ("); + sb.append(physicalXDpi); + sb.append(" x "); + sb.append(physicalYDpi); + sb.append(") dpi, layerStack "); + sb.append(layerStack); + sb.append(", type "); + sb.append(Display.typeToString(type)); + sb.append(", address "); + sb.append(address); + sb.append(flagsToString(flags)); + sb.append("}"); + return sb.toString(); } private static String flagsToString(int flags) { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 885327c..e4ecb5c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -65,6 +65,8 @@ interface IWindowManager void setForcedDisplayDensity(int displayId, int density); void clearForcedDisplayDensity(int displayId); + void setOverscan(int displayId, int left, int top, int right, int bottom); + // Is the device configured to have a full system bar for larger screens? boolean hasSystemNavBar(); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 6a67d8b..d236561 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -735,20 +735,20 @@ public interface WindowManager extends ViewManager { /** *

Indicates whether this window should be hardware accelerated. * Requesting hardware acceleration does not guarantee it will happen.

- * + * *

This flag can be controlled programmatically only to enable * hardware acceleration. To enable hardware acceleration for a given * window programmatically, do the following:

- * + * *
          * Window w = activity.getWindow(); // in Activity's onCreate() for instance
          * w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
          *         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
          * 
- * + * *

It is important to remember that this flag must * be set before setting the content view of your activity or dialog.

- * + * *

This flag cannot be used to disable hardware acceleration after it * was enabled in your manifest using * {@link android.R.attr#hardwareAccelerated}. If you need to selectively @@ -756,13 +756,19 @@ public interface WindowManager extends ViewManager { * for instance), make sure it is turned off in your manifest and enable it * on your activity or dialog when you need it instead, using the method * described above.

- * + * *

This flag is automatically set by the system if the * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated} * XML attribute is set to true on an activity or on the application.

*/ public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000; + /** Window flag: allow window contents to extend in to the screen's + * overscan area, if there is one. The window should still correctly + * position its contents to take the overscan area into account. + */ + public static final int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000; + // ----- HIDDEN FLAGS. // These start at the high bit and go down. diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index b5d216a..192eded 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -458,6 +458,12 @@ public interface WindowManagerPolicy { public void setInitialDisplaySize(Display display, int width, int height, int density); /** + * Called by window manager to set the overscan region that should be used for the + * given display. + */ + public void setDisplayOverscan(Display display, int left, int top, int right, int bottom); + + /** * Check permissions when adding a window. * * @param attrs The window's LayoutParams. diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a3e5b2c..c73ff81 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -312,6 +312,8 @@ + + @@ -1562,6 +1564,7 @@ + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 0d80082..42e5cf1 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2036,4 +2036,18 @@ + + + + + + + + + + + + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 75850dd..411419b 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -166,6 +166,7 @@ please see themes_device_defaults.xml. @null false false + false false @null false @@ -403,6 +404,14 @@ please see themes_device_defaults.xml. @null + + + + + + + + + + + + + diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index 4178cc4..71aa5e6 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -202,12 +202,17 @@ easier. + + + + + +