/* * Copyright (C) 2006 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.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); } } /** * 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. * *
Applications will not normally use WindowManager directly, instead relying * on the higher-level facilities in {@link android.app.Activity} and * {@link android.app.Dialog}. * *
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
* activity -- the window manager will not normally allow you to add arbitrary
* windows that are not associated with an activity.
*
* @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;
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 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());
}
public WindowManagerImpl makeCompatible(CompatibilityInfoHolder compatInfo) {
if (compatInfo == mCompatibilityInfo) {
return this;
}
if (compatInfo == null && mParentWindow == null) {
return getDefault();
}
return new WindowManagerImpl(mState, mParentWindow, compatInfo);
}
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
mState.addView(view, params, mParentWindow, mCompatibilityInfo);
}
@Override
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
mState.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mState.removeView(view, false);
}
@Override
public void removeViewImmediate(View view) {
mState.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