diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-08-19 20:30:52 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-08-19 22:42:08 -0700 |
commit | 98365d7663cbd82979a5700faf0050220b01084d (patch) | |
tree | 8a4ff3e0a8afd814ed29609b26aa1c6ade2367f6 /core/java/android | |
parent | 848c2dc93b6795e171f3dd6f64ea0be65e2762ca (diff) | |
download | frameworks_base-98365d7663cbd82979a5700faf0050220b01084d.zip frameworks_base-98365d7663cbd82979a5700faf0050220b01084d.tar.gz frameworks_base-98365d7663cbd82979a5700faf0050220b01084d.tar.bz2 |
Refactor for multi-display support.
Split WindowManagerImpl into two parts, the WindowManager
interface implementation remains where it is but the global
communications with the window manager are now handled by
the WindowManagerGlobal class. This change greatly simplifies
the challenge of having separate WindowManager instances
for each Context.
Removed WindowManagerImpl.getDefault(). This represents the
bulk of this change. Most of the usages of this method were
either to perform global functions (now handled by WindowManagerGlobal)
or to obtain the default display (now handled by DisplayManager).
Explicitly associate each new window with a display and make
the Display object available to the View hierarchy.
Add stubs for some new display manager API features.
Start to split apart the concepts of display id and layer stack.
since they operate at different layers of abstraction.
While it's true that each logical display uniquely corresponds to a
surface flinger layer stack, it is not necessarily the case that
they must use the same ids. Added Display.getLayerStack()
and started using it in places where it was relatively easy to do.
Change-Id: I29ed909114dec86807c4d3a5059c3fa0358bea61
Diffstat (limited to 'core/java/android')
26 files changed, 919 insertions, 691 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 77107ee..395a79c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -74,7 +74,7 @@ import android.view.ViewGroup.LayoutParams; import android.view.ViewManager; import android.view.Window; import android.view.WindowManager; -import android.view.WindowManagerImpl; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.widget.AdapterView; @@ -5018,7 +5018,9 @@ public class Activity extends ContextThemeWrapper mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; - mWindow.setWindowManager(null, mToken, mComponent.flattenToString(), + mWindow.setWindowManager( + (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), + mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); @@ -5065,7 +5067,7 @@ public class Activity extends ContextThemeWrapper if (mStopped) { mStopped = false; if (mToken != null && mParent == null) { - WindowManagerImpl.getDefault().setStoppedState(mToken, false); + WindowManagerGlobal.getInstance().setStoppedState(mToken, false); } synchronized (mManagedCursors) { @@ -5165,7 +5167,7 @@ public class Activity extends ContextThemeWrapper } if (mToken != null && mParent == null) { - WindowManagerImpl.getDefault().setStoppedState(mToken, true); + WindowManagerGlobal.getInstance().setStoppedState(mToken, true); } mFragments.dispatchStop(); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 2c6d5d9..58e6616 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Point; +import android.hardware.display.DisplayManager; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -366,7 +367,7 @@ public class ActivityManager { * (which tends to consume a lot more RAM). * @hide */ - static public boolean isHighEndGfx(Display display) { + static public boolean isHighEndGfx() { MemInfoReader reader = new MemInfoReader(); reader.readMemInfo(); if (reader.getTotalSize() >= (512*1024*1024)) { @@ -374,6 +375,8 @@ public class ActivityManager { // we can afford the overhead of graphics acceleration. return true; } + + Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); Point p = new Point(); display.getRealSize(p); int pixels = p.x * p.y; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 2cdb086..a3880f3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -42,6 +42,7 @@ import android.database.sqlite.SQLiteDebug; import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.hardware.display.DisplayManager; import android.net.IConnectivityManager; import android.net.Proxy; import android.net.ProxyProperties; @@ -79,7 +80,7 @@ import android.view.ViewManager; import android.view.ViewRootImpl; import android.view.Window; import android.view.WindowManager; -import android.view.WindowManagerImpl; +import android.view.WindowManagerGlobal; import android.renderscript.RenderScript; import com.android.internal.os.BinderInternal; @@ -1055,7 +1056,7 @@ public final class ActivityThread { @Override public void dumpGfxInfo(FileDescriptor fd, String[] args) { dumpGraphicsInfo(fd); - WindowManagerImpl.getDefault().dumpGfxInfo(fd); + WindowManagerGlobal.getInstance().dumpGfxInfo(fd); } @Override @@ -1569,7 +1570,7 @@ public final class ActivityThread { CompatibilityInfoHolder cih = new CompatibilityInfoHolder(); cih.set(ci); - Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay(); + Display d = displayManager.getCompatibleDisplay(Display.DEFAULT_DISPLAY, cih); d.getMetrics(dm); //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h=" // + metrics.heightPixels + " den=" + metrics.density @@ -2641,7 +2642,7 @@ public final class ActivityThread { r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow); IBinder wtoken = r.mPendingRemoveWindow.getWindowToken(); if (wtoken != null) { - WindowManagerImpl.getDefault().closeAll(wtoken, + WindowManagerGlobal.getInstance().closeAll(wtoken, r.activity.getClass().getName(), "Activity"); } } @@ -3176,7 +3177,7 @@ public final class ActivityThread { apk.mCompatibilityInfo.set(data.info); } handleConfigurationChanged(mConfiguration, data.info); - WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration); + WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration); } private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) { @@ -3365,7 +3366,7 @@ public final class ActivityThread { } } if (wtoken != null && r.mPendingRemoveWindow == null) { - WindowManagerImpl.getDefault().closeAll(wtoken, + WindowManagerGlobal.getInstance().closeAll(wtoken, r.activity.getClass().getName(), "Activity"); } r.activity.mDecor = null; @@ -3377,7 +3378,7 @@ public final class ActivityThread { // by the app will leak. Well we try to warning them a lot // about leaking windows, because that is a bug, so if they are // using this recreate facility then they get to live with leaks. - WindowManagerImpl.getDefault().closeAll(token, + WindowManagerGlobal.getInstance().closeAll(token, r.activity.getClass().getName(), "Activity"); } @@ -3805,7 +3806,7 @@ public final class ActivityThread { } // Cleanup hardware accelerated stuff - WindowManagerImpl.getDefault().trimLocalMemory(); + WindowManagerGlobal.getInstance().trimLocalMemory(); freeTextLayoutCachesIfNeeded(configDiff); @@ -3945,7 +3946,7 @@ public final class ActivityThread { final void handleTrimMemory(int level) { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level); - final WindowManagerImpl windowManager = WindowManagerImpl.getDefault(); + final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance(); windowManager.startTrimMemory(level); ArrayList<ComponentCallbacks2> callbacks; @@ -3958,7 +3959,7 @@ public final class ActivityThread { callbacks.get(i).onTrimMemory(level); } - windowManager.endTrimMemory(); + windowManager.endTrimMemory(); } private void setupGraphicsSupport(LoadedApk info, File cacheDir) { @@ -4011,8 +4012,7 @@ public final class ActivityThread { // Persistent processes on low-memory devices do not get to // use hardware accelerated drawing, since this can add too much // overhead to the process. - final Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); - if (!ActivityManager.isHighEndGfx(display)) { + if (!ActivityManager.isHighEndGfx()) { HardwareRenderer.disable(false); } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 08947a4..0543f05 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -95,7 +95,9 @@ import android.telephony.TelephonyManager; import android.content.ClipboardManager; import android.util.AndroidRuntimeException; import android.util.Log; +import android.view.CompatibilityInfoHolder; import android.view.ContextThemeWrapper; +import android.view.Display; import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.InputMethodManager; @@ -499,8 +501,8 @@ class ContextImpl extends Context { registerService(WINDOW_SERVICE, new ServiceFetcher() { public Object getService(ContextImpl ctx) { - return WindowManagerImpl.getDefault().makeCompatible( - ctx.mPackageInfo.mCompatibilityInfo); + return new WindowManagerImpl(ctx.getOuterContext(), + Display.DEFAULT_DISPLAY); }}); registerService(USER_SERVICE, new ServiceFetcher() { @@ -1609,6 +1611,11 @@ class ContextImpl extends Context { return mRestricted; } + @Override + public CompatibilityInfoHolder getCompatibilityInfo() { + return mPackageInfo.mCompatibilityInfo; + } + private File getDataDirFile() { if (mPackageInfo != null) { return mPackageInfo.getDataDirFile(); diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index ef61af7..22a21cd 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -16,13 +16,12 @@ package android.app; -import android.content.Context; import android.os.Binder; import android.os.RemoteException; import android.os.IBinder; -import android.os.ServiceManager; import android.view.IWindowManager; import android.view.IOnKeyguardExitResult; +import android.view.WindowManagerGlobal; /** * Class that can be used to lock and unlock the keyboard. Get an instance of this @@ -111,7 +110,7 @@ public class KeyguardManager { KeyguardManager() { - mWM = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)); + mWM = WindowManagerGlobal.getWindowManagerService(); } /** diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 27843ac..1ad2e6d 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -43,6 +43,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.ViewRootImpl; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import java.io.FileOutputStream; import java.io.IOException; @@ -689,7 +690,7 @@ public class WallpaperManager { public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) { try { //Log.v(TAG, "Sending new wallpaper offsets from app..."); - ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( + WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep); //Log.v(TAG, "...app returning after sending offsets!"); } catch (RemoteException e) { @@ -727,7 +728,7 @@ public class WallpaperManager { int x, int y, int z, Bundle extras) { try { //Log.v(TAG, "Sending new wallpaper offsets from app..."); - ViewRootImpl.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand( + WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand( windowToken, action, x, y, z, extras, false); //Log.v(TAG, "...app returning after sending offsets!"); } catch (RemoteException e) { @@ -747,7 +748,7 @@ public class WallpaperManager { */ public void clearWallpaperOffsets(IBinder windowToken) { try { - ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( + WindowManagerGlobal.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( windowToken, -1, -1, -1, -1); } catch (RemoteException e) { // Ignore. diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a70bf6c..1460bf5 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.util.AttributeSet; +import android.view.CompatibilityInfoHolder; import java.io.File; import java.io.FileInputStream; @@ -2464,6 +2465,16 @@ public abstract class Context { public abstract Context createConfigurationContext(Configuration overrideConfiguration); /** + * Gets the compatibility info holder for this context. This information + * is provided on a per-application basis and is used to simulate lower density + * display metrics for legacy applications. + * + * @return The compatibility info holder, or null if not required by the application. + * @hide + */ + public abstract CompatibilityInfoHolder getCompatibilityInfo(); + + /** * Indicates whether this Context is restricted. * * @return True if this Context is restricted, false otherwise. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 75842be..3a13725 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -31,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; +import android.view.CompatibilityInfoHolder; import java.io.File; import java.io.FileInputStream; @@ -543,4 +544,10 @@ public class ContextWrapper extends Context { public boolean isRestricted() { return mBase.isRestricted(); } + + /** @hide */ + @Override + public CompatibilityInfoHolder getCompatibilityInfo() { + return mBase.getCompatibilityInfo(); + } } diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index dc79710..a73115c 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -17,12 +17,20 @@ package android.hardware.display; import android.content.Context; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import android.util.SparseArray; +import android.view.CompatibilityInfoHolder; +import android.view.Display; import android.view.DisplayInfo; +import java.util.ArrayList; + /** * Manages the properties, media routing and power state of attached displays. * <p> @@ -34,11 +42,22 @@ import android.view.DisplayInfo; */ public final class DisplayManager { private static final String TAG = "DisplayManager"; + private static final boolean DEBUG = false; + + private static final int MSG_DISPLAY_ADDED = 1; + private static final int MSG_DISPLAY_REMOVED = 2; + private static final int MSG_DISPLAY_CHANGED = 3; private static DisplayManager sInstance; private final IDisplayManager mDm; + // Guarded by mDisplayLock + private final Object mDisplayLock = new Object(); + private final ArrayList<DisplayListenerDelegate> mDisplayListeners = + new ArrayList<DisplayListenerDelegate>(); + + private DisplayManager(IDisplayManager dm) { mDm = dm; } @@ -79,4 +98,161 @@ public final class DisplayManager { return false; } } + + /** + * Gets information about a logical display. + * + * The display metrics may be adjusted to provide compatibility + * for legacy applications. + * + * @param displayId The logical display id. + * @param applicationContext The application context from which to obtain + * compatible metrics. + * @return The display object. + */ + public Display getDisplay(int displayId, Context applicationContext) { + if (applicationContext == null) { + throw new IllegalArgumentException("applicationContext must not be null"); + } + + CompatibilityInfoHolder cih = null; + if (displayId == Display.DEFAULT_DISPLAY) { + cih = applicationContext.getCompatibilityInfo(); + } + return getCompatibleDisplay(displayId, cih); + } + + /** + * Gets information about a logical display. + * + * The display metrics may be adjusted to provide compatibility + * for legacy applications. + * + * @param displayId The logical display id. + * @param cih The compatibility info, or null if none is required. + * @return The display object. + * + * @hide + */ + public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) { + return new Display(displayId, cih); + } + + /** + * Gets information about a logical display without applying any compatibility metrics. + * + * @param displayId The logical display id. + * @return The display object. + * + * @hide + */ + public Display getRealDisplay(int displayId) { + return getCompatibleDisplay(displayId, null); + } + + /** + * Registers an display listener to receive notifications about when + * displays are added, removed or changed. + * + * @param listener The listener to register. + * @param handler The handler on which the listener should be invoked, or null + * if the listener should be invoked on the calling thread's looper. + * + * @see #unregisterDisplayListener + */ + public void registerDisplayListener(DisplayListener listener, Handler handler) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + synchronized (mDisplayLock) { + int index = findDisplayListenerLocked(listener); + if (index < 0) { + mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); + } + } + } + + /** + * Unregisters an input device listener. + * + * @param listener The listener to unregister. + * + * @see #registerDisplayListener + */ + public void unregisterDisplayListener(DisplayListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + + synchronized (mDisplayLock) { + int index = findDisplayListenerLocked(listener); + if (index >= 0) { + DisplayListenerDelegate d = mDisplayListeners.get(index); + d.removeCallbacksAndMessages(null); + mDisplayListeners.remove(index); + } + } + } + + private int findDisplayListenerLocked(DisplayListener listener) { + final int numListeners = mDisplayListeners.size(); + for (int i = 0; i < numListeners; i++) { + if (mDisplayListeners.get(i).mListener == listener) { + return i; + } + } + return -1; + } + + /** + * Listens for changes in available display devices. + */ + public interface DisplayListener { + /** + * Called whenever a logical display has been added to the system. + * Use {@link DisplayManager#getDisplay} to get more information about the display. + * + * @param displayId The id of the logical display that was added. + */ + void onDisplayAdded(int displayId); + + /** + * Called whenever a logical display has been removed from the system. + * + * @param displayId The id of the logical display that was removed. + */ + void onDisplayRemoved(int displayId); + + /** + * Called whenever the properties of a logical display have changed. + * + * @param displayId The id of the logical display that changed. + */ + void onDisplayChanged(int displayId); + } + + private static final class DisplayListenerDelegate extends Handler { + public final DisplayListener mListener; + + public DisplayListenerDelegate(DisplayListener listener, Handler handler) { + super(handler != null ? handler.getLooper() : Looper.myLooper()); + mListener = listener; + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DISPLAY_ADDED: + mListener.onDisplayAdded(msg.arg1); + break; + case MSG_DISPLAY_REMOVED: + mListener.onDisplayRemoved(msg.arg1); + break; + case MSG_DISPLAY_CHANGED: + mListener.onDisplayChanged(msg.arg1); + break; + } + } + } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index a9de289..d5b9edc 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -39,7 +39,6 @@ import android.text.method.MovementMethod; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; -import android.view.Display; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -630,7 +629,7 @@ public class InputMethodService extends AbstractInputMethodService { if (mWindow != null) { throw new IllegalStateException("Must be called before onCreate()"); } - if (ActivityManager.isHighEndGfx(new Display(Display.DEFAULT_DISPLAY, null))) { + if (ActivityManager.isHighEndGfx()) { mHardwareAccelerated = true; return true; } diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java index fc3f501..5d6b17e 100644 --- a/core/java/android/service/dreams/DreamManagerService.java +++ b/core/java/android/service/dreams/DreamManagerService.java @@ -18,6 +18,7 @@ import android.provider.Settings; import android.util.Slog; import android.view.IWindowManager; import android.view.WindowManager; +import android.view.WindowManagerGlobal; /** * @@ -44,8 +45,7 @@ public class DreamManagerService public DreamManagerService(Context context) { if (DEBUG) Slog.v(TAG, "DreamManagerService startup"); mContext = context; - mIWindowManager = IWindowManager.Stub.asInterface( - ServiceManager.getService(Context.WINDOW_SERVICE)); + mIWindowManager = WindowManagerGlobal.getWindowManagerService(); } private void checkPermission(String permission) { diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index b513915..efa8911 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -36,7 +36,6 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.PowerManager; -import android.os.Process; import android.os.RemoteException; import android.util.Log; import android.util.LogPrinter; @@ -51,9 +50,8 @@ import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup; -import android.view.ViewRootImpl; import android.view.WindowManager; -import android.view.WindowManagerImpl; +import android.view.WindowManagerGlobal; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -674,8 +672,8 @@ public abstract class WallpaperService extends Service { } } - redrawNeeded |= creating - || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0; + redrawNeeded |= creating || (relayoutResult + & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0; if (forceReport || creating || surfaceCreating || formatChanged || sizeChanged) { @@ -762,7 +760,7 @@ public abstract class WallpaperService extends Service { mWindowToken = wrapper.mWindowToken; mSurfaceHolder.setSizeFromLayout(); mInitializing = true; - mSession = ViewRootImpl.getWindowSession(getMainLooper()); + mSession = WindowManagerGlobal.getWindowSession(getMainLooper()); mWindow.setSession(mSession); diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 6288ce5..392d1f2 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -16,6 +16,7 @@ package android.view; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -165,7 +166,7 @@ public final class Choreographer { mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null; mLastFrameTimeNanos = Long.MIN_VALUE; - Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); + Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); mFrameIntervalNanos = (long)(1000000000 / d.getRefreshRate()); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 5409b38..18eba81 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -67,20 +67,16 @@ public final class Display { private int mCachedAppHeightCompat; /** - * The default Display id. + * The default Display id, which is the id of the built-in primary display + * assuming there is one. */ public static final int DEFAULT_DISPLAY = 0; /** - * Uninitialized display. - * @hide - */ - public static final int NO_DISPLAY = -1; - - /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} - * to get a display object for the default display. + * or {@link android.hardware.display.DisplayManager#getDisplay} + * to get a display object. * * @hide */ @@ -114,6 +110,31 @@ public final class Display { } /** + * Gets the display's layer stack. + * + * Each display has its own independent layer stack upon which surfaces + * are placed to be managed by surface flinger. + * + * @return The layer stack number. + * @hide + */ + public int getLayerStack() { + // Note: This is the current convention but there is no requirement that + // the display id and layer stack id be the same. + return mDisplayId; + } + + /** + * Gets the compatibility info used by this display instance. + * + * @return The compatibility info holder, or null if none is required. + * @hide + */ + public CompatibilityInfoHolder getCompatibilityInfo() { + return mCompatibilityInfo; + } + + /** * Gets the size of the display, in pixels. * <p> * Note that this value should <em>not</em> be used for computing layouts, diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index e93e480..c5d9255 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -59,8 +59,8 @@ interface IWindowSession { * @param requestedWidth The width the window wants to be. * @param requestedHeight The height the window wants to be. * @param viewVisibility Window root view's visibility. - * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING}, - * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}. + * @param flags Request flags: {@link WindowManagerGlobal#RELAYOUT_INSETS_PENDING}, + * {@link WindowManagerGlobal#RELAYOUT_DEFER_SURFACE_DESTROY}. * @param outFrame Rect in which is placed the new position/size on * screen. * @param outContentInsets Rect in which is placed the offsets from @@ -79,8 +79,8 @@ interface IWindowSession { * was last displayed. * @param outSurface Object in which is placed the new display surface. * - * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS}, - * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}. + * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS}, + * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}. */ int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 5f5d1f2..517b514 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -246,22 +246,9 @@ public class Surface implements Parcelable { native private static void nativeClassInit(); static { nativeClassInit(); } - /** create a surface @hide */ - public Surface(SurfaceSession s, - int pid, int displayId, int w, int h, int format, int flags) - throws OutOfResourcesException { - checkHeadless(); - - if (DEBUG_RELEASE) { - mCreationStack = new Exception(); - } - mCanvas = new CompatibleCanvas(); - init(s,pid,null,displayId,w,h,format,flags); - } - /** create a surface with a name @hide */ public Surface(SurfaceSession s, - int pid, String name, int displayId, int w, int h, int format, int flags) + int pid, String name, int layerStack, int w, int h, int format, int flags) throws OutOfResourcesException { checkHeadless(); @@ -269,7 +256,7 @@ public class Surface implements Parcelable { mCreationStack = new Exception(); } mCanvas = new CompatibleCanvas(); - init(s,pid,name,displayId,w,h,format,flags); + init(s, pid, name, layerStack, w, h, format, flags); mName = name; } @@ -470,7 +457,7 @@ public class Surface implements Parcelable { /** @hide */ public native void setWindowCrop(Rect crop); /** @hide */ - public native void setDisplayId(int displayId); + public native void setLayerStack(int layerStack); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index bf570c9..fdf1c22 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -480,10 +480,10 @@ public class SurfaceView extends View { relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, visible ? VISIBLE : GONE, - WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY, + WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mNewSurface); - if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { + if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportDrawNeeded = true; } @@ -516,8 +516,8 @@ public class SurfaceView extends View { SurfaceHolder.Callback callbacks[] = null; - final boolean surfaceChanged = - (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0; + final boolean surfaceChanged = (relayoutResult + & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0; if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { mSurfaceCreated = false; if (mSurface.isValid()) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1684a9e..b1f5e9e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -39,6 +39,7 @@ import android.graphics.Region; import android.graphics.Shader; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -7346,7 +7347,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, outRect.bottom -= insets.bottom; return; } - Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); + Display d = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); d.getRectSize(outRect); } @@ -11622,6 +11623,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Gets the logical display to which the view's window has been attached. + * + * @return The logical display, or null if the view is not currently attached to a window. + */ + public Display getDisplay() { + return mAttachInfo != null ? mAttachInfo.mDisplay : null; + } + + /** * Retrieve private session object this view hierarchy is using to * communicate with the window manager. * @return the session object to communicate with the window manager @@ -17260,6 +17270,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final IBinder mWindowToken; + final Display mDisplay; + final Callbacks mRootCallbacks; HardwareCanvas mHardwareCanvas; @@ -17519,11 +17531,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @param handler the events handler the view must use */ - AttachInfo(IWindowSession session, IWindow window, + AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { mSession = session; mWindow = window; mWindowToken = window.asBinder(); + mDisplay = display; mViewRootImpl = viewRootImpl; mHandler = handler; mRootCallbacks = effectPlayer; diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 3082976..499075e 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -279,7 +279,8 @@ public class ViewConfiguration { mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f); // Size of the screen in bytes, in ARGB_8888 format - final Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); + final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); + final Display display = win.getDefaultDisplay(); final Point size = new Point(); display.getRealSize(size); mMaximumDrawingCacheSize = 4 * size.x * size.y; @@ -288,7 +289,7 @@ public class ViewConfiguration { mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f); if (!sHasPermanentMenuKeySet) { - IWindowManager wm = WindowManagerImpl.getWindowManagerService(); + IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); try { sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar(); sHasPermanentMenuKeySet = true; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 4918d5b..725d9b5 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -18,7 +18,6 @@ package android.view; import android.Manifest; import android.animation.LayoutTransition; -import android.animation.ValueAnimator; import android.app.ActivityManagerNative; import android.content.ClipDescription; import android.content.ComponentCallbacks; @@ -88,7 +87,7 @@ import java.util.HashSet; /** * The top of a view hierarchy, implementing the needed protocol between View * and the WindowManager. This is for the most part an internal implementation - * detail of {@link WindowManagerImpl}. + * detail of {@link WindowManagerGlobal}. * * {@hide} */ @@ -126,11 +125,6 @@ public final class ViewRootImpl implements ViewParent, */ static final int MAX_TRACKBALL_DELAY = 250; - static IWindowSession sWindowSession; - - static final Object mStaticInit = new Object(); - static boolean mInitialized = false; - static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>(); static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>(); @@ -143,6 +137,9 @@ public final class ViewRootImpl implements ViewParent, private static boolean sRenderThreadQueried = false; private static final Object[] sRenderThreadQueryLock = new Object[0]; + final IWindowSession mWindowSession; + final Display mDisplay; + long mLastTrackballTime = 0; final TrackballAxis mTrackballAxisX = new TrackballAxis(); final TrackballAxis mTrackballAxisY = new TrackballAxis(); @@ -250,7 +247,7 @@ public final class ViewRootImpl implements ViewParent, boolean mAdded; boolean mAddedTouchMode; - CompatibilityInfoHolder mCompatibilityInfo; + final CompatibilityInfoHolder mCompatibilityInfo; // These are accessed by multiple threads. final Rect mWinFrame; // frame given by window manager. @@ -322,24 +319,6 @@ public final class ViewRootImpl implements ViewParent, InputEventConsistencyVerifier.isInstrumentationEnabled() ? new InputEventConsistencyVerifier(this, 0) : null; - public static IWindowSession getWindowSession(Looper mainLooper) { - synchronized (mStaticInit) { - if (!mInitialized) { - try { - InputMethodManager imm = InputMethodManager.getInstance(mainLooper); - IWindowManager windowManager = WindowManagerImpl.getWindowManagerService(); - sWindowSession = windowManager.openSession( - imm.getClient(), imm.getInputContext()); - float animatorScale = windowManager.getAnimationScale(2); - ValueAnimator.setDurationScale(animatorScale); - mInitialized = true; - } catch (RemoteException e) { - } - } - return sWindowSession; - } - } - static final class SystemUiVisibilityInfo { int seq; int globalVisibility; @@ -347,7 +326,7 @@ public final class ViewRootImpl implements ViewParent, int localChanges; } - public ViewRootImpl(Context context) { + public ViewRootImpl(Context context, Display display) { super(); if (MEASURE_LATENCY) { @@ -359,7 +338,11 @@ public final class ViewRootImpl implements ViewParent, // Initialize the statics when this class is first instantiated. This is // done here instead of in the static block because Zygote does not // allow the spawning of threads. - getWindowSession(context.getMainLooper()); + mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper()); + mDisplay = display; + + CompatibilityInfoHolder cih = display.getCompatibilityInfo(); + mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder(); mThread = Thread.currentThread(); mLocation = new WindowLeaked(null); @@ -383,7 +366,7 @@ public final class ViewRootImpl implements ViewParent, new AccessibilityInteractionConnectionManager(); mAccessibilityManager.addAccessibilityStateChangeListener( mAccessibilityInteractionConnectionManager); - mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this); + mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this); mViewConfiguration = ViewConfiguration.get(context); mDensity = context.getResources().getDisplayMetrics().densityDpi; mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi; @@ -460,9 +443,10 @@ public final class ViewRootImpl implements ViewParent, * @hide */ static boolean isInTouchMode() { - if (mInitialized) { + IWindowSession windowSession = WindowManagerGlobal.peekWindowSession(); + if (windowSession != null) { try { - return sWindowSession.getInTouchMode(); + return windowSession.getInTouchMode(); } catch (RemoteException e) { } } @@ -541,8 +525,8 @@ public final class ViewRootImpl implements ViewParent, mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); - res = sWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, - getHostVisibility(), Display.DEFAULT_DISPLAY, + res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, + getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mInputChannel); } catch (RemoteException e) { mAdded = false; @@ -565,7 +549,7 @@ public final class ViewRootImpl implements ViewParent, mPendingContentInsets.set(mAttachInfo.mContentInsets); mPendingVisibleInsets.set(0, 0, 0, 0); if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow); - if (res < WindowManagerImpl.ADD_OKAY) { + if (res < WindowManagerGlobal.ADD_OKAY) { mView = null; mAttachInfo.mRootView = null; mAdded = false; @@ -573,33 +557,33 @@ public final class ViewRootImpl implements ViewParent, unscheduleTraversals(); setAccessibilityFocus(null, null); switch (res) { - case WindowManagerImpl.ADD_BAD_APP_TOKEN: - case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_BAD_APP_TOKEN: + case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN: + throw new WindowManager.BadTokenException( "Unable to add window -- token " + attrs.token + " is not valid; is your activity running?"); - case WindowManagerImpl.ADD_NOT_APP_TOKEN: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_NOT_APP_TOKEN: + throw new WindowManager.BadTokenException( "Unable to add window -- token " + attrs.token + " is not for an application"); - case WindowManagerImpl.ADD_APP_EXITING: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_APP_EXITING: + throw new WindowManager.BadTokenException( "Unable to add window -- app for token " + attrs.token + " is exiting"); - case WindowManagerImpl.ADD_DUPLICATE_ADD: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_DUPLICATE_ADD: + throw new WindowManager.BadTokenException( "Unable to add window -- window " + mWindow + " has already been added"); - case WindowManagerImpl.ADD_STARTING_NOT_NEEDED: + case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED: // Silently ignore -- we would have just removed it // right away, anyway. return; - case WindowManagerImpl.ADD_MULTIPLE_SINGLETON: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON: + throw new WindowManager.BadTokenException( "Unable to add window " + mWindow + " -- another window of this type already exists"); - case WindowManagerImpl.ADD_PERMISSION_DENIED: - throw new WindowManagerImpl.BadTokenException( + case WindowManagerGlobal.ADD_PERMISSION_DENIED: + throw new WindowManager.BadTokenException( "Unable to add window " + mWindow + " -- permission denied for this window type"); } @@ -622,8 +606,8 @@ public final class ViewRootImpl implements ViewParent, } view.assignParent(this); - mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0; - mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0; + mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0; + mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0; if (mAccessibilityManager.isEnabled()) { mAccessibilityInteractionConnectionManager.ensureConnection(); @@ -1164,9 +1148,8 @@ public final class ViewRootImpl implements ViewParent, if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) { // NOTE -- system code, won't try to do compat mode. - Display disp = WindowManagerImpl.getDefault().getDefaultDisplay(); Point size = new Point(); - disp.getRealSize(size); + mDisplay.getRealSize(size); desiredWindowWidth = size.x; desiredWindowHeight = size.y; } else { @@ -1251,9 +1234,8 @@ public final class ViewRootImpl implements ViewParent, if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) { // NOTE -- system code, won't try to do compat mode. - Display disp = WindowManagerImpl.getDefault().getDefaultDisplay(); Point size = new Point(); - disp.getRealSize(size); + mDisplay.getRealSize(size); desiredWindowWidth = size.x; desiredWindowHeight = size.y; } else { @@ -1502,7 +1484,7 @@ public final class ViewRootImpl implements ViewParent, } catch (Surface.OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException initializing HW surface", e); try { - if (!sWindowSession.outOfMemory(mWindow)) { + if (!mWindowSession.outOfMemory(mWindow)) { Slog.w(TAG, "No processes killed for memory; killing self"); Process.killProcess(Process.myPid()); } @@ -1535,7 +1517,7 @@ public final class ViewRootImpl implements ViewParent, } catch (Surface.OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException updating HW surface", e); try { - if (!sWindowSession.outOfMemory(mWindow)) { + if (!mWindowSession.outOfMemory(mWindow)) { Slog.w(TAG, "No processes killed for memory; killing self"); Process.killProcess(Process.myPid()); } @@ -1629,7 +1611,7 @@ public final class ViewRootImpl implements ViewParent, if (!mStopped) { boolean focusChangedDueToTouchMode = ensureTouchModeLocally( - (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0); + (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight() || contentInsetsChanged) { int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); @@ -1726,7 +1708,7 @@ public final class ViewRootImpl implements ViewParent, mPreviousTransparentRegion.set(mTransparentRegion); // reconfigure window manager try { - sWindowSession.setTransparentRegion(mWindow, mTransparentRegion); + mWindowSession.setTransparentRegion(mWindow, mTransparentRegion); } catch (RemoteException e) { } } @@ -1775,7 +1757,7 @@ public final class ViewRootImpl implements ViewParent, } try { - sWindowSession.setInsets(mWindow, insets.mTouchableInsets, + mWindowSession.setInsets(mWindow, insets.mTouchableInsets, contentInsets, visibleInsets, touchableRegion); } catch (RemoteException e) { } @@ -1800,7 +1782,7 @@ public final class ViewRootImpl implements ViewParent, + mRealFocusedView); } } - if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) { + if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_ANIMATING) != 0) { // The first time we relayout the window, if the system is // doing window animations, we want to hold of on any future // draws until the animation is done. @@ -1831,7 +1813,7 @@ public final class ViewRootImpl implements ViewParent, } // Remember if we must report the next draw. - if ((relayoutResult & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { + if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportNextDraw = true; } @@ -2061,7 +2043,7 @@ public final class ViewRootImpl implements ViewParent, } } try { - sWindowSession.finishDrawing(mWindow); + mWindowSession.finishDrawing(mWindow); } catch (RemoteException e) { } } @@ -2217,7 +2199,7 @@ public final class ViewRootImpl implements ViewParent, } catch (Surface.OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException locking surface", e); try { - if (!sWindowSession.outOfMemory(mWindow)) { + if (!mWindowSession.outOfMemory(mWindow)) { Slog.w(TAG, "No processes killed for memory; killing self"); Process.killProcess(Process.myPid()); } @@ -2646,7 +2628,7 @@ public final class ViewRootImpl implements ViewParent, mInputEventReceiver = null; } try { - sWindowSession.remove(mWindow); + mWindowSession.remove(mWindow); } catch (RemoteException e) { } @@ -2891,7 +2873,7 @@ public final class ViewRootImpl implements ViewParent, } catch (Surface.OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException locking surface", e); try { - if (!sWindowSession.outOfMemory(mWindow)) { + if (!mWindowSession.outOfMemory(mWindow)) { Slog.w(TAG, "No processes killed for memory; killing self"); Process.killProcess(Process.myPid()); } @@ -3036,7 +3018,7 @@ public final class ViewRootImpl implements ViewParent, // tell the window manager try { - sWindowSession.setInTouchMode(inTouchMode); + mWindowSession.setInTouchMode(inTouchMode); } catch (RemoteException e) { throw new RuntimeException(e); } @@ -3750,10 +3732,10 @@ public final class ViewRootImpl implements ViewParent, if (prevDragView != mCurrentDragView) { try { if (prevDragView != null) { - sWindowSession.dragRecipientExited(mWindow); + mWindowSession.dragRecipientExited(mWindow); } if (mCurrentDragView != null) { - sWindowSession.dragRecipientEntered(mWindow); + mWindowSession.dragRecipientEntered(mWindow); } } catch (RemoteException e) { Slog.e(TAG, "Unable to note drag target change"); @@ -3765,7 +3747,7 @@ public final class ViewRootImpl implements ViewParent, mDragDescription = null; try { Log.i(TAG, "Reporting drop result: " + result); - sWindowSession.reportDropResult(mWindow, result); + mWindowSession.reportDropResult(mWindow, result); } catch (RemoteException e) { Log.e(TAG, "Unable to report drop result"); } @@ -3867,11 +3849,11 @@ public final class ViewRootImpl implements ViewParent, params.type = mOrigWindowType; } } - int relayoutResult = sWindowSession.relayout( + int relayoutResult = mWindowSession.relayout( mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), - viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0, + viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); @@ -3928,7 +3910,7 @@ public final class ViewRootImpl implements ViewParent, */ public boolean performHapticFeedback(int effectId, boolean always) { try { - return sWindowSession.performHapticFeedback(mWindow, effectId, always); + return mWindowSession.performHapticFeedback(mWindow, effectId, always); } catch (RemoteException e) { return false; } @@ -4007,8 +3989,8 @@ public final class ViewRootImpl implements ViewParent, // animation info. try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) - & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { - sWindowSession.finishDrawing(mWindow); + & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { + mWindowSession.finishDrawing(mWindow); } } catch (RemoteException e) { } @@ -4726,9 +4708,11 @@ public final class ViewRootImpl implements ViewParent, static class W extends IWindow.Stub { private final WeakReference<ViewRootImpl> mViewAncestor; + private final IWindowSession mWindowSession; W(ViewRootImpl viewAncestor) { mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor); + mWindowSession = viewAncestor.mWindowSession; } public void resized(Rect frame, Rect contentInsets, @@ -4827,7 +4811,7 @@ public final class ViewRootImpl implements ViewParent, boolean sync) { if (sync) { try { - sWindowSession.wallpaperOffsetsComplete(asBinder()); + mWindowSession.wallpaperOffsetsComplete(asBinder()); } catch (RemoteException e) { } } @@ -4837,7 +4821,7 @@ public final class ViewRootImpl implements ViewParent, int z, Bundle extras, boolean sync) { if (sync) { try { - sWindowSession.wallpaperCommandComplete(asBinder(), null); + mWindowSession.wallpaperCommandComplete(asBinder(), null); } catch (RemoteException e) { } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index f57f056..a242895 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -16,7 +16,6 @@ package android.view; -import android.app.Application; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; @@ -455,7 +454,7 @@ public abstract class Window { * display panels. This is <em>not</em> used for displaying the * Window itself -- that must be done by the client. * - * @param wm The ViewManager for adding new windows. + * @param wm The window manager for adding new windows. */ public void setWindowManager(WindowManager wm, IBinder appToken, String appName) { setWindowManager(wm, appToken, appName, false); @@ -466,7 +465,7 @@ public abstract class Window { * display panels. This is <em>not</em> used for displaying the * Window itself -- that must be done by the client. * - * @param wm The ViewManager for adding new windows. + * @param wm The window manager for adding new windows. */ public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { @@ -475,14 +474,9 @@ public abstract class Window { mHardwareAccelerated = hardwareAccelerated || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); if (wm == null) { - wm = WindowManagerImpl.getDefault(); + wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); } - mWindowManager = ((WindowManagerImpl)wm).makeLocal(this); - } - - CompatibilityInfoHolder getCompatibilityInfo() { - Application app = (Application)mContext.getApplicationContext(); - return app != null ? app.mLoadedApk.mCompatibilityInfo : null; + mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); } void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) { diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java new file mode 100644 index 0000000..7855763c --- /dev/null +++ b/core/java/android/view/WindowManagerGlobal.java @@ -0,0 +1,516 @@ +/* + * Copyright (C) 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. + */ + +package android.view; + +import android.animation.ValueAnimator; +import android.app.ActivityManager; +import android.content.ComponentCallbacks2; +import android.content.res.Configuration; +import android.opengl.ManagedEGLContext; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.util.AndroidRuntimeException; +import android.util.Log; +import android.view.inputmethod.InputMethodManager; + +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintWriter; + +/** + * Provides low-level communication with the system window manager for + * operations that are not associated with any particular context. + * + * This class is only used internally to implement global functions where + * the caller already knows the display and relevant compatibility information + * for the operation. For most purposes, you should use {@link WindowManager} instead + * since it is bound to a context. + * + * @see WindowManagerImpl + * @hide + */ +public final class WindowManagerGlobal { + private static final String TAG = "WindowManager"; + + /** + * The user is navigating with keys (not the touch screen), so + * navigational focus should be shown. + */ + public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1; + + /** + * This is the first time the window is being drawn, + * so the client must call drawingFinished() when done + */ + public static final int RELAYOUT_RES_FIRST_TIME = 0x2; + + /** + * The window manager has changed the surface from the last call. + */ + public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4; + + /** + * The window manager is currently animating. It will call + * IWindow.doneAnimating() when done. + */ + public static final int RELAYOUT_RES_ANIMATING = 0x8; + + /** + * Flag for relayout: the client will be later giving + * internal insets; as a result, the window will not impact other window + * layouts until the insets are given. + */ + public static final int RELAYOUT_INSETS_PENDING = 0x1; + + /** + * Flag for relayout: the client may be currently using the current surface, + * so if it is to be destroyed as a part of the relayout the destroy must + * be deferred until later. The client will call performDeferredDestroy() + * when it is okay. + */ + public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2; + + public static final int ADD_FLAG_APP_VISIBLE = 0x2; + public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE; + + public static final int ADD_OKAY = 0; + public static final int ADD_BAD_APP_TOKEN = -1; + public static final int ADD_BAD_SUBWINDOW_TOKEN = -2; + public static final int ADD_NOT_APP_TOKEN = -3; + public static final int ADD_APP_EXITING = -4; + public static final int ADD_DUPLICATE_ADD = -5; + public static final int ADD_STARTING_NOT_NEEDED = -6; + public static final int ADD_MULTIPLE_SINGLETON = -7; + public static final int ADD_PERMISSION_DENIED = -8; + + private static WindowManagerGlobal sDefaultWindowManager; + private static IWindowManager sWindowManagerService; + private static IWindowSession sWindowSession; + + private final Object mLock = new Object(); + + private View[] mViews; + private ViewRootImpl[] mRoots; + private WindowManager.LayoutParams[] mParams; + private boolean mNeedsEglTerminate; + + private Runnable mSystemPropertyUpdater; + + private WindowManagerGlobal() { + } + + public static WindowManagerGlobal getInstance() { + synchronized (WindowManagerGlobal.class) { + if (sDefaultWindowManager == null) { + sDefaultWindowManager = new WindowManagerGlobal(); + } + return sDefaultWindowManager; + } + } + + public static IWindowManager getWindowManagerService() { + synchronized (WindowManagerGlobal.class) { + if (sWindowManagerService == null) { + sWindowManagerService = IWindowManager.Stub.asInterface( + ServiceManager.getService("window")); + } + return sWindowManagerService; + } + } + + public static IWindowSession getWindowSession(Looper mainLooper) { + synchronized (WindowManagerGlobal.class) { + if (sWindowSession == null) { + try { + InputMethodManager imm = InputMethodManager.getInstance(mainLooper); + IWindowManager windowManager = getWindowManagerService(); + sWindowSession = windowManager.openSession( + imm.getClient(), imm.getInputContext()); + float animatorScale = windowManager.getAnimationScale(2); + ValueAnimator.setDurationScale(animatorScale); + } catch (RemoteException e) { + Log.e(TAG, "Failed to open window session", e); + } + } + return sWindowSession; + } + } + + public static IWindowSession peekWindowSession() { + synchronized (WindowManagerGlobal.class) { + return sWindowSession; + } + } + + public void addView(View view, ViewGroup.LayoutParams params, + Display display, Window parentWindow) { + if (view == null) { + throw new IllegalArgumentException("view must not be null"); + } + if (display == null) { + throw new IllegalArgumentException("display must not be null"); + } + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; + if (parentWindow != null) { + parentWindow.adjustLayoutParamsForSubWindow(wparams); + } + + ViewRootImpl root; + View panelParentView = null; + + synchronized (mLock) { + // Start watching for system property changes. + if (mSystemPropertyUpdater == null) { + mSystemPropertyUpdater = new Runnable() { + @Override public void run() { + synchronized (mLock) { + for (ViewRootImpl root : mRoots) { + root.loadSystemProperties(); + } + } + } + }; + SystemProperties.addChangeCallback(mSystemPropertyUpdater); + } + + int index = findViewLocked(view, false); + if (index >= 0) { + throw new IllegalStateException("View " + view + + " has already been added to the window manager."); + } + + // If this is a panel window, then find the window it is being + // attached to for future reference. + if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && + wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + final int count = mViews != null ? mViews.length : 0; + for (int i=0; i<count; i++) { + if (mRoots[i].mWindow.asBinder() == wparams.token) { + panelParentView = mViews[i]; + } + } + } + + root = new ViewRootImpl(view.getContext(), display); + + view.setLayoutParams(wparams); + + if (mViews == null) { + index = 1; + mViews = new View[1]; + mRoots = new ViewRootImpl[1]; + mParams = new WindowManager.LayoutParams[1]; + } else { + index = mViews.length + 1; + Object[] old = mViews; + mViews = new View[index]; + System.arraycopy(old, 0, mViews, 0, index-1); + old = mRoots; + mRoots = new ViewRootImpl[index]; + System.arraycopy(old, 0, mRoots, 0, index-1); + old = mParams; + mParams = new WindowManager.LayoutParams[index]; + System.arraycopy(old, 0, mParams, 0, index-1); + } + index--; + + mViews[index] = view; + mRoots[index] = root; + mParams[index] = wparams; + } + + // do this last because it fires off messages to start doing things + root.setView(view, wparams, panelParentView); + } + + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + if (view == null) { + throw new IllegalArgumentException("view must not be null"); + } + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; + + view.setLayoutParams(wparams); + + synchronized (mLock) { + int index = findViewLocked(view, true); + ViewRootImpl root = mRoots[index]; + mParams[index] = wparams; + root.setLayoutParams(wparams, false); + } + } + + public void removeView(View view, boolean immediate) { + if (view == null) { + throw new IllegalArgumentException("view must not be null"); + } + + synchronized (mLock) { + int index = findViewLocked(view, true); + View curView = removeViewLocked(index, immediate); + if (curView == view) { + return; + } + + throw new IllegalStateException("Calling with view " + view + + " but the ViewAncestor is attached to " + curView); + } + } + + public void closeAll(IBinder token, String who, String what) { + synchronized (mLock) { + if (mViews == null) + return; + + int count = mViews.length; + //Log.i("foo", "Closing all windows of " + token); + for (int i=0; i<count; i++) { + //Log.i("foo", "@ " + i + " token " + mParams[i].token + // + " view " + mRoots[i].getView()); + if (token == null || mParams[i].token == token) { + ViewRootImpl root = mRoots[i]; + + //Log.i("foo", "Force closing " + root); + if (who != null) { + WindowLeaked leak = new WindowLeaked( + what + " " + who + " has leaked window " + + root.getView() + " that was originally added here"); + leak.setStackTrace(root.getLocation().getStackTrace()); + Log.e(TAG, leak.getMessage(), leak); + } + + removeViewLocked(i, false); + i--; + count--; + } + } + } + } + + private View removeViewLocked(int index, boolean immediate) { + ViewRootImpl root = mRoots[index]; + View view = root.getView(); + + if (view != null) { + InputMethodManager imm = InputMethodManager.getInstance(view.getContext()); + if (imm != null) { + imm.windowDismissed(mViews[index].getWindowToken()); + } + } + root.die(immediate); + + final int count = mViews.length; + + // remove it from the list + View[] tmpViews = new View[count-1]; + removeItem(tmpViews, mViews, index); + mViews = tmpViews; + + ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1]; + removeItem(tmpRoots, mRoots, index); + mRoots = tmpRoots; + + WindowManager.LayoutParams[] tmpParams + = new WindowManager.LayoutParams[count-1]; + removeItem(tmpParams, mParams, index); + mParams = tmpParams; + + if (view != null) { + view.assignParent(null); + // func doesn't allow null... does it matter if we clear them? + //view.setLayoutParams(null); + } + return view; + } + + private static void removeItem(Object[] dst, Object[] src, int index) { + if (dst.length > 0) { + if (index > 0) { + System.arraycopy(src, 0, dst, 0, index); + } + if (index < dst.length) { + System.arraycopy(src, index+1, dst, index, src.length-index-1); + } + } + } + + private int findViewLocked(View view, boolean required) { + synchronized (mLock) { + if (mViews != null) { + final int count = mViews.length; + for (int i = 0; i < count; i++) { + if (mViews[i] == view) { + return i; + } + } + } + if (required) { + throw new IllegalArgumentException("View not attached to window manager"); + } + return -1; + } + } + + public void startTrimMemory(int level) { + if (HardwareRenderer.isAvailable()) { + // On low-end gfx devices we trim when memory is moderate; + // on high-end devices we do this when low. + if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE + || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE + && !ActivityManager.isHighEndGfx())) { + // Destroy all hardware surfaces and resources associated to + // known windows + synchronized (mLock) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].terminateHardwareResources(); + } + } + // Force a full memory flush + mNeedsEglTerminate = true; + HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); + return; + } + + HardwareRenderer.startTrimMemory(level); + } + } + + public void endTrimMemory() { + HardwareRenderer.endTrimMemory(); + + if (mNeedsEglTerminate) { + ManagedEGLContext.doTerminate(); + mNeedsEglTerminate = false; + } + } + + public void trimLocalMemory() { + synchronized (mLock) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].destroyHardwareLayers(); + } + } + } + + public void dumpGfxInfo(FileDescriptor fd) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + try { + synchronized (mLock) { + if (mViews != null) { + final int count = mViews.length; + + pw.println("Profile data in ms:"); + + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + String name = getWindowName(root); + pw.printf("\n\t%s", name); + + HardwareRenderer renderer = + root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + renderer.dumpGfxInfo(pw); + } + } + + pw.println("\nView hierarchy:\n"); + + int viewsCount = 0; + int displayListsSize = 0; + int[] info = new int[2]; + + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.dumpGfxInfo(info); + + String name = getWindowName(root); + pw.printf(" %s\n %d views, %.2f kB of display lists", + name, info[0], info[1] / 1024.0f); + HardwareRenderer renderer = + root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + pw.printf(", %d frames rendered", renderer.getFrameCount()); + } + pw.printf("\n\n"); + + viewsCount += info[0]; + displayListsSize += info[1]; + } + + pw.printf("\nTotal ViewRootImpl: %d\n", count); + pw.printf("Total Views: %d\n", viewsCount); + pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); + } + } + } finally { + pw.flush(); + } + } + + private static String getWindowName(ViewRootImpl root) { + return root.mWindowAttributes.getTitle() + "/" + + root.getClass().getName() + '@' + Integer.toHexString(root.hashCode()); + } + + public void setStoppedState(IBinder token, boolean stopped) { + synchronized (mLock) { + if (mViews != null) { + int count = mViews.length; + for (int i=0; i < count; i++) { + if (token == null || mParams[i].token == token) { + ViewRootImpl root = mRoots[i]; + root.setStopped(stopped); + } + } + } + } + } + + public void reportNewConfiguration(Configuration config) { + synchronized (mLock) { + if (mViews != null) { + int count = mViews.length; + config = new Configuration(config); + for (int i=0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.requestUpdateConfiguration(config); + } + } + } + } +} + +final class WindowLeaked extends AndroidRuntimeException { + public WindowLeaked(String msg) { + super(msg); + } +} diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index bd95cdb..bf061df 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -16,34 +16,20 @@ package android.view; -import android.app.ActivityManager; -import android.content.ComponentCallbacks2; -import android.content.res.Configuration; -import android.opengl.ManagedEGLContext; -import android.os.IBinder; -import android.os.ServiceManager; -import android.os.SystemProperties; -import android.util.AndroidRuntimeException; -import android.util.Log; -import android.view.inputmethod.InputMethodManager; - -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.PrintWriter; - -final class WindowLeaked extends AndroidRuntimeException { - public WindowLeaked(String msg) { - super(msg); - } -} +import android.content.Context; +import android.hardware.display.DisplayManager; /** - * Low-level communication with the global system window manager. It implements - * the ViewManager interface, allowing you to add any View subclass as a - * top-level window on the screen. Additional window manager specific layout - * parameters are defined for control over how windows are displayed. - * It also implements the WindowManager interface, allowing you to control the - * displays attached to the device. + * Provides low-level communication with the system window manager for + * operations that are bound to a particular context, display or parent window. + * Instances of this object are sensitive to the compatibility info associated + * with the running application. + * + * This object implements the {@link ViewManager} interface, + * allowing you to add any View subclass as a top-level window on the screen. + * Additional window manager specific layout parameters are defined for + * control over how windows are displayed. It also implements the {@link WindowManager} + * interface, allowing you to control the displays attached to the device. * * <p>Applications will not normally use WindowManager directly, instead relying * on the higher-level facilities in {@link android.app.Activity} and @@ -51,531 +37,58 @@ final class WindowLeaked extends AndroidRuntimeException { * * <p>Even for low-level window manager access, it is almost never correct to use * this class. For example, {@link android.app.Activity#getWindowManager} - * provides a ViewManager for adding windows that are associated with that + * provides a window manager for adding windows that are associated with that * activity -- the window manager will not normally allow you to add arbitrary * windows that are not associated with an activity. - * + * + * @see WindowManager + * @see WindowManagerGlobal * @hide */ -public class WindowManagerImpl implements WindowManager { - private static final String TAG = "WindowManager"; - - /** - * The user is navigating with keys (not the touch screen), so - * navigational focus should be shown. - */ - public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1; - - /** - * This is the first time the window is being drawn, - * so the client must call drawingFinished() when done - */ - public static final int RELAYOUT_RES_FIRST_TIME = 0x2; - - /** - * The window manager has changed the surface from the last call. - */ - public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4; - - /** - * The window manager is currently animating. It will call - * IWindow.doneAnimating() when done. - */ - public static final int RELAYOUT_RES_ANIMATING = 0x8; - - /** - * Flag for relayout: the client will be later giving - * internal insets; as a result, the window will not impact other window - * layouts until the insets are given. - */ - public static final int RELAYOUT_INSETS_PENDING = 0x1; - - /** - * Flag for relayout: the client may be currently using the current surface, - * so if it is to be destroyed as a part of the relayout the destroy must - * be deferred until later. The client will call performDeferredDestroy() - * when it is okay. - */ - public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2; - - public static final int ADD_FLAG_APP_VISIBLE = 0x2; - public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE; - - public static final int ADD_OKAY = 0; - public static final int ADD_BAD_APP_TOKEN = -1; - public static final int ADD_BAD_SUBWINDOW_TOKEN = -2; - public static final int ADD_NOT_APP_TOKEN = -3; - public static final int ADD_APP_EXITING = -4; - public static final int ADD_DUPLICATE_ADD = -5; - public static final int ADD_STARTING_NOT_NEEDED = -6; - public static final int ADD_MULTIPLE_SINGLETON = -7; - public static final int ADD_PERMISSION_DENIED = -8; - - private static WindowManagerImpl sDefaultWindowManager; - private static IWindowManager sWindowManagerService; - - private final WindowManagerState mState; +public final class WindowManagerImpl implements WindowManager { + private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); + private final Context mContext; + private final Display mDisplay; private final Window mParentWindow; - private final CompatibilityInfoHolder mCompatibilityInfo; - private final Display mDefaultDisplay; - private WindowManagerImpl(WindowManagerState state, Window parentWindow, - CompatibilityInfoHolder compatibilityInfo) { - mState = state; - mParentWindow = parentWindow; - mCompatibilityInfo = compatibilityInfo; - mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo); + public WindowManagerImpl(Context context, int displayId) { + mContext = context; + mDisplay = DisplayManager.getInstance().getDisplay(displayId, mContext); + mParentWindow = null; } - public static WindowManagerImpl getDefault() { - synchronized (WindowManagerImpl.class) { - if (sDefaultWindowManager == null) { - sDefaultWindowManager = new WindowManagerImpl( - new WindowManagerState(), null, null); - } - return sDefaultWindowManager; - } - } - - public static IWindowManager getWindowManagerService() { - synchronized (WindowManagerImpl.class) { - if (sWindowManagerService == null) { - sWindowManagerService = IWindowManager.Stub.asInterface( - ServiceManager.getService("window")); - } - return sWindowManagerService; - } - } - - public WindowManagerImpl makeLocal(Window parentWindow) { - return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo()); + private WindowManagerImpl(Context context, Display display, Window parentWindow) { + mContext = context; + mDisplay = display; + mParentWindow = parentWindow; } - public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) { - if (compatInfo == mCompatibilityInfo) { - return this; - } - if (compatInfo == null && mParentWindow == null) { - return getDefault(); - } - return new WindowManagerImpl(mState, mParentWindow, compatInfo); + public WindowManagerImpl createLocalWindowManager(Window parentWindow) { + return new WindowManagerImpl(mContext, mDisplay, parentWindow); } @Override public void addView(View view, ViewGroup.LayoutParams params) { - mState.addView(view, params, mParentWindow, mCompatibilityInfo); + mGlobal.addView(view, params, mDisplay, mParentWindow); } @Override public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - mState.updateViewLayout(view, params); + mGlobal.updateViewLayout(view, params); } @Override public void removeView(View view) { - mState.removeView(view, false); + mGlobal.removeView(view, false); } @Override public void removeViewImmediate(View view) { - mState.removeView(view, true); + mGlobal.removeView(view, true); } @Override public Display getDefaultDisplay() { - return mDefaultDisplay; - } - - public void closeAll(IBinder token, String who, String what) { - mState.closeAll(token, who, what); - } - - public void startTrimMemory(int level) { - mState.startTrimMemory(level); - } - - public void endTrimMemory() { - mState.endTrimMemory(); - } - - public void trimLocalMemory() { - mState.trimLocalMemory(); - } - - public void dumpGfxInfo(FileDescriptor fd) { - mState.dumpGfxInfo(fd); - } - - public void setStoppedState(IBinder token, boolean stopped) { - mState.setStoppedState(token, stopped); - } - - public void reportNewConfiguration(Configuration config) { - mState.reportNewConfiguration(config); - } - - static final class WindowManagerState { - private final Display mDefaultDisplay; - - private View[] mViews; - private ViewRootImpl[] mRoots; - private WindowManager.LayoutParams[] mParams; - private boolean mNeedsEglTerminate; - - private Runnable mSystemPropertyUpdater; - - public WindowManagerState() { - mDefaultDisplay = new Display(Display.DEFAULT_DISPLAY, null); - } - - public Display getDefaultDisplay(CompatibilityInfoHolder compatInfo) { - if (compatInfo == null) { - return mDefaultDisplay; - } - return new Display(Display.DEFAULT_DISPLAY, compatInfo); - } - - public void addView(View view, ViewGroup.LayoutParams params, Window parentWindow, - CompatibilityInfoHolder cih) { - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); - } - - final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; - if (parentWindow != null) { - parentWindow.adjustLayoutParamsForSubWindow(wparams); - } - - ViewRootImpl root; - View panelParentView = null; - - synchronized (this) { - // Start watching for system property changes. - if (mSystemPropertyUpdater == null) { - mSystemPropertyUpdater = new Runnable() { - @Override public void run() { - synchronized (this) { - synchronized (this) { - for (ViewRootImpl root : mRoots) { - root.loadSystemProperties(); - } - } - } - } - }; - SystemProperties.addChangeCallback(mSystemPropertyUpdater); - } - - int index = findViewLocked(view, false); - if (index >= 0) { - throw new IllegalStateException("View " + view - + " has already been added to the window manager."); - } - - // If this is a panel window, then find the window it is being - // attached to for future reference. - if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i<count; i++) { - if (mRoots[i].mWindow.asBinder() == wparams.token) { - panelParentView = mViews[i]; - } - } - } - - root = new ViewRootImpl(view.getContext()); - if (cih == null) { - root.mCompatibilityInfo = new CompatibilityInfoHolder(); - } else { - root.mCompatibilityInfo = cih; - } - - view.setLayoutParams(wparams); - - if (mViews == null) { - index = 1; - mViews = new View[1]; - mRoots = new ViewRootImpl[1]; - mParams = new WindowManager.LayoutParams[1]; - } else { - index = mViews.length + 1; - Object[] old = mViews; - mViews = new View[index]; - System.arraycopy(old, 0, mViews, 0, index-1); - old = mRoots; - mRoots = new ViewRootImpl[index]; - System.arraycopy(old, 0, mRoots, 0, index-1); - old = mParams; - mParams = new WindowManager.LayoutParams[index]; - System.arraycopy(old, 0, mParams, 0, index-1); - } - index--; - - mViews[index] = view; - mRoots[index] = root; - mParams[index] = wparams; - } - - // do this last because it fires off messages to start doing things - root.setView(view, wparams, panelParentView); - } - - public void updateViewLayout(View view, ViewGroup.LayoutParams params) { - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); - } - - final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; - - view.setLayoutParams(wparams); - - synchronized (this) { - int index = findViewLocked(view, true); - ViewRootImpl root = mRoots[index]; - mParams[index] = wparams; - root.setLayoutParams(wparams, false); - } - } - - public void removeView(View view, boolean immediate) { - synchronized (this) { - int index = findViewLocked(view, true); - View curView = removeViewLocked(index, immediate); - if (curView == view) { - return; - } - - throw new IllegalStateException("Calling with view " + view - + " but the ViewAncestor is attached to " + curView); - } - } - - public void closeAll(IBinder token, String who, String what) { - synchronized (this) { - if (mViews == null) - return; - - int count = mViews.length; - //Log.i("foo", "Closing all windows of " + token); - for (int i=0; i<count; i++) { - //Log.i("foo", "@ " + i + " token " + mParams[i].token - // + " view " + mRoots[i].getView()); - if (token == null || mParams[i].token == token) { - ViewRootImpl root = mRoots[i]; - - //Log.i("foo", "Force closing " + root); - if (who != null) { - WindowLeaked leak = new WindowLeaked( - what + " " + who + " has leaked window " - + root.getView() + " that was originally added here"); - leak.setStackTrace(root.getLocation().getStackTrace()); - Log.e(TAG, leak.getMessage(), leak); - } - - removeViewLocked(i, false); - i--; - count--; - } - } - } - } - - private View removeViewLocked(int index, boolean immediate) { - ViewRootImpl root = mRoots[index]; - View view = root.getView(); - - if (view != null) { - InputMethodManager imm = InputMethodManager.getInstance(view.getContext()); - if (imm != null) { - imm.windowDismissed(mViews[index].getWindowToken()); - } - } - root.die(immediate); - - final int count = mViews.length; - - // remove it from the list - View[] tmpViews = new View[count-1]; - removeItem(tmpViews, mViews, index); - mViews = tmpViews; - - ViewRootImpl[] tmpRoots = new ViewRootImpl[count-1]; - removeItem(tmpRoots, mRoots, index); - mRoots = tmpRoots; - - WindowManager.LayoutParams[] tmpParams - = new WindowManager.LayoutParams[count-1]; - removeItem(tmpParams, mParams, index); - mParams = tmpParams; - - if (view != null) { - view.assignParent(null); - // func doesn't allow null... does it matter if we clear them? - //view.setLayoutParams(null); - } - return view; - } - - private static void removeItem(Object[] dst, Object[] src, int index) { - if (dst.length > 0) { - if (index > 0) { - System.arraycopy(src, 0, dst, 0, index); - } - if (index < dst.length) { - System.arraycopy(src, index+1, dst, index, src.length-index-1); - } - } - } - - private int findViewLocked(View view, boolean required) { - synchronized (this) { - if (mViews != null) { - final int count = mViews.length; - for (int i = 0; i < count; i++) { - if (mViews[i] == view) { - return i; - } - } - } - if (required) { - throw new IllegalArgumentException("View not attached to window manager"); - } - return -1; - } - } - - public void startTrimMemory(int level) { - if (HardwareRenderer.isAvailable()) { - // On low-end gfx devices we trim when memory is moderate; - // on high-end devices we do this when low. - if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE - || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE - && !ActivityManager.isHighEndGfx(mDefaultDisplay))) { - // Destroy all hardware surfaces and resources associated to - // known windows - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].terminateHardwareResources(); - } - } - // Force a full memory flush - mNeedsEglTerminate = true; - HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); - return; - } - - HardwareRenderer.startTrimMemory(level); - } - } - - public void endTrimMemory() { - HardwareRenderer.endTrimMemory(); - - if (mNeedsEglTerminate) { - ManagedEGLContext.doTerminate(); - mNeedsEglTerminate = false; - } - } - - public void trimLocalMemory() { - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].destroyHardwareLayers(); - } - } - } - - public void dumpGfxInfo(FileDescriptor fd) { - FileOutputStream fout = new FileOutputStream(fd); - PrintWriter pw = new PrintWriter(fout); - try { - synchronized (this) { - if (mViews != null) { - final int count = mViews.length; - - pw.println("Profile data in ms:"); - - for (int i = 0; i < count; i++) { - ViewRootImpl root = mRoots[i]; - String name = getWindowName(root); - pw.printf("\n\t%s", name); - - HardwareRenderer renderer = - root.getView().mAttachInfo.mHardwareRenderer; - if (renderer != null) { - renderer.dumpGfxInfo(pw); - } - } - - pw.println("\nView hierarchy:\n"); - - int viewsCount = 0; - int displayListsSize = 0; - int[] info = new int[2]; - - for (int i = 0; i < count; i++) { - ViewRootImpl root = mRoots[i]; - root.dumpGfxInfo(info); - - String name = getWindowName(root); - pw.printf(" %s\n %d views, %.2f kB of display lists", - name, info[0], info[1] / 1024.0f); - HardwareRenderer renderer = - root.getView().mAttachInfo.mHardwareRenderer; - if (renderer != null) { - pw.printf(", %d frames rendered", renderer.getFrameCount()); - } - pw.printf("\n\n"); - - viewsCount += info[0]; - displayListsSize += info[1]; - } - - pw.printf("\nTotal ViewRootImpl: %d\n", count); - pw.printf("Total Views: %d\n", viewsCount); - pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); - } - } - } finally { - pw.flush(); - } - } - - private static String getWindowName(ViewRootImpl root) { - return root.mWindowAttributes.getTitle() + "/" + - root.getClass().getName() + '@' + Integer.toHexString(root.hashCode()); - } - - public void setStoppedState(IBinder token, boolean stopped) { - synchronized (this) { - if (mViews != null) { - int count = mViews.length; - for (int i=0; i < count; i++) { - if (token == null || mParams[i].token == token) { - ViewRootImpl root = mRoots[i]; - root.setStopped(stopped); - } - } - } - } - } - - public void reportNewConfiguration(Configuration config) { - synchronized (this) { - if (mViews != null) { - int count = mViews.length; - config = new Configuration(config); - for (int i=0; i < count; i++) { - ViewRootImpl root = mRoots[i]; - root.requestUpdateConfiguration(config); - } - } - } - } + return mDisplay; } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 7aa3bb4..c0a4a63 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -487,9 +487,9 @@ public interface WindowManagerPolicy { * * @param attrs The window's LayoutParams. * - * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed; + * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed; * else an error code, usually - * {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add. + * {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add. */ public int checkAddPermission(WindowManager.LayoutParams attrs); @@ -662,7 +662,7 @@ public interface WindowManagerPolicy { * @param win The window being added. * @param attrs The window's LayoutParams. * - * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an + * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an * error code to abort the add. */ public int prepareAddWindowLw(WindowState win, diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 8d79492..c816d5b 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -7279,11 +7279,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // nativeCreate sets mNativeClass to a non-zero value String drawableDir = BrowserFrame.getRawResFilename( BrowserFrame.DRAWABLEDIR, mContext); - WindowManager windowManager = - (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); - Display display = windowManager.getDefaultDisplay(); - nativeCreate(msg.arg1, drawableDir, - ActivityManager.isHighEndGfx(display)); + nativeCreate(msg.arg1, drawableDir, ActivityManager.isHighEndGfx()); if (mDelaySetPicture != null) { setNewPicture(mDelaySetPicture, true); mDelaySetPicture = null; diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 7dcbc3e..053ade7 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -30,7 +30,6 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; -import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -331,7 +330,7 @@ public class Toast { View mView; View mNextView; - WindowManagerImpl mWM; + WindowManager mWM; TN() { // XXX This should be changed to use a Dialog, with a Theme.Toast @@ -371,7 +370,7 @@ public class Toast { // remove the old view if necessary handleHide(); mView = mNextView; - mWM = WindowManagerImpl.getDefault(); + mWM = (WindowManager)mView.getContext().getSystemService(Context.WINDOW_SERVICE); // We can resolve the Gravity here by using the Locale for getting // the layout direction final Configuration config = mView.getContext().getResources().getConfiguration(); |