From d32460c5b7bea7b06e345397fdbaca58d9732dcf Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Fri, 20 Jul 2012 16:15:36 -0700 Subject: Refactor local window manager implementation. The objective of this refactoring is to remove the reliance on WindowManager wrapper objects for compatibility mode and for managing sub-windows. Removed the WindowManager.isHardwareAccelerated() method since it is never used. Change-Id: I4840a6353121859a5e0c07d5cc307a437c595d63 --- core/java/android/view/WindowManagerImpl.java | 777 ++++++++++++-------------- 1 file changed, 368 insertions(+), 409 deletions(-) (limited to 'core/java/android/view/WindowManagerImpl.java') diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index ce8b4a512bae..dedee97fa5b1 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -18,9 +18,7 @@ package android.view; import android.app.ActivityManager; import android.content.ComponentCallbacks2; -import android.content.res.CompatibilityInfo; import android.content.res.Configuration; -import android.graphics.PixelFormat; import android.opengl.ManagedEGLContext; import android.os.IBinder; import android.os.SystemProperties; @@ -31,7 +29,6 @@ import android.view.inputmethod.InputMethodManager; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.PrintWriter; -import java.util.HashMap; final class WindowLeaked extends AndroidRuntimeException { public WindowLeaked(String msg) { @@ -44,7 +41,7 @@ final class WindowLeaked extends AndroidRuntimeException { * 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 implemens the WindowManager interface, allowing you to control the + * It also implements the WindowManager interface, allowing you to control the * displays attached to the device. * *

Applications will not normally use WindowManager directly, instead relying @@ -60,20 +57,25 @@ final class WindowLeaked extends AndroidRuntimeException { * @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. @@ -108,503 +110,460 @@ public class WindowManagerImpl implements WindowManager { public static final int ADD_MULTIPLE_SINGLETON = -7; public static final int ADD_PERMISSION_DENIED = -8; - private View[] mViews; - private ViewRootImpl[] mRoots; - private WindowManager.LayoutParams[] mParams; - private boolean mNeedsEglTerminate; + private static WindowManagerImpl sDefaultWindowManager; - private Runnable mSystemPropertyUpdater = null; + private final WindowManagerState mState; + private final Window mParentWindow; + private final CompatibilityInfoHolder mCompatibilityInfo; + private final Display mDefaultDisplay; - private final static Object sLock = new Object(); - private final static WindowManagerImpl sWindowManager = new WindowManagerImpl(); - private final static HashMap sCompatWindowManagers - = new HashMap(); + private WindowManagerImpl(WindowManagerState state, Window parentWindow, + CompatibilityInfoHolder compatibilityInfo) { + mState = state; + mParentWindow = parentWindow; + mCompatibilityInfo = compatibilityInfo; + mDefaultDisplay = mState.getDefaultDisplay(mCompatibilityInfo); + } - static class CompatModeWrapper implements WindowManager { - private final WindowManagerImpl mWindowManager; - private final Display mDefaultDisplay; - private final CompatibilityInfoHolder mCompatibilityInfo; - - CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) { - mWindowManager = wm instanceof CompatModeWrapper - ? ((CompatModeWrapper)wm).mWindowManager : (WindowManagerImpl)wm; - - // Use the original display if there is no compatibility mode - // to apply, or the underlying window manager is already a - // compatibility mode wrapper. (We assume that if it is a - // wrapper, it is applying the same compatibility mode.) - if (ci == null) { - mDefaultDisplay = mWindowManager.getDefaultDisplay(); - } else { - //mDefaultDisplay = mWindowManager.getDefaultDisplay(); - mDefaultDisplay = Display.createCompatibleDisplay( - mWindowManager.getDefaultDisplay().getDisplayId(), ci); + public static WindowManagerImpl getDefault() { + synchronized (WindowManagerImpl.class) { + if (sDefaultWindowManager == null) { + sDefaultWindowManager = new WindowManagerImpl( + new WindowManagerState(), null, null); } - - mCompatibilityInfo = ci; - } - - @Override - public void addView(View view, android.view.ViewGroup.LayoutParams params) { - mWindowManager.addView(view, params, mCompatibilityInfo); + return sDefaultWindowManager; } + } - @Override - public void updateViewLayout(View view, android.view.ViewGroup.LayoutParams params) { - mWindowManager.updateViewLayout(view, params); + public WindowManagerImpl makeLocal(Window parentWindow) { + return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo()); + } + public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) { + if (compatInfo == mCompatibilityInfo) { + return this; } - - @Override - public void removeView(View view) { - mWindowManager.removeView(view); + if (compatInfo == null && mParentWindow == null) { + return getDefault(); } + return new WindowManagerImpl(mState, mParentWindow, compatInfo); + } - @Override - public Display getDefaultDisplay() { - return mDefaultDisplay; - } + @Override + public void addView(View view, ViewGroup.LayoutParams params) { + mState.addView(view, params, mParentWindow, mCompatibilityInfo); + } - @Override - public void removeViewImmediate(View view) { - mWindowManager.removeViewImmediate(view); - } + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + mState.updateViewLayout(view, params); + } - @Override - public boolean isHardwareAccelerated() { - return mWindowManager.isHardwareAccelerated(); - } + @Override + public void removeView(View view) { + mState.removeView(view, false); + } + @Override + public void removeViewImmediate(View view) { + mState.removeView(view, true); } - public static WindowManagerImpl getDefault() { - return sWindowManager; + @Override + public Display getDefaultDisplay() { + return mDefaultDisplay; } - public static WindowManager getDefault(CompatibilityInfo compatInfo) { - CompatibilityInfoHolder cih = new CompatibilityInfoHolder(); - cih.set(compatInfo); - if (cih.getIfNeeded() == null) { - return sWindowManager; - } + public void closeAll(IBinder token, String who, String what) { + mState.closeAll(token, who, what); + } - synchronized (sLock) { - // NOTE: It would be cleaner to move the implementation of - // WindowManagerImpl into a static inner class, and have this - // public impl just call into that. Then we can make multiple - // instances of WindowManagerImpl for compat mode rather than - // having to make wrappers. - WindowManager wm = sCompatWindowManagers.get(compatInfo); - if (wm == null) { - wm = new CompatModeWrapper(sWindowManager, cih); - sCompatWindowManagers.put(compatInfo, wm); - } - return wm; - } + public void startTrimMemory(int level) { + mState.startTrimMemory(level); } - public static WindowManager getDefault(CompatibilityInfoHolder compatInfo) { - return new CompatModeWrapper(sWindowManager, compatInfo); + public void endTrimMemory() { + mState.endTrimMemory(); } - - public boolean isHardwareAccelerated() { - return false; + + public void trimLocalMemory() { + mState.trimLocalMemory(); } - - public void addView(View view) { - addView(view, new WindowManager.LayoutParams( - WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE)); + + public void dumpGfxInfo(FileDescriptor fd) { + mState.dumpGfxInfo(fd); } - public void addView(View view, ViewGroup.LayoutParams params) { - addView(view, params, null); + public void setStoppedState(IBinder token, boolean stopped) { + mState.setStoppedState(token, stopped); } - - public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) { - if (false) Log.v("WindowManager", "addView view=" + view); - if (!(params instanceof WindowManager.LayoutParams)) { - throw new IllegalArgumentException( - "Params must be WindowManager.LayoutParams"); + 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); } - final WindowManager.LayoutParams wparams - = (WindowManager.LayoutParams)params; - - 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) { + 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) { - for (ViewRootImpl root : mRoots) { - root.loadSystemProperties(); + synchronized (this) { + for (ViewRootImpl root : mRoots) { + root.loadSystemProperties(); + } } } } - } - }; - SystemProperties.addChangeCallback(mSystemPropertyUpdater); - } + }; + 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= 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 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); } } } - } - /** - * @param level See {@link android.content.ComponentCallbacks} - * - * @hide - */ - 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(getDefaultDisplay()))) { - // Destroy all hardware surfaces and resources associated to - // known windows - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; + private int findViewLocked(View view, boolean required) { + synchronized (this) { + if (mViews != null) { + final int count = mViews.length; for (int i = 0; i < count; i++) { - mRoots[i].terminateHardwareResources(); + if (mViews[i] == view) { + return i; + } } } - // Force a full memory flush - mNeedsEglTerminate = true; - HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); - return; + if (required) { + throw new IllegalArgumentException("View not attached to window manager"); + } + return -1; } - - HardwareRenderer.startTrimMemory(level); } - } - /** - * @hide - */ - public void endTrimMemory() { - HardwareRenderer.endTrimMemory(); + 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; + } - if (mNeedsEglTerminate) { - ManagedEGLContext.doTerminate(); - mNeedsEglTerminate = false; + HardwareRenderer.startTrimMemory(level); + } } - } - /** - * @hide - */ - 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 endTrimMemory() { + HardwareRenderer.endTrimMemory(); + + if (mNeedsEglTerminate) { + ManagedEGLContext.doTerminate(); + mNeedsEglTerminate = false; } } - } - /** - * @hide - */ - public void dumpGfxInfo(FileDescriptor fd) { - FileOutputStream fout = new FileOutputStream(fd); - PrintWriter pw = new PrintWriter(fout); - try { + public void trimLocalMemory() { 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); + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].destroyHardwareLayers(); + } + } + } - HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer; - if (renderer != null) { - renderer.dumpGfxInfo(pw); - } - } + 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("\nView hierarchy:\n"); + pw.println("Profile data in ms:"); - int viewsCount = 0; - int displayListsSize = 0; - int[] info = new int[2]; + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + String name = getWindowName(root); + pw.printf("\n\t%s", name); - 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()); + HardwareRenderer renderer = + root.getView().mAttachInfo.mHardwareRenderer; + if (renderer != null) { + renderer.dumpGfxInfo(pw); + } } - pw.printf("\n\n"); - viewsCount += info[0]; - displayListsSize += info[1]; - } + pw.println("\nView hierarchy:\n"); - 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(); - } - } + int viewsCount = 0; + int displayListsSize = 0; + int[] info = new int[2]; - private static String getWindowName(ViewRootImpl root) { - return root.mWindowAttributes.getTitle() + "/" + - root.getClass().getName() + '@' + Integer.toHexString(root.hashCode()); - } + for (int i = 0; i < count; i++) { + ViewRootImpl root = mRoots[i]; + root.dumpGfxInfo(info); - public void setStoppedState(IBinder token, boolean stopped) { - synchronized (this) { - if (mViews == null) - return; - int count = mViews.length; - for (int i=0; i 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); + 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); + } + } + } } } - } - private int findViewLocked(View view, boolean required) { - synchronized (this) { - final int count = mViews != null ? mViews.length : 0; - for (int i=0; i