diff options
Diffstat (limited to 'services/java/com/android/server/WindowManagerService.java')
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 12089 |
1 files changed, 0 insertions, 12089 deletions
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java deleted file mode 100644 index b662c5501187..000000000000 --- a/services/java/com/android/server/WindowManagerService.java +++ /dev/null @@ -1,12089 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; -import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND; -import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; -import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; -import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; -import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; -import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; -import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; -import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; -import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; -import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; - -import com.android.internal.app.IBatteryStats; -import com.android.internal.policy.PolicyManager; -import com.android.internal.policy.impl.PhoneWindowManager; -import com.android.internal.view.BaseInputHandler; -import com.android.internal.view.IInputContext; -import com.android.internal.view.IInputMethodClient; -import com.android.internal.view.IInputMethodManager; -import com.android.internal.view.WindowManagerPolicyThread; -import com.android.server.am.BatteryStatsService; - -import android.Manifest; -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.app.StatusBarManager; -import android.app.admin.DevicePolicyManager; -import android.content.BroadcastReceiver; -import android.content.ClipData; -import android.content.ClipDescription; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.Region; -import android.graphics.Typeface; -import android.graphics.Paint.FontMetricsInt; -import android.os.BatteryStats; -import android.os.Binder; -import android.os.Bundle; -import android.os.Debug; -import android.os.Handler; -import android.os.IBinder; -import android.os.LocalPowerManager; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Power; -import android.os.PowerManager; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.StrictMode; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.os.TokenWatcher; -import android.provider.Settings; -import android.util.DisplayMetrics; -import android.util.EventLog; -import android.util.Log; -import android.util.Slog; -import android.util.SparseIntArray; -import android.util.TypedValue; -import android.view.Display; -import android.view.DragEvent; -import android.view.Gravity; -import android.view.IApplicationToken; -import android.view.IOnKeyguardExitResult; -import android.view.IRotationWatcher; -import android.view.IWindow; -import android.view.IWindowManager; -import android.view.IWindowSession; -import android.view.InputChannel; -import android.view.InputDevice; -import android.view.InputEvent; -import android.view.InputHandler; -import android.view.InputQueue; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.Surface; -import android.view.SurfaceSession; -import android.view.View; -import android.view.ViewTreeObserver; -import android.view.WindowManager; -import android.view.WindowManagerImpl; -import android.view.WindowManagerPolicy; -import android.view.Surface.OutOfResourcesException; -import android.view.WindowManager.LayoutParams; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.Transformation; - -import java.io.BufferedWriter; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.Socket; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; - -/** {@hide} */ -public class WindowManagerService extends IWindowManager.Stub - implements Watchdog.Monitor { - static final String TAG = "WindowManager"; - static final boolean DEBUG = false; - static final boolean DEBUG_ADD_REMOVE = false; - static final boolean DEBUG_FOCUS = false; - static final boolean DEBUG_ANIM = false; - static final boolean DEBUG_LAYOUT = false; - static final boolean DEBUG_RESIZE = false; - static final boolean DEBUG_LAYERS = false; - static final boolean DEBUG_INPUT = false; - static final boolean DEBUG_INPUT_METHOD = false; - static final boolean DEBUG_VISIBILITY = false; - static final boolean DEBUG_WINDOW_MOVEMENT = false; - static final boolean DEBUG_TOKEN_MOVEMENT = false; - static final boolean DEBUG_ORIENTATION = false; - static final boolean DEBUG_CONFIGURATION = false; - static final boolean DEBUG_APP_TRANSITIONS = false; - static final boolean DEBUG_STARTING_WINDOW = false; - static final boolean DEBUG_REORDER = false; - static final boolean DEBUG_WALLPAPER = false; - static final boolean DEBUG_DRAG = false; - static final boolean SHOW_TRANSACTIONS = false; - static final boolean HIDE_STACK_CRAWLS = true; - - static final boolean PROFILE_ORIENTATION = false; - static final boolean BLUR = true; - static final boolean localLOGV = DEBUG; - - /** How much to multiply the policy's type layer, to reserve room - * for multiple windows of the same type and Z-ordering adjustment - * with TYPE_LAYER_OFFSET. */ - static final int TYPE_LAYER_MULTIPLIER = 10000; - - /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above - * or below others in the same layer. */ - static final int TYPE_LAYER_OFFSET = 1000; - - /** How much to increment the layer for each window, to reserve room - * for effect surfaces between them. - */ - static final int WINDOW_LAYER_MULTIPLIER = 5; - - /** The maximum length we will accept for a loaded animation duration: - * this is 10 seconds. - */ - static final int MAX_ANIMATION_DURATION = 10*1000; - - /** Amount of time (in milliseconds) to animate the dim surface from one - * value to another, when no window animation is driving it. - */ - static final int DEFAULT_DIM_DURATION = 200; - - /** Amount of time (in milliseconds) to animate the fade-in-out transition for - * compatible windows. - */ - static final int DEFAULT_FADE_IN_OUT_DURATION = 400; - - /** - * If true, the window manager will do its own custom freezing and general - * management of the screen during rotation. - */ - static final boolean CUSTOM_SCREEN_ROTATION = true; - - // Maximum number of milliseconds to wait for input event injection. - // FIXME is this value reasonable? - private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; - - // Maximum number of milliseconds to wait for input devices to be enumerated before - // proceding with safe mode detection. - private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; - - // Default input dispatching timeout in nanoseconds. - private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; - - static final int UPDATE_FOCUS_NORMAL = 0; - static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; - static final int UPDATE_FOCUS_PLACING_SURFACES = 2; - static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; - - private static final String SYSTEM_SECURE = "ro.secure"; - private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; - - /** - * Condition waited on by {@link #reenableKeyguard} to know the call to - * the window policy has finished. - * This is set to true only if mKeyguardTokenWatcher.acquired() has - * actually disabled the keyguard. - */ - private boolean mKeyguardDisabled = false; - - private static final int ALLOW_DISABLE_YES = 1; - private static final int ALLOW_DISABLE_NO = 0; - private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager - private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher - - final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher( - new Handler(), "WindowManagerService.mKeyguardTokenWatcher") { - public void acquired() { - if (shouldAllowDisableKeyguard()) { - mPolicy.enableKeyguard(false); - mKeyguardDisabled = true; - } else { - Log.v(TAG, "Not disabling keyguard since device policy is enforced"); - } - } - public void released() { - mPolicy.enableKeyguard(true); - synchronized (mKeyguardTokenWatcher) { - mKeyguardDisabled = false; - mKeyguardTokenWatcher.notifyAll(); - } - } - }; - - final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - mPolicy.enableKeyguard(true); - synchronized(mKeyguardTokenWatcher) { - // lazily evaluate this next time we're asked to disable keyguard - mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; - mKeyguardDisabled = false; - } - } - }; - - final Context mContext; - - final boolean mHaveInputMethods; - - final boolean mLimitedAlphaCompositing; - - final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); - - final IActivityManager mActivityManager; - - final IBatteryStats mBatteryStats; - - private static final boolean mInEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); - - /** - * All currently active sessions with clients. - */ - final HashSet<Session> mSessions = new HashSet<Session>(); - - /** - * Mapping from an IWindow IBinder to the server's Window object. - * This is also used as the lock for all of our state. - */ - final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>(); - - /** - * Mapping from a token IBinder to a WindowToken object. - */ - final HashMap<IBinder, WindowToken> mTokenMap = - new HashMap<IBinder, WindowToken>(); - - /** - * Window tokens that are in the process of exiting, but still - * on screen for animations. - */ - final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>(); - - /** - * Z-ordered (bottom-most first) list of all application tokens, for - * controlling the ordering of windows in different applications. This - * contains AppWindowToken objects. - */ - final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>(); - - /** - * Application tokens that are in the process of exiting, but still - * on screen for animations. - */ - final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>(); - - /** - * List of window tokens that have finished starting their application, - * and now need to have the policy remove their windows. - */ - final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>(); - - /** - * Z-ordered (bottom-most first) list of all Window objects. - */ - final ArrayList<WindowState> mWindows = new ArrayList<WindowState>(); - - /** - * Windows that are being resized. Used so we can tell the client about - * the resize after closing the transaction in which we resized the - * underlying surface. - */ - final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>(); - - /** - * Windows whose animations have ended and now must be removed. - */ - final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>(); - - /** - * Used when processing mPendingRemove to avoid working on the original array. - */ - WindowState[] mPendingRemoveTmp = new WindowState[20]; - - /** - * Windows whose surface should be destroyed. - */ - final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>(); - - /** - * Windows that have lost input focus and are waiting for the new - * focus window to be displayed before they are told about this. - */ - ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>(); - - /** - * This is set when we have run out of memory, and will either be an empty - * list or contain windows that need to be force removed. - */ - ArrayList<WindowState> mForceRemoves; - - /** - * Used when rebuilding window list to keep track of windows that have - * been removed. - */ - WindowState[] mRebuildTmp = new WindowState[20]; - - IInputMethodManager mInputMethodManager; - - SurfaceSession mFxSession; - private DimAnimator mDimAnimator = null; - Surface mBlurSurface; - boolean mBlurShown; - Watermark mWatermark; - StrictModeFlash mStrictModeFlash; - ScreenRotationAnimation mScreenRotationAnimation; - - int mTransactionSequence = 0; - - final float[] mTmpFloats = new float[9]; - - boolean mSafeMode; - boolean mDisplayEnabled = false; - boolean mSystemBooted = false; - int mInitialDisplayWidth = 0; - int mInitialDisplayHeight = 0; - int mRotation = 0; - int mRequestedRotation = 0; - int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - int mLastRotationFlags; - ArrayList<IRotationWatcher> mRotationWatchers - = new ArrayList<IRotationWatcher>(); - int mDeferredRotation; - int mDeferredRotationAnimFlags; - - boolean mLayoutNeeded = true; - boolean mAnimationPending = false; - boolean mDisplayFrozen = false; - boolean mWaitingForConfig = false; - boolean mWindowsFreezingScreen = false; - long mFreezeGcPending = 0; - int mAppsFreezingScreen = 0; - - int mLayoutSeq = 0; - - // State while inside of layoutAndPlaceSurfacesLocked(). - boolean mFocusMayChange; - - Configuration mCurConfiguration = new Configuration(); - - // This is held as long as we have the screen frozen, to give us time to - // perform a rotation animation when turning off shows the lock screen which - // changes the orientation. - PowerManager.WakeLock mScreenFrozenLock; - - // State management of app transitions. When we are preparing for a - // transition, mNextAppTransition will be the kind of transition to - // perform or TRANSIT_NONE if we are not waiting. If we are waiting, - // mOpeningApps and mClosingApps are the lists of tokens that will be - // made visible or hidden at the next transition. - int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; - String mNextAppTransitionPackage; - int mNextAppTransitionEnter; - int mNextAppTransitionExit; - boolean mAppTransitionReady = false; - boolean mAppTransitionRunning = false; - boolean mAppTransitionTimeout = false; - boolean mStartingIconInTransition = false; - boolean mSkipAppTransitionAnimation = false; - final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>(); - final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>(); - final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>(); - final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>(); - - Display mDisplay; - - H mH = new H(); - - WindowState mCurrentFocus = null; - WindowState mLastFocus = null; - - // This just indicates the window the input method is on top of, not - // necessarily the window its input is going to. - WindowState mInputMethodTarget = null; - boolean mInputMethodTargetWaitingAnim; - int mInputMethodAnimLayerAdjustment; - - WindowState mInputMethodWindow = null; - final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); - - boolean mHardKeyboardAvailable; - boolean mHardKeyboardEnabled; - OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; - - final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); - - // If non-null, this is the currently visible window that is associated - // with the wallpaper. - WindowState mWallpaperTarget = null; - // If non-null, we are in the middle of animating from one wallpaper target - // to another, and this is the lower one in Z-order. - WindowState mLowerWallpaperTarget = null; - // If non-null, we are in the middle of animating from one wallpaper target - // to another, and this is the higher one in Z-order. - WindowState mUpperWallpaperTarget = null; - // Window currently running an animation that has requested it be detached - // from the wallpaper. This means we need to ensure the wallpaper is - // visible behind it in case it animates in a way that would allow it to be - // seen. - WindowState mWindowDetachedWallpaper = null; - int mWallpaperAnimLayerAdjustment; - float mLastWallpaperX = -1; - float mLastWallpaperY = -1; - float mLastWallpaperXStep = -1; - float mLastWallpaperYStep = -1; - // This is set when we are waiting for a wallpaper to tell us it is done - // changing its scroll position. - WindowState mWaitingOnWallpaper; - // The last time we had a timeout when waiting for a wallpaper. - long mLastWallpaperTimeoutTime; - // We give a wallpaper up to 150ms to finish scrolling. - static final long WALLPAPER_TIMEOUT = 150; - // Time we wait after a timeout before trying to wait again. - static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; - - AppWindowToken mFocusedApp = null; - - PowerManagerService mPowerManager; - - float mWindowAnimationScale = 1.0f; - float mTransitionAnimationScale = 1.0f; - - final InputManager mInputManager; - - // Who is holding the screen on. - Session mHoldingScreenOn; - PowerManager.WakeLock mHoldingScreenWakeLock; - - boolean mTurnOnScreen; - - /** - * Drag/drop state - */ - class DragState { - IBinder mToken; - Surface mSurface; - int mFlags; - IBinder mLocalWin; - ClipData mData; - ClipDescription mDataDescription; - boolean mDragResult; - float mCurrentX, mCurrentY; - float mThumbOffsetX, mThumbOffsetY; - InputChannel mServerChannel, mClientChannel; - WindowState mTargetWindow; - ArrayList<WindowState> mNotifiedWindows; - boolean mDragInProgress; - - private final Region mTmpRegion = new Region(); - - DragState(IBinder token, Surface surface, int flags, IBinder localWin) { - mToken = token; - mSurface = surface; - mFlags = flags; - mLocalWin = localWin; - mNotifiedWindows = new ArrayList<WindowState>(); - } - - void reset() { - if (mSurface != null) { - mSurface.destroy(); - } - mSurface = null; - mFlags = 0; - mLocalWin = null; - mToken = null; - mData = null; - mThumbOffsetX = mThumbOffsetY = 0; - mNotifiedWindows = null; - } - - void register() { - if (DEBUG_DRAG) Slog.d(TAG, "registering drag input channel"); - if (mClientChannel != null) { - Slog.e(TAG, "Duplicate register of drag input channel"); - } else { - InputChannel[] channels = InputChannel.openInputChannelPair("drag"); - mServerChannel = channels[0]; - mClientChannel = channels[1]; - mInputManager.registerInputChannel(mServerChannel, null); - InputQueue.registerInputChannel(mClientChannel, mDragInputHandler, - mH.getLooper().getQueue()); - } - } - - void unregister() { - if (DEBUG_DRAG) Slog.d(TAG, "unregistering drag input channel"); - if (mClientChannel == null) { - Slog.e(TAG, "Unregister of nonexistent drag input channel"); - } else { - mInputManager.unregisterInputChannel(mServerChannel); - InputQueue.unregisterInputChannel(mClientChannel); - mClientChannel.dispose(); - mServerChannel.dispose(); - mClientChannel = null; - mServerChannel = null; - } - } - - int getDragLayerLw() { - return mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG) - * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; - } - - /* call out to each visible window/session informing it about the drag - */ - void broadcastDragStartedLw(final float touchX, final float touchY) { - // Cache a base-class instance of the clip metadata so that parceling - // works correctly in calling out to the apps. - mDataDescription = (mData != null) ? mData.getDescription() : null; - mNotifiedWindows.clear(); - mDragInProgress = true; - - if (DEBUG_DRAG) { - Slog.d(TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")"); - } - - final int N = mWindows.size(); - for (int i = 0; i < N; i++) { - sendDragStartedLw(mWindows.get(i), touchX, touchY, mDataDescription); - } - } - - /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the - * designated window is potentially a drop recipient. There are race situations - * around DRAG_ENDED broadcast, so we make sure that once we've declared that - * the drag has ended, we never send out another DRAG_STARTED for this drag action. - * - * This method clones the 'event' parameter if it's being delivered to the same - * process, so it's safe for the caller to call recycle() on the event afterwards. - */ - private void sendDragStartedLw(WindowState newWin, float touchX, float touchY, - ClipDescription desc) { - // Don't actually send the event if the drag is supposed to be pinned - // to the originating window but 'newWin' is not that window. - if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) { - final IBinder winBinder = newWin.mClient.asBinder(); - if (winBinder != mLocalWin) { - if (DEBUG_DRAG) { - Slog.d(TAG, "Not dispatching local DRAG_STARTED to " + newWin); - } - return; - } - } - - if (mDragInProgress && newWin.isPotentialDragTarget()) { - DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED, - touchX - newWin.mFrame.left, touchY - newWin.mFrame.top, - null, desc, null, false); - try { - newWin.mClient.dispatchDragEvent(event); - // track each window that we've notified that the drag is starting - mNotifiedWindows.add(newWin); - } catch (RemoteException e) { - Slog.w(TAG, "Unable to drag-start window " + newWin); - } finally { - // if the callee was local, the dispatch has already recycled the event - if (Process.myPid() != newWin.mSession.mPid) { - event.recycle(); - } - } - } - } - - /* helper - construct and send a DRAG_STARTED event only if the window has not - * previously been notified, i.e. it became visible after the drag operation - * was begun. This is a rare case. - */ - private void sendDragStartedIfNeededLw(WindowState newWin) { - if (mDragInProgress) { - // If we have sent the drag-started, we needn't do so again - for (WindowState ws : mNotifiedWindows) { - if (ws == newWin) { - return; - } - } - if (DEBUG_DRAG) { - Slog.d(TAG, "need to send DRAG_STARTED to new window " + newWin); - } - sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription); - } - } - - void broadcastDragEndedLw() { - if (DEBUG_DRAG) { - Slog.d(TAG, "broadcasting DRAG_ENDED"); - } - DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, - 0, 0, null, null, null, mDragResult); - for (WindowState ws: mNotifiedWindows) { - try { - ws.mClient.dispatchDragEvent(evt); - } catch (RemoteException e) { - Slog.w(TAG, "Unable to drag-end window " + ws); - } - } - mNotifiedWindows.clear(); - mDragInProgress = false; - evt.recycle(); - } - - void endDragLw() { - mDragState.broadcastDragEndedLw(); - - // stop intercepting input - mDragState.unregister(); - mInputMonitor.updateInputWindowsLw(true /*force*/); - - // free our resources and drop all the object references - mDragState.reset(); - mDragState = null; - - if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-drag rotation"); - boolean changed = setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - if (changed) { - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - } - - void notifyMoveLw(float x, float y) { - final int myPid = Process.myPid(); - - // Move the surface to the given touch - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION notifyMoveLw"); - Surface.openTransaction(); - try { - mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY)); - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " - + mSurface + ": pos=(" + - (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")"); - } finally { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION notifyMoveLw"); - } - - // Tell the affected window - WindowState touchedWin = getTouchedWinAtPointLw(x, y); - if (touchedWin == null) { - if (DEBUG_DRAG) Slog.d(TAG, "No touched win at x=" + x + " y=" + y); - return; - } - if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) { - final IBinder touchedBinder = touchedWin.mClient.asBinder(); - if (touchedBinder != mLocalWin) { - // This drag is pinned only to the originating window, but the drag - // point is outside that window. Pretend it's over empty space. - touchedWin = null; - } - } - try { - // have we dragged over a new window? - if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) { - if (DEBUG_DRAG) { - Slog.d(TAG, "sending DRAG_EXITED to " + mTargetWindow); - } - // force DRAG_EXITED_EVENT if appropriate - DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED, - x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top, - null, null, null, false); - mTargetWindow.mClient.dispatchDragEvent(evt); - if (myPid != mTargetWindow.mSession.mPid) { - evt.recycle(); - } - } - if (touchedWin != null) { - if (false && DEBUG_DRAG) { - Slog.d(TAG, "sending DRAG_LOCATION to " + touchedWin); - } - DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION, - x - touchedWin.mFrame.left, y - touchedWin.mFrame.top, - null, null, null, false); - touchedWin.mClient.dispatchDragEvent(evt); - if (myPid != touchedWin.mSession.mPid) { - evt.recycle(); - } - } - } catch (RemoteException e) { - Slog.w(TAG, "can't send drag notification to windows"); - } - mTargetWindow = touchedWin; - } - - // Tell the drop target about the data. Returns 'true' if we can immediately - // dispatch the global drag-ended message, 'false' if we need to wait for a - // result from the recipient. - boolean notifyDropLw(float x, float y) { - WindowState touchedWin = getTouchedWinAtPointLw(x, y); - if (touchedWin == null) { - // "drop" outside a valid window -- no recipient to apply a - // timeout to, and we can send the drag-ended message immediately. - mDragResult = false; - return true; - } - - if (DEBUG_DRAG) { - Slog.d(TAG, "sending DROP to " + touchedWin); - } - final int myPid = Process.myPid(); - final IBinder token = touchedWin.mClient.asBinder(); - DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP, - x - touchedWin.mFrame.left, y - touchedWin.mFrame.top, - null, null, mData, false); - try { - touchedWin.mClient.dispatchDragEvent(evt); - - // 5 second timeout for this window to respond to the drop - mH.removeMessages(H.DRAG_END_TIMEOUT, token); - Message msg = mH.obtainMessage(H.DRAG_END_TIMEOUT, token); - mH.sendMessageDelayed(msg, 5000); - } catch (RemoteException e) { - Slog.w(TAG, "can't send drop notification to win " + touchedWin); - return true; - } finally { - if (myPid != touchedWin.mSession.mPid) { - evt.recycle(); - } - } - mToken = token; - return false; - } - - // Find the visible, touch-deliverable window under the given point - private WindowState getTouchedWinAtPointLw(float xf, float yf) { - WindowState touchedWin = null; - final int x = (int) xf; - final int y = (int) yf; - final ArrayList<WindowState> windows = mWindows; - final int N = windows.size(); - for (int i = N - 1; i >= 0; i--) { - WindowState child = windows.get(i); - final int flags = child.mAttrs.flags; - if (!child.isVisibleLw()) { - // not visible == don't tell about drags - continue; - } - if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) { - // not touchable == don't tell about drags - continue; - } - - child.getTouchableRegion(mTmpRegion); - - final int touchFlags = flags & - (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); - if (mTmpRegion.contains(x, y) || touchFlags == 0) { - // Found it - touchedWin = child; - break; - } - } - - return touchedWin; - } - } - - DragState mDragState = null; - private final InputHandler mDragInputHandler = new BaseInputHandler() { - @Override - public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) { - boolean handled = false; - try { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 - && mDragState != null) { - boolean endDrag = false; - final float newX = event.getRawX(); - final float newY = event.getRawY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - if (DEBUG_DRAG) { - Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer"); - } - } break; - - case MotionEvent.ACTION_MOVE: { - synchronized (mWindowMap) { - // move the surface and tell the involved window(s) where we are - mDragState.notifyMoveLw(newX, newY); - } - } break; - - case MotionEvent.ACTION_UP: { - if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at " - + newX + "," + newY); - synchronized (mWindowMap) { - endDrag = mDragState.notifyDropLw(newX, newY); - } - } break; - - case MotionEvent.ACTION_CANCEL: { - if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!"); - endDrag = true; - } break; - } - - if (endDrag) { - if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state"); - // tell all the windows that the drag has ended - synchronized (mWindowMap) { - mDragState.endDragLw(); - } - } - - handled = true; - } - } catch (Exception e) { - Slog.e(TAG, "Exception caught by drag handleMotion", e); - } finally { - finishedCallback.finished(handled); - } - } - }; - - /** - * Whether the UI is currently running in touch mode (not showing - * navigational focus because the user is directly pressing the screen). - */ - boolean mInTouchMode = false; - - private ViewServer mViewServer; - private ArrayList<WindowChangeListener> mWindowChangeListeners = - new ArrayList<WindowChangeListener>(); - private boolean mWindowsChanged = false; - - public interface WindowChangeListener { - public void windowsChanged(); - public void focusChanged(); - } - - final Configuration mTempConfiguration = new Configuration(); - int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED; - - // The frame use to limit the size of the app running in compatibility mode. - Rect mCompatibleScreenFrame = new Rect(); - // The surface used to fill the outer rim of the app running in compatibility mode. - Surface mBackgroundFillerSurface = null; - WindowState mBackgroundFillerTarget = null; - - public static WindowManagerService main(Context context, - PowerManagerService pm, boolean haveInputMethods) { - WMThread thr = new WMThread(context, pm, haveInputMethods); - thr.start(); - - synchronized (thr) { - while (thr.mService == null) { - try { - thr.wait(); - } catch (InterruptedException e) { - } - } - return thr.mService; - } - } - - static class WMThread extends Thread { - WindowManagerService mService; - - private final Context mContext; - private final PowerManagerService mPM; - private final boolean mHaveInputMethods; - - public WMThread(Context context, PowerManagerService pm, - boolean haveInputMethods) { - super("WindowManager"); - mContext = context; - mPM = pm; - mHaveInputMethods = haveInputMethods; - } - - public void run() { - Looper.prepare(); - WindowManagerService s = new WindowManagerService(mContext, mPM, - mHaveInputMethods); - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_DISPLAY); - android.os.Process.setCanSelfBackground(false); - - synchronized (this) { - mService = s; - notifyAll(); - } - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i(TAG, "Enabled StrictMode logging for WMThread's Looper"); - } - - Looper.loop(); - } - } - - static class PolicyThread extends Thread { - private final WindowManagerPolicy mPolicy; - private final WindowManagerService mService; - private final Context mContext; - private final PowerManagerService mPM; - boolean mRunning = false; - - public PolicyThread(WindowManagerPolicy policy, - WindowManagerService service, Context context, - PowerManagerService pm) { - super("WindowManagerPolicy"); - mPolicy = policy; - mService = service; - mContext = context; - mPM = pm; - } - - public void run() { - Looper.prepare(); - WindowManagerPolicyThread.set(this, Looper.myLooper()); - - //Looper.myLooper().setMessageLogging(new LogPrinter( - // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM)); - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_FOREGROUND); - android.os.Process.setCanSelfBackground(false); - mPolicy.init(mContext, mService, mPM); - - synchronized (this) { - mRunning = true; - notifyAll(); - } - - // For debug builds, log event loop stalls to dropbox for analysis. - if (StrictMode.conditionallyEnableDebugLogging()) { - Slog.i(TAG, "Enabled StrictMode for PolicyThread's Looper"); - } - - Looper.loop(); - } - } - - private WindowManagerService(Context context, PowerManagerService pm, - boolean haveInputMethods) { - mContext = context; - mHaveInputMethods = haveInputMethods; - mLimitedAlphaCompositing = context.getResources().getBoolean( - com.android.internal.R.bool.config_sf_limitedAlpha); - - mPowerManager = pm; - mPowerManager.setPolicy(mPolicy); - PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE); - mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - "SCREEN_FROZEN"); - mScreenFrozenLock.setReferenceCounted(false); - - mActivityManager = ActivityManagerNative.getDefault(); - mBatteryStats = BatteryStatsService.getService(); - - // Get persisted window scale setting - mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(), - Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); - mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(), - Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); - - // Track changes to DevicePolicyManager state so we can enable/disable keyguard. - IntentFilter filter = new IntentFilter(); - filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - mContext.registerReceiver(mBroadcastReceiver, filter); - - mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, - "KEEP_SCREEN_ON_FLAG"); - mHoldingScreenWakeLock.setReferenceCounted(false); - - mInputManager = new InputManager(context, this); - - PolicyThread thr = new PolicyThread(mPolicy, this, context, pm); - thr.start(); - - synchronized (thr) { - while (!thr.mRunning) { - try { - thr.wait(); - } catch (InterruptedException e) { - } - } - } - - mInputManager.start(); - - // Add ourself to the Watchdog monitors. - Watchdog.getInstance().addMonitor(this); - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (RuntimeException e) { - // The window manager only throws security exceptions, so let's - // log all others. - if (!(e instanceof SecurityException)) { - Slog.e(TAG, "Window Manager Crash", e); - } - throw e; - } - } - - private void placeWindowAfter(WindowState pos, WindowState window) { - final int i = mWindows.indexOf(pos); - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( - TAG, "Adding window " + window + " at " - + (i+1) + " of " + mWindows.size() + " (after " + pos + ")"); - mWindows.add(i+1, window); - mWindowsChanged = true; - } - - private void placeWindowBefore(WindowState pos, WindowState window) { - final int i = mWindows.indexOf(pos); - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( - TAG, "Adding window " + window + " at " - + i + " of " + mWindows.size() + " (before " + pos + ")"); - mWindows.add(i, window); - mWindowsChanged = true; - } - - //This method finds out the index of a window that has the same app token as - //win. used for z ordering the windows in mWindows - private int findIdxBasedOnAppTokens(WindowState win) { - //use a local variable to cache mWindows - ArrayList<WindowState> localmWindows = mWindows; - int jmax = localmWindows.size(); - if(jmax == 0) { - return -1; - } - for(int j = (jmax-1); j >= 0; j--) { - WindowState wentry = localmWindows.get(j); - if(wentry.mAppToken == win.mAppToken) { - return j; - } - } - return -1; - } - - private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) { - final IWindow client = win.mClient; - final WindowToken token = win.mToken; - final ArrayList<WindowState> localmWindows = mWindows; - - final int N = localmWindows.size(); - final WindowState attached = win.mAttachedWindow; - int i; - if (attached == null) { - int tokenWindowsPos = token.windows.size(); - if (token.appWindowToken != null) { - int index = tokenWindowsPos-1; - if (index >= 0) { - // If this application has existing windows, we - // simply place the new window on top of them... but - // keep the starting window on top. - if (win.mAttrs.type == TYPE_BASE_APPLICATION) { - // Base windows go behind everything else. - placeWindowBefore(token.windows.get(0), win); - tokenWindowsPos = 0; - } else { - AppWindowToken atoken = win.mAppToken; - if (atoken != null && - token.windows.get(index) == atoken.startingWindow) { - placeWindowBefore(token.windows.get(index), win); - tokenWindowsPos--; - } else { - int newIdx = findIdxBasedOnAppTokens(win); - if(newIdx != -1) { - //there is a window above this one associated with the same - //apptoken note that the window could be a floating window - //that was created later or a window at the top of the list of - //windows associated with this token. - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { - Slog.v(TAG, "Adding window " + win + " at " - + (newIdx+1) + " of " + N); - } - localmWindows.add(newIdx+1, win); - mWindowsChanged = true; - } - } - } - } else { - if (localLOGV) Slog.v( - TAG, "Figuring out where to add app window " - + client.asBinder() + " (token=" + token + ")"); - // Figure out where the window should go, based on the - // order of applications. - final int NA = mAppTokens.size(); - WindowState pos = null; - for (i=NA-1; i>=0; i--) { - AppWindowToken t = mAppTokens.get(i); - if (t == token) { - i--; - break; - } - - // We haven't reached the token yet; if this token - // is not going to the bottom and has windows, we can - // use it as an anchor for when we do reach the token. - if (!t.sendingToBottom && t.windows.size() > 0) { - pos = t.windows.get(0); - } - } - // We now know the index into the apps. If we found - // an app window above, that gives us the position; else - // we need to look some more. - if (pos != null) { - // Move behind any windows attached to this one. - WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); - if (atoken != null) { - final int NC = atoken.windows.size(); - if (NC > 0) { - WindowState bottom = atoken.windows.get(0); - if (bottom.mSubLayer < 0) { - pos = bottom; - } - } - } - placeWindowBefore(pos, win); - } else { - // Continue looking down until we find the first - // token that has windows. - while (i >= 0) { - AppWindowToken t = mAppTokens.get(i); - final int NW = t.windows.size(); - if (NW > 0) { - pos = t.windows.get(NW-1); - break; - } - i--; - } - if (pos != null) { - // Move in front of any windows attached to this - // one. - WindowToken atoken = mTokenMap.get(pos.mClient.asBinder()); - if (atoken != null) { - final int NC = atoken.windows.size(); - if (NC > 0) { - WindowState top = atoken.windows.get(NC-1); - if (top.mSubLayer >= 0) { - pos = top; - } - } - } - placeWindowAfter(pos, win); - } else { - // Just search for the start of this layer. - final int myLayer = win.mBaseLayer; - for (i=0; i<N; i++) { - WindowState w = localmWindows.get(i); - if (w.mBaseLayer > myLayer) { - break; - } - } - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { - Slog.v(TAG, "Adding window " + win + " at " - + i + " of " + N); - } - localmWindows.add(i, win); - mWindowsChanged = true; - } - } - } - } else { - // Figure out where window should go, based on layer. - final int myLayer = win.mBaseLayer; - for (i=N-1; i>=0; i--) { - if (localmWindows.get(i).mBaseLayer <= myLayer) { - i++; - break; - } - } - if (i < 0) i = 0; - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( - TAG, "Adding window " + win + " at " - + i + " of " + N); - localmWindows.add(i, win); - mWindowsChanged = true; - } - if (addToToken) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); - token.windows.add(tokenWindowsPos, win); - } - - } else { - // Figure out this window's ordering relative to the window - // it is attached to. - final int NA = token.windows.size(); - final int sublayer = win.mSubLayer; - int largestSublayer = Integer.MIN_VALUE; - WindowState windowWithLargestSublayer = null; - for (i=0; i<NA; i++) { - WindowState w = token.windows.get(i); - final int wSublayer = w.mSubLayer; - if (wSublayer >= largestSublayer) { - largestSublayer = wSublayer; - windowWithLargestSublayer = w; - } - if (sublayer < 0) { - // For negative sublayers, we go below all windows - // in the same sublayer. - if (wSublayer >= sublayer) { - if (addToToken) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); - token.windows.add(i, win); - } - placeWindowBefore( - wSublayer >= 0 ? attached : w, win); - break; - } - } else { - // For positive sublayers, we go above all windows - // in the same sublayer. - if (wSublayer > sublayer) { - if (addToToken) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); - token.windows.add(i, win); - } - placeWindowBefore(w, win); - break; - } - } - } - if (i >= NA) { - if (addToToken) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token); - token.windows.add(win); - } - if (sublayer < 0) { - placeWindowBefore(attached, win); - } else { - placeWindowAfter(largestSublayer >= 0 - ? windowWithLargestSublayer - : attached, - win); - } - } - } - - if (win.mAppToken != null && addToToken) { - win.mAppToken.allAppWindows.add(win); - } - } - - static boolean canBeImeTarget(WindowState w) { - final int fl = w.mAttrs.flags - & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); - if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) - || w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { - if (DEBUG_INPUT_METHOD) { - Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); - if (!w.isVisibleOrAdding()) { - Slog.i(TAG, " mSurface=" + w.mSurface + " reportDestroy=" + w.mReportDestroySurface - + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility - + " policyVis=" + w.mPolicyVisibility + " attachHid=" + w.mAttachedHidden - + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); - if (w.mAppToken != null) { - Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); - } - } - } - return w.isVisibleOrAdding(); - } - return false; - } - - int findDesiredInputMethodWindowIndexLocked(boolean willMove) { - final ArrayList<WindowState> localmWindows = mWindows; - final int N = localmWindows.size(); - WindowState w = null; - int i = N; - while (i > 0) { - i--; - w = localmWindows.get(i); - - if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i - + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); - if (canBeImeTarget(w)) { - //Slog.i(TAG, "Putting input method here!"); - - // Yet more tricksyness! If this window is a "starting" - // window, we do actually want to be on top of it, but - // it is not -really- where input will go. So if the caller - // is not actually looking to move the IME, look down below - // for a real window to target... - if (!willMove - && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING - && i > 0) { - WindowState wb = localmWindows.get(i-1); - if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { - i--; - w = wb; - } - } - break; - } - } - - if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); - - // Now, a special case -- if the last target's window is in the - // process of exiting, and is above the new target, keep on the - // last target to avoid flicker. Consider for example a Dialog with - // the IME shown: when the Dialog is dismissed, we want to keep - // the IME above it until it is completely gone so it doesn't drop - // behind the dialog or its full-screen scrim. - if (mInputMethodTarget != null && w != null - && mInputMethodTarget.isDisplayedLw() - && mInputMethodTarget.mExiting) { - if (mInputMethodTarget.mAnimLayer > w.mAnimLayer) { - w = mInputMethodTarget; - i = localmWindows.indexOf(w); - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w); - } - } - - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target=" - + w + " willMove=" + willMove); - - if (willMove && w != null) { - final WindowState curTarget = mInputMethodTarget; - if (curTarget != null && curTarget.mAppToken != null) { - - // Now some fun for dealing with window animations that - // modify the Z order. We need to look at all windows below - // the current target that are in this app, finding the highest - // visible one in layering. - AppWindowToken token = curTarget.mAppToken; - WindowState highestTarget = null; - int highestPos = 0; - if (token.animating || token.animation != null) { - int pos = 0; - pos = localmWindows.indexOf(curTarget); - while (pos >= 0) { - WindowState win = localmWindows.get(pos); - if (win.mAppToken != token) { - break; - } - if (!win.mRemoved) { - if (highestTarget == null || win.mAnimLayer > - highestTarget.mAnimLayer) { - highestTarget = win; - highestPos = pos; - } - } - pos--; - } - } - - if (highestTarget != null) { - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition=" - + mNextAppTransition + " " + highestTarget - + " animating=" + highestTarget.isAnimating() - + " layer=" + highestTarget.mAnimLayer - + " new layer=" + w.mAnimLayer); - - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - // If we are currently setting up for an animation, - // hold everything until we can find out what will happen. - mInputMethodTargetWaitingAnim = true; - mInputMethodTarget = highestTarget; - return highestPos + 1; - } else if (highestTarget.isAnimating() && - highestTarget.mAnimLayer > w.mAnimLayer) { - // If the window we are currently targeting is involved - // with an animation, and it is on top of the next target - // we will be over, then hold off on moving until - // that is done. - mInputMethodTargetWaitingAnim = true; - mInputMethodTarget = highestTarget; - return highestPos + 1; - } - } - } - } - - //Slog.i(TAG, "Placing input method @" + (i+1)); - if (w != null) { - if (willMove) { - if (DEBUG_INPUT_METHOD) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.w(TAG, "Moving IM target from " - + mInputMethodTarget + " to " + w, e); - } - mInputMethodTarget = w; - mInputMethodTargetWaitingAnim = false; - if (w.mAppToken != null) { - setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment); - } else { - setInputMethodAnimLayerAdjustment(0); - } - } - return i+1; - } - if (willMove) { - if (DEBUG_INPUT_METHOD) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.w(TAG, "Moving IM target from " - + mInputMethodTarget + " to null", e); - } - mInputMethodTarget = null; - setInputMethodAnimLayerAdjustment(0); - } - return -1; - } - - void addInputMethodWindowToListLocked(WindowState win) { - int pos = findDesiredInputMethodWindowIndexLocked(true); - if (pos >= 0) { - win.mTargetAppToken = mInputMethodTarget.mAppToken; - if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( - TAG, "Adding input method window " + win + " at " + pos); - mWindows.add(pos, win); - mWindowsChanged = true; - moveInputMethodDialogsLocked(pos+1); - return; - } - win.mTargetAppToken = null; - addWindowToListInOrderLocked(win, true); - moveInputMethodDialogsLocked(pos); - } - - void setInputMethodAnimLayerAdjustment(int adj) { - if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj); - mInputMethodAnimLayerAdjustment = adj; - WindowState imw = mInputMethodWindow; - if (imw != null) { - imw.mAnimLayer = imw.mLayer + adj; - if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw - + " anim layer: " + imw.mAnimLayer); - int wi = imw.mChildWindows.size(); - while (wi > 0) { - wi--; - WindowState cw = imw.mChildWindows.get(wi); - cw.mAnimLayer = cw.mLayer + adj; - if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw - + " anim layer: " + cw.mAnimLayer); - } - } - int di = mInputMethodDialogs.size(); - while (di > 0) { - di --; - imw = mInputMethodDialogs.get(di); - imw.mAnimLayer = imw.mLayer + adj; - if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw - + " anim layer: " + imw.mAnimLayer); - } - } - - private int tmpRemoveWindowLocked(int interestingPos, WindowState win) { - int wpos = mWindows.indexOf(win); - if (wpos >= 0) { - if (wpos < interestingPos) interestingPos--; - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win); - mWindows.remove(wpos); - mWindowsChanged = true; - int NC = win.mChildWindows.size(); - while (NC > 0) { - NC--; - WindowState cw = win.mChildWindows.get(NC); - int cpos = mWindows.indexOf(cw); - if (cpos >= 0) { - if (cpos < interestingPos) interestingPos--; - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at " - + cpos + ": " + cw); - mWindows.remove(cpos); - } - } - } - return interestingPos; - } - - private void reAddWindowToListInOrderLocked(WindowState win) { - addWindowToListInOrderLocked(win, false); - // This is a hack to get all of the child windows added as well - // at the right position. Child windows should be rare and - // this case should be rare, so it shouldn't be that big a deal. - int wpos = mWindows.indexOf(win); - if (wpos >= 0) { - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos - + ": " + win); - mWindows.remove(wpos); - mWindowsChanged = true; - reAddWindowLocked(wpos, win); - } - } - - void logWindowList(String prefix) { - int N = mWindows.size(); - while (N > 0) { - N--; - Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N)); - } - } - - void moveInputMethodDialogsLocked(int pos) { - ArrayList<WindowState> dialogs = mInputMethodDialogs; - - final int N = dialogs.size(); - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos); - for (int i=0; i<N; i++) { - pos = tmpRemoveWindowLocked(pos, dialogs.get(i)); - } - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "Window list w/pos=" + pos); - logWindowList(" "); - } - - if (pos >= 0) { - final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken; - if (pos < mWindows.size()) { - WindowState wp = mWindows.get(pos); - if (wp == mInputMethodWindow) { - pos++; - } - } - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos); - for (int i=0; i<N; i++) { - WindowState win = dialogs.get(i); - win.mTargetAppToken = targetAppToken; - pos = reAddWindowLocked(pos, win); - } - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "Final window list:"); - logWindowList(" "); - } - return; - } - for (int i=0; i<N; i++) { - WindowState win = dialogs.get(i); - win.mTargetAppToken = null; - reAddWindowToListInOrderLocked(win); - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "No IM target, final list:"); - logWindowList(" "); - } - } - } - - boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) { - final WindowState imWin = mInputMethodWindow; - final int DN = mInputMethodDialogs.size(); - if (imWin == null && DN == 0) { - return false; - } - - int imPos = findDesiredInputMethodWindowIndexLocked(true); - if (imPos >= 0) { - // In this case, the input method windows are to be placed - // immediately above the window they are targeting. - - // First check to see if the input method windows are already - // located here, and contiguous. - final int N = mWindows.size(); - WindowState firstImWin = imPos < N - ? mWindows.get(imPos) : null; - - // Figure out the actual input method window that should be - // at the bottom of their stack. - WindowState baseImWin = imWin != null - ? imWin : mInputMethodDialogs.get(0); - if (baseImWin.mChildWindows.size() > 0) { - WindowState cw = baseImWin.mChildWindows.get(0); - if (cw.mSubLayer < 0) baseImWin = cw; - } - - if (firstImWin == baseImWin) { - // The windows haven't moved... but are they still contiguous? - // First find the top IM window. - int pos = imPos+1; - while (pos < N) { - if (!(mWindows.get(pos)).mIsImWindow) { - break; - } - pos++; - } - pos++; - // Now there should be no more input method windows above. - while (pos < N) { - if ((mWindows.get(pos)).mIsImWindow) { - break; - } - pos++; - } - if (pos >= N) { - // All is good! - return false; - } - } - - if (imWin != null) { - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "Moving IM from " + imPos); - logWindowList(" "); - } - imPos = tmpRemoveWindowLocked(imPos, imWin); - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "List after removing with new pos " + imPos + ":"); - logWindowList(" "); - } - imWin.mTargetAppToken = mInputMethodTarget.mAppToken; - reAddWindowLocked(imPos, imWin); - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "List after moving IM to " + imPos + ":"); - logWindowList(" "); - } - if (DN > 0) moveInputMethodDialogsLocked(imPos+1); - } else { - moveInputMethodDialogsLocked(imPos); - } - - } else { - // In this case, the input method windows go in a fixed layer, - // because they aren't currently associated with a focus window. - - if (imWin != null) { - if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos); - tmpRemoveWindowLocked(0, imWin); - imWin.mTargetAppToken = null; - reAddWindowToListInOrderLocked(imWin); - if (DEBUG_INPUT_METHOD) { - Slog.v(TAG, "List with no IM target:"); - logWindowList(" "); - } - if (DN > 0) moveInputMethodDialogsLocked(-1);; - } else { - moveInputMethodDialogsLocked(-1);; - } - - } - - if (needAssignLayers) { - assignLayersLocked(); - } - - return true; - } - - void adjustInputMethodDialogsLocked() { - moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true)); - } - - final boolean isWallpaperVisible(WindowState wallpaperTarget) { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured=" - + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") - + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) - ? wallpaperTarget.mAppToken.animation : null) - + " upper=" + mUpperWallpaperTarget - + " lower=" + mLowerWallpaperTarget); - return (wallpaperTarget != null - && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null - && wallpaperTarget.mAppToken.animation != null))) - || mUpperWallpaperTarget != null - || mLowerWallpaperTarget != null; - } - - static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; - static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; - - int adjustWallpaperWindowsLocked() { - int changed = 0; - - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - - // First find top-most window that has asked to be on top of the - // wallpaper; all wallpapers go behind it. - final ArrayList<WindowState> localmWindows = mWindows; - int N = localmWindows.size(); - WindowState w = null; - WindowState foundW = null; - int foundI = 0; - WindowState topCurW = null; - int topCurI = 0; - int windowDetachedI = -1; - int i = N; - while (i > 0) { - i--; - w = localmWindows.get(i); - if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) { - if (topCurW == null) { - topCurW = w; - topCurI = i; - } - continue; - } - topCurW = null; - if (w != mWindowDetachedWallpaper && w.mAppToken != null) { - // If this window's app token is hidden and not animating, - // it is of no interest to us. - if (w.mAppToken.hidden && w.mAppToken.animation == null) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Skipping not hidden or animating token: " + w); - continue; - } - } - if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay=" - + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending - + " commitdrawpending=" + w.mCommitDrawPending); - if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay() - && (mWallpaperTarget == w - || (!w.mDrawPending && !w.mCommitDrawPending))) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Found wallpaper activity: #" + i + "=" + w); - foundW = w; - foundI = i; - if (w == mWallpaperTarget && ((w.mAppToken != null - && w.mAppToken.animation != null) - || w.mAnimation != null)) { - // The current wallpaper target is animating, so we'll - // look behind it for another possible target and figure - // out what is going on below. - if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w - + ": token animating, looking behind."); - continue; - } - break; - } else if (w == mWindowDetachedWallpaper) { - windowDetachedI = i; - } - } - - if (foundW == null && windowDetachedI >= 0) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Found animating detached wallpaper activity: #" + i + "=" + w); - foundW = w; - foundI = windowDetachedI; - } - - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - // If we are currently waiting for an app transition, and either - // the current target or the next target are involved with it, - // then hold off on doing anything with the wallpaper. - // Note that we are checking here for just whether the target - // is part of an app token... which is potentially overly aggressive - // (the app token may not be involved in the transition), but good - // enough (we'll just wait until whatever transition is pending - // executes). - if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Wallpaper not changing: waiting for app anim in current target"); - return 0; - } - if (foundW != null && foundW.mAppToken != null) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Wallpaper not changing: waiting for app anim in found target"); - return 0; - } - } - - if (mWallpaperTarget != foundW) { - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "New wallpaper target: " + foundW - + " oldTarget: " + mWallpaperTarget); - } - - mLowerWallpaperTarget = null; - mUpperWallpaperTarget = null; - - WindowState oldW = mWallpaperTarget; - mWallpaperTarget = foundW; - - // Now what is happening... if the current and new targets are - // animating, then we are in our super special mode! - if (foundW != null && oldW != null) { - boolean oldAnim = oldW.mAnimation != null - || (oldW.mAppToken != null && oldW.mAppToken.animation != null); - boolean foundAnim = foundW.mAnimation != null - || (foundW.mAppToken != null && foundW.mAppToken.animation != null); - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "New animation: " + foundAnim - + " old animation: " + oldAnim); - } - if (foundAnim && oldAnim) { - int oldI = localmWindows.indexOf(oldW); - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "New i: " + foundI + " old i: " + oldI); - } - if (oldI >= 0) { - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "Animating wallpapers: old#" + oldI - + "=" + oldW + "; new#" + foundI - + "=" + foundW); - } - - // Set the new target correctly. - if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) { - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "Old wallpaper still the target."); - } - mWallpaperTarget = oldW; - } - - // Now set the upper and lower wallpaper targets - // correctly, and make sure that we are positioning - // the wallpaper below the lower. - if (foundI > oldI) { - // The new target is on top of the old one. - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "Found target above old target."); - } - mUpperWallpaperTarget = foundW; - mLowerWallpaperTarget = oldW; - foundW = oldW; - foundI = oldI; - } else { - // The new target is below the old one. - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "Found target below old target."); - } - mUpperWallpaperTarget = oldW; - mLowerWallpaperTarget = foundW; - } - } - } - } - - } else if (mLowerWallpaperTarget != null) { - // Is it time to stop animating? - boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null - || (mLowerWallpaperTarget.mAppToken != null - && mLowerWallpaperTarget.mAppToken.animation != null); - boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null - || (mUpperWallpaperTarget.mAppToken != null - && mUpperWallpaperTarget.mAppToken.animation != null); - if (!lowerAnimating || !upperAnimating) { - if (DEBUG_WALLPAPER) { - Slog.v(TAG, "No longer animating wallpaper targets!"); - } - mLowerWallpaperTarget = null; - mUpperWallpaperTarget = null; - } - } - - boolean visible = foundW != null; - if (visible) { - // The window is visible to the compositor... but is it visible - // to the user? That is what the wallpaper cares about. - visible = isWallpaperVisible(foundW); - if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible); - - // If the wallpaper target is animating, we may need to copy - // its layer adjustment. Only do this if we are not transfering - // between two wallpaper targets. - mWallpaperAnimLayerAdjustment = - (mLowerWallpaperTarget == null && foundW.mAppToken != null) - ? foundW.mAppToken.animLayerAdjustment : 0; - - final int maxLayer = mPolicy.getMaxWallpaperLayer() - * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; - - // Now w is the window we are supposed to be behind... but we - // need to be sure to also be behind any of its attached windows, - // AND any starting window associated with it, AND below the - // maximum layer the policy allows for wallpapers. - while (foundI > 0) { - WindowState wb = localmWindows.get(foundI-1); - if (wb.mBaseLayer < maxLayer && - wb.mAttachedWindow != foundW && - (foundW.mAttachedWindow == null || - wb.mAttachedWindow != foundW.mAttachedWindow) && - (wb.mAttrs.type != TYPE_APPLICATION_STARTING || - foundW.mToken == null || wb.mToken != foundW.mToken)) { - // This window is not related to the previous one in any - // interesting way, so stop here. - break; - } - foundW = wb; - foundI--; - } - } else { - if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target"); - } - - if (foundW == null && topCurW != null) { - // There is no wallpaper target, so it goes at the bottom. - // We will assume it is the same place as last time, if known. - foundW = topCurW; - foundI = topCurI+1; - } else { - // Okay i is the position immediately above the wallpaper. Look at - // what is below it for later. - foundW = foundI > 0 ? localmWindows.get(foundI-1) : null; - } - - if (visible) { - if (mWallpaperTarget.mWallpaperX >= 0) { - mLastWallpaperX = mWallpaperTarget.mWallpaperX; - mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep; - } - if (mWallpaperTarget.mWallpaperY >= 0) { - mLastWallpaperY = mWallpaperTarget.mWallpaperY; - mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep; - } - } - - // Start stepping backwards from here, ensuring that our wallpaper windows - // are correctly placed. - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - if (token.hidden == visible) { - changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; - token.hidden = !visible; - // Need to do a layout to ensure the wallpaper now has the - // correct size. - mLayoutNeeded = true; - } - - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - - if (visible) { - updateWallpaperOffsetLocked(wallpaper, dw, dh, false); - } - - // First, make sure the client has the current visibility - // state. - if (wallpaper.mWallpaperVisible != visible) { - wallpaper.mWallpaperVisible = visible; - try { - if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG, - "Setting visibility of wallpaper " + wallpaper - + ": " + visible); - wallpaper.mClient.dispatchAppVisibility(visible); - } catch (RemoteException e) { - } - } - - wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win " - + wallpaper + " anim layer: " + wallpaper.mAnimLayer); - - // First, if this window is at the current index, then all - // is well. - if (wallpaper == foundW) { - foundI--; - foundW = foundI > 0 - ? localmWindows.get(foundI-1) : null; - continue; - } - - // The window didn't match... the current wallpaper window, - // wherever it is, is in the wrong place, so make sure it is - // not in the list. - int oldIndex = localmWindows.indexOf(wallpaper); - if (oldIndex >= 0) { - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at " - + oldIndex + ": " + wallpaper); - localmWindows.remove(oldIndex); - mWindowsChanged = true; - if (oldIndex < foundI) { - foundI--; - } - } - - // Now stick it in. - if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { - Slog.v(TAG, "Moving wallpaper " + wallpaper - + " from " + oldIndex + " to " + foundI); - } - - localmWindows.add(foundI, wallpaper); - mWindowsChanged = true; - changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; - } - } - - return changed; - } - - void setWallpaperAnimLayerAdjustmentLocked(int adj) { - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, - "Setting wallpaper layer adj to " + adj); - mWallpaperAnimLayerAdjustment = adj; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - wallpaper.mAnimLayer = wallpaper.mLayer + adj; - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win " - + wallpaper + " anim layer: " + wallpaper.mAnimLayer); - } - } - } - - boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh, - boolean sync) { - boolean changed = false; - boolean rawChanged = false; - float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f; - float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f; - int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw; - int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0; - changed = wallpaperWin.mXOffset != offset; - if (changed) { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " - + wallpaperWin + " x: " + offset); - wallpaperWin.mXOffset = offset; - } - if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) { - wallpaperWin.mWallpaperX = wpx; - wallpaperWin.mWallpaperXStep = wpxs; - rawChanged = true; - } - - float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f; - float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f; - int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh; - offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0; - if (wallpaperWin.mYOffset != offset) { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper " - + wallpaperWin + " y: " + offset); - changed = true; - wallpaperWin.mYOffset = offset; - } - if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) { - wallpaperWin.mWallpaperY = wpy; - wallpaperWin.mWallpaperYStep = wpys; - rawChanged = true; - } - - if (rawChanged) { - try { - if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset " - + wallpaperWin + " x=" + wallpaperWin.mWallpaperX - + " y=" + wallpaperWin.mWallpaperY); - if (sync) { - mWaitingOnWallpaper = wallpaperWin; - } - wallpaperWin.mClient.dispatchWallpaperOffsets( - wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, - wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync); - if (sync) { - if (mWaitingOnWallpaper != null) { - long start = SystemClock.uptimeMillis(); - if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) - < start) { - try { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Waiting for offset complete..."); - mWindowMap.wait(WALLPAPER_TIMEOUT); - } catch (InterruptedException e) { - } - if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!"); - if ((start+WALLPAPER_TIMEOUT) - < SystemClock.uptimeMillis()) { - Slog.i(TAG, "Timeout waiting for wallpaper to offset: " - + wallpaperWin); - mLastWallpaperTimeoutTime = start; - } - } - mWaitingOnWallpaper = null; - } - } - } catch (RemoteException e) { - } - } - - return changed; - } - - void wallpaperOffsetsComplete(IBinder window) { - synchronized (mWindowMap) { - if (mWaitingOnWallpaper != null && - mWaitingOnWallpaper.mClient.asBinder() == window) { - mWaitingOnWallpaper = null; - mWindowMap.notifyAll(); - } - } - } - - boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) { - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - - boolean changed = false; - - WindowState target = mWallpaperTarget; - if (target != null) { - if (target.mWallpaperX >= 0) { - mLastWallpaperX = target.mWallpaperX; - } else if (changingTarget.mWallpaperX >= 0) { - mLastWallpaperX = changingTarget.mWallpaperX; - } - if (target.mWallpaperY >= 0) { - mLastWallpaperY = target.mWallpaperY; - } else if (changingTarget.mWallpaperY >= 0) { - mLastWallpaperY = changingTarget.mWallpaperY; - } - } - - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { - wallpaper.computeShownFrameLocked(); - changed = true; - // We only want to be synchronous with one wallpaper. - sync = false; - } - } - } - - return changed; - } - - void updateWallpaperVisibilityLocked() { - final boolean visible = isWallpaperVisible(mWallpaperTarget); - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - if (token.hidden == visible) { - token.hidden = !visible; - // Need to do a layout to ensure the wallpaper now has the - // correct size. - mLayoutNeeded = true; - } - - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - if (visible) { - updateWallpaperOffsetLocked(wallpaper, dw, dh, false); - } - - if (wallpaper.mWallpaperVisible != visible) { - wallpaper.mWallpaperVisible = visible; - try { - if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG, - "Updating visibility of wallpaper " + wallpaper - + ": " + visible); - wallpaper.mClient.dispatchAppVisibility(visible); - } catch (RemoteException e) { - } - } - } - } - } - - public int addWindow(Session session, IWindow client, - WindowManager.LayoutParams attrs, int viewVisibility, - Rect outContentInsets, InputChannel outInputChannel) { - int res = mPolicy.checkAddPermission(attrs); - if (res != WindowManagerImpl.ADD_OKAY) { - return res; - } - - boolean reportNewConfig = false; - WindowState attachedWindow = null; - WindowState win = null; - long origId; - - synchronized(mWindowMap) { - if (mDisplay == null) { - throw new IllegalStateException("Display has not been initialialized"); - } - - if (mWindowMap.containsKey(client.asBinder())) { - Slog.w(TAG, "Window " + client + " is already added"); - return WindowManagerImpl.ADD_DUPLICATE_ADD; - } - - if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) { - attachedWindow = windowForClientLocked(null, attrs.token, false); - if (attachedWindow == null) { - Slog.w(TAG, "Attempted to add window with token that is not a window: " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN; - } - if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW - && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { - Slog.w(TAG, "Attempted to add window with token that is a sub-window: " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN; - } - } - - boolean addToken = false; - WindowToken token = mTokenMap.get(attrs.token); - if (token == null) { - if (attrs.type >= FIRST_APPLICATION_WINDOW - && attrs.type <= LAST_APPLICATION_WINDOW) { - Slog.w(TAG, "Attempted to add application window with unknown token " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; - } - if (attrs.type == TYPE_INPUT_METHOD) { - Slog.w(TAG, "Attempted to add input method window with unknown token " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; - } - if (attrs.type == TYPE_WALLPAPER) { - Slog.w(TAG, "Attempted to add wallpaper window with unknown token " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; - } - token = new WindowToken(attrs.token, -1, false); - addToken = true; - } else if (attrs.type >= FIRST_APPLICATION_WINDOW - && attrs.type <= LAST_APPLICATION_WINDOW) { - AppWindowToken atoken = token.appWindowToken; - if (atoken == null) { - Slog.w(TAG, "Attempted to add window with non-application token " - + token + ". Aborting."); - return WindowManagerImpl.ADD_NOT_APP_TOKEN; - } else if (atoken.removed) { - Slog.w(TAG, "Attempted to add window with exiting application token " - + token + ". Aborting."); - return WindowManagerImpl.ADD_APP_EXITING; - } - if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { - // No need for this guy! - if (localLOGV) Slog.v( - TAG, "**** NO NEED TO START: " + attrs.getTitle()); - return WindowManagerImpl.ADD_STARTING_NOT_NEEDED; - } - } else if (attrs.type == TYPE_INPUT_METHOD) { - if (token.windowType != TYPE_INPUT_METHOD) { - Slog.w(TAG, "Attempted to add input method window with bad token " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; - } - } else if (attrs.type == TYPE_WALLPAPER) { - if (token.windowType != TYPE_WALLPAPER) { - Slog.w(TAG, "Attempted to add wallpaper window with bad token " - + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; - } - } - - win = new WindowState(session, client, token, - attachedWindow, attrs, viewVisibility); - if (win.mDeathRecipient == null) { - // Client has apparently died, so there is no reason to - // continue. - Slog.w(TAG, "Adding window client " + client.asBinder() - + " that is dead, aborting."); - return WindowManagerImpl.ADD_APP_EXITING; - } - - mPolicy.adjustWindowParamsLw(win.mAttrs); - - res = mPolicy.prepareAddWindowLw(win, attrs); - if (res != WindowManagerImpl.ADD_OKAY) { - return res; - } - - if (outInputChannel != null) { - String name = win.makeInputChannelName(); - InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); - win.mInputChannel = inputChannels[0]; - inputChannels[1].transferToBinderOutParameter(outInputChannel); - - mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); - } - - // From now on, no exceptions or errors allowed! - - res = WindowManagerImpl.ADD_OKAY; - - origId = Binder.clearCallingIdentity(); - - if (addToken) { - mTokenMap.put(attrs.token, token); - } - win.attach(); - mWindowMap.put(client.asBinder(), win); - - if (attrs.type == TYPE_APPLICATION_STARTING && - token.appWindowToken != null) { - token.appWindowToken.startingWindow = win; - } - - boolean imMayMove = true; - - if (attrs.type == TYPE_INPUT_METHOD) { - mInputMethodWindow = win; - addInputMethodWindowToListLocked(win); - imMayMove = false; - } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) { - mInputMethodDialogs.add(win); - addWindowToListInOrderLocked(win, true); - adjustInputMethodDialogsLocked(); - imMayMove = false; - } else { - addWindowToListInOrderLocked(win, true); - if (attrs.type == TYPE_WALLPAPER) { - mLastWallpaperTimeoutTime = 0; - adjustWallpaperWindowsLocked(); - } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) { - adjustWallpaperWindowsLocked(); - } - } - - win.mEnterAnimationPending = true; - - mPolicy.getContentInsetHintLw(attrs, outContentInsets); - - if (mInTouchMode) { - res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE; - } - if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) { - res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE; - } - - mInputMonitor.setUpdateInputWindowsNeededLw(); - - boolean focusChanged = false; - if (win.canReceiveKeys()) { - focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS, - false /*updateInputWindows*/); - if (focusChanged) { - imMayMove = false; - } - } - - if (imMayMove) { - moveInputMethodWindowsIfNeededLocked(false); - } - - assignLayersLocked(); - // Don't do layout here, the window must call - // relayout to be displayed, so we'll do it there. - - //dump(); - - if (focusChanged) { - finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/); - } - mInputMonitor.updateInputWindowsLw(false /*force*/); - - if (localLOGV) Slog.v( - TAG, "New client " + client.asBinder() - + ": window=" + win); - - if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) { - reportNewConfig = true; - } - } - - if (reportNewConfig) { - sendNewConfiguration(); - } - - Binder.restoreCallingIdentity(origId); - - return res; - } - - public void removeWindow(Session session, IWindow client) { - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null) { - return; - } - removeWindowLocked(session, win); - } - } - - public void removeWindowLocked(Session session, WindowState win) { - - if (localLOGV || DEBUG_FOCUS) Slog.v( - TAG, "Remove " + win + " client=" - + Integer.toHexString(System.identityHashCode( - win.mClient.asBinder())) - + ", surface=" + win.mSurface); - - final long origId = Binder.clearCallingIdentity(); - - win.disposeInputChannel(); - - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Remove " + win + ": mSurface=" + win.mSurface - + " mExiting=" + win.mExiting - + " isAnimating=" + win.isAnimating() - + " app-animation=" - + (win.mAppToken != null ? win.mAppToken.animation : null) - + " inPendingTransaction=" - + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false) - + " mDisplayFrozen=" + mDisplayFrozen); - // Visibility of the removed window. Will be used later to update orientation later on. - boolean wasVisible = false; - // First, see if we need to run an animation. If we do, we have - // to hold off on removing the window until the animation is done. - // If the display is frozen, just remove immediately, since the - // animation wouldn't be seen. - if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) { - // If we are not currently running the exit animation, we - // need to see about starting one. - if (wasVisible=win.isWinVisibleLw()) { - - int transit = WindowManagerPolicy.TRANSIT_EXIT; - if (win.getAttrs().type == TYPE_APPLICATION_STARTING) { - transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; - } - // Try starting an animation. - if (applyAnimationLocked(win, transit, false)) { - win.mExiting = true; - } - } - if (win.mExiting || win.isAnimating()) { - // The exit animation is running... wait for it! - //Slog.i(TAG, "*** Running exit animation..."); - win.mExiting = true; - win.mRemoveOnExit = true; - mLayoutNeeded = true; - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/); - performLayoutAndPlaceSurfacesLocked(); - mInputMonitor.updateInputWindowsLw(false /*force*/); - if (win.mAppToken != null) { - win.mAppToken.updateReportedVisibilityLocked(); - } - //dump(); - Binder.restoreCallingIdentity(origId); - return; - } - } - - removeWindowInnerLocked(session, win); - // Removing a visible window will effect the computed orientation - // So just update orientation if needed. - if (wasVisible && computeForcedAppOrientationLocked() - != mForcedAppOrientation - && updateOrientationFromAppTokensLocked(false)) { - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); - Binder.restoreCallingIdentity(origId); - } - - private void removeWindowInnerLocked(Session session, WindowState win) { - if (win.mRemoved) { - // Nothing to do. - return; - } - - for (int i=win.mChildWindows.size()-1; i>=0; i--) { - WindowState cwin = win.mChildWindows.get(i); - Slog.w(TAG, "Force-removing child win " + cwin + " from container " - + win); - removeWindowInnerLocked(cwin.mSession, cwin); - } - - win.mRemoved = true; - - if (mInputMethodTarget == win) { - moveInputMethodWindowsIfNeededLocked(false); - } - - if (false) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.w(TAG, "Removing window " + win, e); - } - - mPolicy.removeWindowLw(win); - win.removeLocked(); - - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win); - mWindowMap.remove(win.mClient.asBinder()); - mWindows.remove(win); - mPendingRemove.remove(win); - mWindowsChanged = true; - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win); - - if (mInputMethodWindow == win) { - mInputMethodWindow = null; - } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { - mInputMethodDialogs.remove(win); - } - - final WindowToken token = win.mToken; - final AppWindowToken atoken = win.mAppToken; - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token); - token.windows.remove(win); - if (atoken != null) { - atoken.allAppWindows.remove(win); - } - if (localLOGV) Slog.v( - TAG, "**** Removing window " + win + ": count=" - + token.windows.size()); - if (token.windows.size() == 0) { - if (!token.explicit) { - mTokenMap.remove(token.token); - } else if (atoken != null) { - atoken.firstWindowDrawn = false; - } - } - - if (atoken != null) { - if (atoken.startingWindow == win) { - atoken.startingWindow = null; - } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) { - // If this is the last window and we had requested a starting - // transition window, well there is no point now. - atoken.startingData = null; - } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) { - // If this is the last window except for a starting transition - // window, we need to get rid of the starting transition. - if (DEBUG_STARTING_WINDOW) { - Slog.v(TAG, "Schedule remove starting " + token - + ": no more real windows"); - } - Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken); - mH.sendMessage(m); - } - } - - if (win.mAttrs.type == TYPE_WALLPAPER) { - mLastWallpaperTimeoutTime = 0; - adjustWallpaperWindowsLocked(); - } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { - adjustWallpaperWindowsLocked(); - } - - if (!mInLayout) { - assignLayersLocked(); - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - if (win.mAppToken != null) { - win.mAppToken.updateReportedVisibilityLocked(); - } - } - - mInputMonitor.updateInputWindowsLw(true /*force*/); - } - - private static void logSurface(WindowState w, String msg, RuntimeException where) { - String str = " SURFACE " + Integer.toHexString(w.hashCode()) - + ": " + msg + " / " + w.mAttrs.getTitle(); - if (where != null) { - Slog.i(TAG, str, where); - } else { - Slog.i(TAG, str); - } - } - - private void setTransparentRegionWindow(Session session, IWindow client, Region region) { - long origId = Binder.clearCallingIdentity(); - try { - synchronized (mWindowMap) { - WindowState w = windowForClientLocked(session, client, false); - if ((w != null) && (w.mSurface != null)) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setTransparentRegion"); - Surface.openTransaction(); - try { - if (SHOW_TRANSACTIONS) logSurface(w, - "transparentRegionHint=" + region, null); - w.mSurface.setTransparentRegionHint(region); - } finally { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, - "<<< CLOSE TRANSACTION setTransparentRegion"); - } - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - void setInsetsWindow(Session session, IWindow client, - int touchableInsets, Rect contentInsets, - Rect visibleInsets, Region touchableRegion) { - long origId = Binder.clearCallingIdentity(); - try { - synchronized (mWindowMap) { - WindowState w = windowForClientLocked(session, client, false); - if (w != null) { - w.mGivenInsetsPending = false; - w.mGivenContentInsets.set(contentInsets); - w.mGivenVisibleInsets.set(visibleInsets); - w.mGivenTouchableRegion.set(touchableRegion); - w.mTouchableInsets = touchableInsets; - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - public void getWindowDisplayFrame(Session session, IWindow client, - Rect outDisplayFrame) { - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null) { - outDisplayFrame.setEmpty(); - return; - } - outDisplayFrame.set(win.mDisplayFrame); - } - } - - public void setWindowWallpaperPositionLocked(WindowState window, float x, float y, - float xStep, float yStep) { - if (window.mWallpaperX != x || window.mWallpaperY != y) { - window.mWallpaperX = x; - window.mWallpaperY = y; - window.mWallpaperXStep = xStep; - window.mWallpaperYStep = yStep; - if (updateWallpaperOffsetLocked(window, true)) { - performLayoutAndPlaceSurfacesLocked(); - } - } - } - - void wallpaperCommandComplete(IBinder window, Bundle result) { - synchronized (mWindowMap) { - if (mWaitingOnWallpaper != null && - mWaitingOnWallpaper.mClient.asBinder() == window) { - mWaitingOnWallpaper = null; - mWindowMap.notifyAll(); - } - } - } - - public Bundle sendWindowWallpaperCommandLocked(WindowState window, - String action, int x, int y, int z, Bundle extras, boolean sync) { - if (window == mWallpaperTarget || window == mLowerWallpaperTarget - || window == mUpperWallpaperTarget) { - boolean doWait = sync; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - try { - wallpaper.mClient.dispatchWallpaperCommand(action, - x, y, z, extras, sync); - // We only want to be synchronous with one wallpaper. - sync = false; - } catch (RemoteException e) { - } - } - } - - if (doWait) { - // XXX Need to wait for result. - } - } - - return null; - } - - public int relayoutWindow(Session session, IWindow client, - WindowManager.LayoutParams attrs, int requestedWidth, - int requestedHeight, int viewVisibility, boolean insetsPending, - Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, - Configuration outConfig, Surface outSurface) { - boolean displayed = false; - boolean inTouchMode; - boolean configChanged; - - // if they don't have this permission, mask out the status bar bits - if (attrs != null) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) - != PackageManager.PERMISSION_GRANTED) { - attrs.systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; - attrs.subtreeSystemUiVisibility &= ~StatusBarManager.DISABLE_MASK; - } - } - long origId = Binder.clearCallingIdentity(); - - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null) { - return 0; - } - win.mRequestedWidth = requestedWidth; - win.mRequestedHeight = requestedHeight; - - if (attrs != null) { - mPolicy.adjustWindowParamsLw(attrs); - } - - int attrChanges = 0; - int flagChanges = 0; - if (attrs != null) { - flagChanges = win.mAttrs.flags ^= attrs.flags; - attrChanges = win.mAttrs.copyFrom(attrs); - } - - if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs); - - if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) { - win.mAlpha = attrs.alpha; - } - - final boolean scaledWindow = - ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0); - - if (scaledWindow) { - // requested{Width|Height} Surface's physical size - // attrs.{width|height} Size on screen - win.mHScale = (attrs.width != requestedWidth) ? - (attrs.width / (float)requestedWidth) : 1.0f; - win.mVScale = (attrs.height != requestedHeight) ? - (attrs.height / (float)requestedHeight) : 1.0f; - } else { - win.mHScale = win.mVScale = 1; - } - - boolean imMayMove = (flagChanges&( - WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0; - - boolean focusMayChange = win.mViewVisibility != viewVisibility - || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0) - || (!win.mRelayoutCalled); - - boolean wallpaperMayMove = win.mViewVisibility != viewVisibility - && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0; - - win.mRelayoutCalled = true; - final int oldVisibility = win.mViewVisibility; - win.mViewVisibility = viewVisibility; - if (viewVisibility == View.VISIBLE && - (win.mAppToken == null || !win.mAppToken.clientHidden)) { - displayed = !win.isVisibleLw(); - if (win.mExiting) { - win.mExiting = false; - if (win.mAnimation != null) { - win.mAnimation.cancel(); - win.mAnimation = null; - } - } - if (win.mDestroying) { - win.mDestroying = false; - mDestroySurface.remove(win); - } - if (oldVisibility == View.GONE) { - win.mEnterAnimationPending = true; - } - if (displayed) { - if (win.mSurface != null && !win.mDrawPending - && !win.mCommitDrawPending && !mDisplayFrozen - && mPolicy.isScreenOn()) { - applyEnterAnimationLocked(win); - } - if ((win.mAttrs.flags - & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "Relayout window turning screen on: " + win); - win.mTurnOnScreen = true; - } - int diff = 0; - if (win.mConfiguration != mCurConfiguration - && (win.mConfiguration == null - || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) { - win.mConfiguration = mCurConfiguration; - if (DEBUG_CONFIGURATION) { - Slog.i(TAG, "Window " + win + " visible with new config: " - + win.mConfiguration + " / 0x" - + Integer.toHexString(diff)); - } - outConfig.setTo(mCurConfiguration); - } - } - if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { - // To change the format, we need to re-build the surface. - win.destroySurfaceLocked(); - displayed = true; - } - try { - Surface surface = win.createSurfaceLocked(); - if (surface != null) { - outSurface.copyFrom(surface); - win.mReportDestroySurface = false; - win.mSurfacePendingDestroy = false; - if (SHOW_TRANSACTIONS) Slog.i(TAG, - " OUT SURFACE " + outSurface + ": copied"); - } else { - // For some reason there isn't a surface. Clear the - // caller's object so they see the same state. - outSurface.release(); - } - } catch (Exception e) { - mInputMonitor.updateInputWindowsLw(true /*force*/); - - Slog.w(TAG, "Exception thrown when creating surface for client " - + client + " (" + win.mAttrs.getTitle() + ")", - e); - Binder.restoreCallingIdentity(origId); - return 0; - } - if (displayed) { - focusMayChange = true; - } - if (win.mAttrs.type == TYPE_INPUT_METHOD - && mInputMethodWindow == null) { - mInputMethodWindow = win; - imMayMove = true; - } - if (win.mAttrs.type == TYPE_BASE_APPLICATION - && win.mAppToken != null - && win.mAppToken.startingWindow != null) { - // Special handling of starting window over the base - // window of the app: propagate lock screen flags to it, - // to provide the correct semantics while starting. - final int mask = - WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD - | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; - WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs; - sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask); - } - } else { - win.mEnterAnimationPending = false; - if (win.mSurface != null) { - if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win - + ": mExiting=" + win.mExiting - + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy); - // If we are not currently running the exit animation, we - // need to see about starting one. - if (!win.mExiting || win.mSurfacePendingDestroy) { - // Try starting an animation; if there isn't one, we - // can destroy the surface right away. - int transit = WindowManagerPolicy.TRANSIT_EXIT; - if (win.getAttrs().type == TYPE_APPLICATION_STARTING) { - transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; - } - if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() && - applyAnimationLocked(win, transit, false)) { - focusMayChange = true; - win.mExiting = true; - } else if (win.isAnimating()) { - // Currently in a hide animation... turn this into - // an exit. - win.mExiting = true; - } else if (win == mWallpaperTarget) { - // If the wallpaper is currently behind this - // window, we need to change both of them inside - // of a transaction to avoid artifacts. - win.mExiting = true; - win.mAnimating = true; - } else { - if (mInputMethodWindow == win) { - mInputMethodWindow = null; - } - win.destroySurfaceLocked(); - } - } - } - - if (win.mSurface == null || (win.getAttrs().flags - & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0 - || win.mSurfacePendingDestroy) { - // We are being called from a local process, which - // means outSurface holds its current surface. Ensure the - // surface object is cleared, but we don't want it actually - // destroyed at this point. - win.mSurfacePendingDestroy = false; - outSurface.release(); - if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); - } else if (win.mSurface != null) { - if (DEBUG_VISIBILITY) Slog.i(TAG, - "Keeping surface, will report destroy: " + win); - win.mReportDestroySurface = true; - outSurface.copyFrom(win.mSurface); - } - } - - if (focusMayChange) { - //System.out.println("Focus may change: " + win.mAttrs.getTitle()); - if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/)) { - imMayMove = false; - } - //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus); - } - - // updateFocusedWindowLocked() already assigned layers so we only need to - // reassign them at this point if the IM window state gets shuffled - boolean assignLayers = false; - - if (imMayMove) { - if (moveInputMethodWindowsIfNeededLocked(false) || displayed) { - // Little hack here -- we -should- be able to rely on the - // function to return true if the IME has moved and needs - // its layer recomputed. However, if the IME was hidden - // and isn't actually moved in the list, its layer may be - // out of data so we make sure to recompute it. - assignLayers = true; - } - } - if (wallpaperMayMove) { - if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { - assignLayers = true; - } - } - - mLayoutNeeded = true; - win.mGivenInsetsPending = insetsPending; - if (assignLayers) { - assignLayersLocked(); - } - configChanged = updateOrientationFromAppTokensLocked(false); - performLayoutAndPlaceSurfacesLocked(); - if (displayed && win.mIsWallpaper) { - updateWallpaperOffsetLocked(win, mDisplay.getWidth(), - mDisplay.getHeight(), false); - } - if (win.mAppToken != null) { - win.mAppToken.updateReportedVisibilityLocked(); - } - outFrame.set(win.mFrame); - outContentInsets.set(win.mContentInsets); - outVisibleInsets.set(win.mVisibleInsets); - if (localLOGV) Slog.v( - TAG, "Relayout given client " + client.asBinder() - + ", requestedWidth=" + requestedWidth - + ", requestedHeight=" + requestedHeight - + ", viewVisibility=" + viewVisibility - + "\nRelayout returning frame=" + outFrame - + ", surface=" + outSurface); - - if (localLOGV || DEBUG_FOCUS) Slog.v( - TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); - - inTouchMode = mInTouchMode; - - mInputMonitor.updateInputWindowsLw(true /*force*/); - } - - if (configChanged) { - sendNewConfiguration(); - } - - Binder.restoreCallingIdentity(origId); - - return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0) - | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0); - } - - public void finishDrawingWindow(Session session, IWindow client) { - final long origId = Binder.clearCallingIdentity(); - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win != null && win.finishDrawingLocked()) { - if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { - adjustWallpaperWindowsLocked(); - } - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - } - } - Binder.restoreCallingIdentity(origId); - } - - private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg=" - + (lp != null ? lp.packageName : null) - + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null)); - if (lp != null && lp.windowAnimations != 0) { - // If this is a system resource, don't try to load it from the - // application resources. It is nice to avoid loading application - // resources if we can. - String packageName = lp.packageName != null ? lp.packageName : "android"; - int resId = lp.windowAnimations; - if ((resId&0xFF000000) == 0x01000000) { - packageName = "android"; - } - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" - + packageName); - return AttributeCache.instance().get(packageName, resId, - com.android.internal.R.styleable.WindowAnimation); - } - return null; - } - - private AttributeCache.Entry getCachedAnimations(String packageName, int resId) { - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: package=" - + packageName + " resId=0x" + Integer.toHexString(resId)); - if (packageName != null) { - if ((resId&0xFF000000) == 0x01000000) { - packageName = "android"; - } - if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package=" - + packageName); - return AttributeCache.instance().get(packageName, resId, - com.android.internal.R.styleable.WindowAnimation); - } - return null; - } - - private void applyEnterAnimationLocked(WindowState win) { - int transit = WindowManagerPolicy.TRANSIT_SHOW; - if (win.mEnterAnimationPending) { - win.mEnterAnimationPending = false; - transit = WindowManagerPolicy.TRANSIT_ENTER; - } - - applyAnimationLocked(win, transit, true); - } - - private boolean applyAnimationLocked(WindowState win, - int transit, boolean isEntrance) { - if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) { - // If we are trying to apply an animation, but already running - // an animation of the same type, then just leave that one alone. - return true; - } - - // Only apply an animation if the display isn't frozen. If it is - // frozen, there is no reason to animate and it can cause strange - // artifacts when we unfreeze the display if some different animation - // is running. - if (!mDisplayFrozen && mPolicy.isScreenOn()) { - int anim = mPolicy.selectAnimationLw(win, transit); - int attr = -1; - Animation a = null; - if (anim != 0) { - a = AnimationUtils.loadAnimation(mContext, anim); - } else { - switch (transit) { - case WindowManagerPolicy.TRANSIT_ENTER: - attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; - break; - case WindowManagerPolicy.TRANSIT_EXIT: - attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_SHOW: - attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation; - break; - case WindowManagerPolicy.TRANSIT_HIDE: - attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation; - break; - } - if (attr >= 0) { - a = loadAnimation(win.mAttrs, attr); - } - } - if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win - + " anim=" + anim + " attr=0x" + Integer.toHexString(attr) - + " mAnimation=" + win.mAnimation - + " isEntrance=" + isEntrance); - if (a != null) { - if (DEBUG_ANIM) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.v(TAG, "Loaded animation " + a + " for " + win, e); - } - win.setAnimation(a); - win.mAnimationIsEntrance = isEntrance; - } - } else { - win.clearAnimation(); - } - - return win.mAnimation != null; - } - - private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) { - int anim = 0; - Context context = mContext; - if (animAttr >= 0) { - AttributeCache.Entry ent = getCachedAnimations(lp); - if (ent != null) { - context = ent.context; - anim = ent.array.getResourceId(animAttr, 0); - } - } - if (anim != 0) { - return AnimationUtils.loadAnimation(context, anim); - } - return null; - } - - private Animation loadAnimation(String packageName, int resId) { - int anim = 0; - Context context = mContext; - if (resId >= 0) { - AttributeCache.Entry ent = getCachedAnimations(packageName, resId); - if (ent != null) { - context = ent.context; - anim = resId; - } - } - if (anim != 0) { - return AnimationUtils.loadAnimation(context, anim); - } - return null; - } - - private boolean applyAnimationLocked(AppWindowToken wtoken, - WindowManager.LayoutParams lp, int transit, boolean enter) { - // Only apply an animation if the display isn't frozen. If it is - // frozen, there is no reason to animate and it can cause strange - // artifacts when we unfreeze the display if some different animation - // is running. - if (!mDisplayFrozen && mPolicy.isScreenOn()) { - Animation a; - if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) { - a = new FadeInOutAnimation(enter); - if (DEBUG_ANIM) Slog.v(TAG, - "applying FadeInOutAnimation for a window in compatibility mode"); - } else if (mNextAppTransitionPackage != null) { - a = loadAnimation(mNextAppTransitionPackage, enter ? - mNextAppTransitionEnter : mNextAppTransitionExit); - } else { - int animAttr = 0; - switch (transit) { - case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation; - break; - } - a = animAttr != 0 ? loadAnimation(lp, animAttr) : null; - if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken - + " anim=" + a - + " animAttr=0x" + Integer.toHexString(animAttr) - + " transit=" + transit); - } - if (a != null) { - if (DEBUG_ANIM) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e); - } - wtoken.setAnimation(a); - } - } else { - wtoken.clearAnimation(); - } - - return wtoken.animation != null; - } - - // ------------------------------------------------------------- - // Application Window Tokens - // ------------------------------------------------------------- - - public void validateAppTokens(List tokens) { - int v = tokens.size()-1; - int m = mAppTokens.size()-1; - while (v >= 0 && m >= 0) { - AppWindowToken wtoken = mAppTokens.get(m); - if (wtoken.removed) { - m--; - continue; - } - if (tokens.get(v) != wtoken.token) { - Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v) - + " @ " + v + ", internal is " + wtoken.token + " @ " + m); - } - v--; - m--; - } - while (v >= 0) { - Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v); - v--; - } - while (m >= 0) { - AppWindowToken wtoken = mAppTokens.get(m); - if (!wtoken.removed) { - Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m); - } - m--; - } - } - - boolean checkCallingPermission(String permission, String func) { - // Quick check: if the calling permission is me, it's all okay. - if (Binder.getCallingPid() == Process.myPid()) { - return true; - } - - if (mContext.checkCallingPermission(permission) - == PackageManager.PERMISSION_GRANTED) { - return true; - } - String msg = "Permission Denial: " + func + " from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " requires " + permission; - Slog.w(TAG, msg); - return false; - } - - AppWindowToken findAppWindowToken(IBinder token) { - WindowToken wtoken = mTokenMap.get(token); - if (wtoken == null) { - return null; - } - return wtoken.appWindowToken; - } - - public void addWindowToken(IBinder token, int type) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "addWindowToken()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - WindowToken wtoken = mTokenMap.get(token); - if (wtoken != null) { - Slog.w(TAG, "Attempted to add existing input method token: " + token); - return; - } - wtoken = new WindowToken(token, type, true); - mTokenMap.put(token, wtoken); - if (type == TYPE_WALLPAPER) { - mWallpaperTokens.add(wtoken); - } - } - } - - public void removeWindowToken(IBinder token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "removeWindowToken()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - final long origId = Binder.clearCallingIdentity(); - synchronized(mWindowMap) { - WindowToken wtoken = mTokenMap.remove(token); - if (wtoken != null) { - boolean delayed = false; - if (!wtoken.hidden) { - wtoken.hidden = true; - - final int N = wtoken.windows.size(); - boolean changed = false; - - for (int i=0; i<N; i++) { - WindowState win = wtoken.windows.get(i); - - if (win.isAnimating()) { - delayed = true; - } - - if (win.isVisibleNow()) { - applyAnimationLocked(win, - WindowManagerPolicy.TRANSIT_EXIT, false); - changed = true; - } - } - - if (changed) { - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, - false /*updateInputWindows*/); - } - - if (delayed) { - mExitingTokens.add(wtoken); - } else if (wtoken.windowType == TYPE_WALLPAPER) { - mWallpaperTokens.remove(wtoken); - } - } - - mInputMonitor.updateInputWindowsLw(true /*force*/); - } else { - Slog.w(TAG, "Attempted to remove non-existing token: " + token); - } - } - Binder.restoreCallingIdentity(origId); - } - - public void addAppToken(int addPos, IApplicationToken token, - int groupId, int requestedOrientation, boolean fullscreen) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "addAppToken()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - // Get the dispatching timeout here while we are not holding any locks so that it - // can be cached by the AppWindowToken. The timeout value is used later by the - // input dispatcher in code that does hold locks. If we did not cache the value - // here we would run the chance of introducing a deadlock between the window manager - // (which holds locks while updating the input dispatcher state) and the activity manager - // (which holds locks while querying the application token). - long inputDispatchingTimeoutNanos; - try { - inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L; - } catch (RemoteException ex) { - Slog.w(TAG, "Could not get dispatching timeout.", ex); - inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - } - - synchronized(mWindowMap) { - AppWindowToken wtoken = findAppWindowToken(token.asBinder()); - if (wtoken != null) { - Slog.w(TAG, "Attempted to add existing app token: " + token); - return; - } - wtoken = new AppWindowToken(token); - wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; - wtoken.groupId = groupId; - wtoken.appFullscreen = fullscreen; - wtoken.requestedOrientation = requestedOrientation; - if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken); - mAppTokens.add(addPos, wtoken); - mTokenMap.put(token.asBinder(), wtoken); - - // Application tokens start out hidden. - wtoken.hidden = true; - wtoken.hiddenRequested = true; - - //dump(); - } - } - - public void setAppGroupId(IBinder token, int groupId) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppStartingIcon()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - AppWindowToken wtoken = findAppWindowToken(token); - if (wtoken == null) { - Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); - return; - } - wtoken.groupId = groupId; - } - } - - public int getOrientationFromWindowsLocked() { - int pos = mWindows.size() - 1; - while (pos >= 0) { - WindowState wtoken = mWindows.get(pos); - pos--; - if (wtoken.mAppToken != null) { - // We hit an application window. so the orientation will be determined by the - // app window. No point in continuing further. - return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) { - continue; - } - int req = wtoken.mAttrs.screenOrientation; - if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) || - (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){ - continue; - } else { - return req; - } - } - return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - - public int getOrientationFromAppTokensLocked() { - int pos = mAppTokens.size() - 1; - int curGroup = 0; - int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - boolean findingBehind = false; - boolean haveGroup = false; - boolean lastFullscreen = false; - while (pos >= 0) { - AppWindowToken wtoken = mAppTokens.get(pos); - pos--; - // if we're about to tear down this window and not seek for - // the behind activity, don't use it for orientation - if (!findingBehind - && (!wtoken.hidden && wtoken.hiddenRequested)) { - continue; - } - - if (!haveGroup) { - // We ignore any hidden applications on the top. - if (wtoken.hiddenRequested || wtoken.willBeHidden) { - continue; - } - haveGroup = true; - curGroup = wtoken.groupId; - lastOrientation = wtoken.requestedOrientation; - } else if (curGroup != wtoken.groupId) { - // If we have hit a new application group, and the bottom - // of the previous group didn't explicitly say to use - // the orientation behind it, and the last app was - // full screen, then we'll stick with the - // user's orientation. - if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND - && lastFullscreen) { - return lastOrientation; - } - } - int or = wtoken.requestedOrientation; - // If this application is fullscreen, and didn't explicitly say - // to use the orientation behind it, then just take whatever - // orientation it has and ignores whatever is under it. - lastFullscreen = wtoken.appFullscreen; - if (lastFullscreen - && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { - return or; - } - // If this application has requested an explicit orientation, - // then use it. - if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { - return or; - } - findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); - } - return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - - public Configuration updateOrientationFromAppTokens( - Configuration currentConfig, IBinder freezeThisOneIfNeeded) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "updateOrientationFromAppTokens()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - Configuration config = null; - long ident = Binder.clearCallingIdentity(); - - synchronized(mWindowMap) { - if (updateOrientationFromAppTokensLocked(false)) { - if (freezeThisOneIfNeeded != null) { - AppWindowToken wtoken = findAppWindowToken( - freezeThisOneIfNeeded); - if (wtoken != null) { - startAppFreezingScreenLocked(wtoken, - ActivityInfo.CONFIG_ORIENTATION); - } - } - config = computeNewConfigurationLocked(); - - } else if (currentConfig != null) { - // No obvious action we need to take, but if our current - // state mismatches the activity manager's, update it, - // disregarding font scale, which should remain set to - // the value of the previous configuration. - mTempConfiguration.setToDefaults(); - mTempConfiguration.fontScale = currentConfig.fontScale; - if (computeNewConfigurationLocked(mTempConfiguration)) { - if (currentConfig.diff(mTempConfiguration) != 0) { - mWaitingForConfig = true; - mLayoutNeeded = true; - startFreezingDisplayLocked(false); - config = new Configuration(mTempConfiguration); - } - } - } - } - - Binder.restoreCallingIdentity(ident); - return config; - } - - /* - * Determine the new desired orientation of the display, returning - * a non-null new Configuration if it has changed from the current - * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL - * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE - * SCREEN. This will typically be done for you if you call - * sendNewConfiguration(). - * - * The orientation is computed from non-application windows first. If none of - * the non-application windows specify orientation, the orientation is computed from - * application tokens. - * @see android.view.IWindowManager#updateOrientationFromAppTokens( - * android.os.IBinder) - */ - boolean updateOrientationFromAppTokensLocked(boolean inTransaction) { - if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) { - // If the display is frozen, some activities may be in the middle - // of restarting, and thus have removed their old window. If the - // window has the flag to hide the lock screen, then the lock screen - // can re-appear and inflict its own orientation on us. Keep the - // orientation stable until this all settles down. - return false; - } - - boolean changed = false; - long ident = Binder.clearCallingIdentity(); - try { - int req = computeForcedAppOrientationLocked(); - - if (req != mForcedAppOrientation) { - mForcedAppOrientation = req; - //send a message to Policy indicating orientation change to take - //action like disabling/enabling sensors etc., - mPolicy.setCurrentOrientationLw(req); - if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE, - inTransaction)) { - changed = true; - } - } - - return changed; - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - int computeForcedAppOrientationLocked() { - int req = getOrientationFromWindowsLocked(); - if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { - req = getOrientationFromAppTokensLocked(); - } - return req; - } - - public void setNewConfiguration(Configuration config) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setNewConfiguration()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - mCurConfiguration = new Configuration(config); - mWaitingForConfig = false; - performLayoutAndPlaceSurfacesLocked(); - } - } - - public void setAppOrientation(IApplicationToken token, int requestedOrientation) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppOrientation()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - AppWindowToken wtoken = findAppWindowToken(token.asBinder()); - if (wtoken == null) { - Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token); - return; - } - - wtoken.requestedOrientation = requestedOrientation; - } - } - - public int getAppOrientation(IApplicationToken token) { - synchronized(mWindowMap) { - AppWindowToken wtoken = findAppWindowToken(token.asBinder()); - if (wtoken == null) { - return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - } - - return wtoken.requestedOrientation; - } - } - - public void setFocusedApp(IBinder token, boolean moveFocusNow) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setFocusedApp()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - boolean changed = false; - if (token == null) { - if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); - changed = mFocusedApp != null; - mFocusedApp = null; - if (changed) { - mInputMonitor.setFocusedAppLw(null); - } - } else { - AppWindowToken newFocus = findAppWindowToken(token); - if (newFocus == null) { - Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); - return; - } - changed = mFocusedApp != newFocus; - mFocusedApp = newFocus; - if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp); - if (changed) { - mInputMonitor.setFocusedAppLw(newFocus); - } - } - - if (moveFocusNow && changed) { - final long origId = Binder.clearCallingIdentity(); - updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); - Binder.restoreCallingIdentity(origId); - } - } - } - - public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "prepareAppTransition()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Prepare app transition: transit=" + transit - + " mNextAppTransition=" + mNextAppTransition); - if (!mDisplayFrozen && mPolicy.isScreenOn()) { - if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET - || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { - mNextAppTransition = transit; - } else if (!alwaysKeepCurrent) { - if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN - && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) { - // Opening a new task always supersedes a close for the anim. - mNextAppTransition = transit; - } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN - && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) { - // Opening a new activity always supersedes a close for the anim. - mNextAppTransition = transit; - } - } - mAppTransitionReady = false; - mAppTransitionTimeout = false; - mStartingIconInTransition = false; - mSkipAppTransitionAnimation = false; - mH.removeMessages(H.APP_TRANSITION_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT), - 5000); - } - } - } - - public int getPendingAppTransition() { - return mNextAppTransition; - } - - public void overridePendingAppTransition(String packageName, - int enterAnim, int exitAnim) { - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mNextAppTransitionPackage = packageName; - mNextAppTransitionEnter = enterAnim; - mNextAppTransitionExit = exitAnim; - } - } - - public void executeAppTransition() { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "executeAppTransition()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.w(TAG, "Execute app transition: mNextAppTransition=" - + mNextAppTransition, e); - } - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mAppTransitionReady = true; - final long origId = Binder.clearCallingIdentity(); - performLayoutAndPlaceSurfacesLocked(); - Binder.restoreCallingIdentity(origId); - } - } - } - - public void setAppStartingWindow(IBinder token, String pkg, - int theme, CharSequence nonLocalizedLabel, int labelRes, int icon, - int windowFlags, IBinder transferFrom, boolean createIfNeeded) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppStartingIcon()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - if (DEBUG_STARTING_WINDOW) Slog.v( - TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg - + " transferFrom=" + transferFrom); - - AppWindowToken wtoken = findAppWindowToken(token); - if (wtoken == null) { - Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token); - return; - } - - // If the display is frozen, we won't do anything until the - // actual window is displayed so there is no reason to put in - // the starting window. - if (mDisplayFrozen || !mPolicy.isScreenOn()) { - return; - } - - if (wtoken.startingData != null) { - return; - } - - if (transferFrom != null) { - AppWindowToken ttoken = findAppWindowToken(transferFrom); - if (ttoken != null) { - WindowState startingWindow = ttoken.startingWindow; - if (startingWindow != null) { - if (mStartingIconInTransition) { - // In this case, the starting icon has already - // been displayed, so start letting windows get - // shown immediately without any more transitions. - mSkipAppTransitionAnimation = true; - } - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, - "Moving existing starting from " + ttoken - + " to " + wtoken); - final long origId = Binder.clearCallingIdentity(); - - // Transfer the starting window over to the new - // token. - wtoken.startingData = ttoken.startingData; - wtoken.startingView = ttoken.startingView; - wtoken.startingWindow = startingWindow; - ttoken.startingData = null; - ttoken.startingView = null; - ttoken.startingWindow = null; - ttoken.startingMoved = true; - startingWindow.mToken = wtoken; - startingWindow.mRootToken = wtoken; - startingWindow.mAppToken = wtoken; - if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, - "Removing starting window: " + startingWindow); - mWindows.remove(startingWindow); - mWindowsChanged = true; - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing starting " + startingWindow - + " from " + ttoken); - ttoken.windows.remove(startingWindow); - ttoken.allAppWindows.remove(startingWindow); - addWindowToListInOrderLocked(startingWindow, true); - - // Propagate other interesting state between the - // tokens. If the old token is displayed, we should - // immediately force the new one to be displayed. If - // it is animating, we need to move that animation to - // the new one. - if (ttoken.allDrawn) { - wtoken.allDrawn = true; - } - if (ttoken.firstWindowDrawn) { - wtoken.firstWindowDrawn = true; - } - if (!ttoken.hidden) { - wtoken.hidden = false; - wtoken.hiddenRequested = false; - wtoken.willBeHidden = false; - } - if (wtoken.clientHidden != ttoken.clientHidden) { - wtoken.clientHidden = ttoken.clientHidden; - wtoken.sendAppVisibilityToClients(); - } - if (ttoken.animation != null) { - wtoken.animation = ttoken.animation; - wtoken.animating = ttoken.animating; - wtoken.animLayerAdjustment = ttoken.animLayerAdjustment; - ttoken.animation = null; - ttoken.animLayerAdjustment = 0; - wtoken.updateLayers(); - ttoken.updateLayers(); - } - - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - true /*updateInputWindows*/); - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - Binder.restoreCallingIdentity(origId); - return; - } else if (ttoken.startingData != null) { - // The previous app was getting ready to show a - // starting window, but hasn't yet done so. Steal it! - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, - "Moving pending starting from " + ttoken - + " to " + wtoken); - wtoken.startingData = ttoken.startingData; - ttoken.startingData = null; - ttoken.startingMoved = true; - Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); - // Note: we really want to do sendMessageAtFrontOfQueue() because we - // want to process the message ASAP, before any other queued - // messages. - mH.sendMessageAtFrontOfQueue(m); - return; - } - } - } - - // There is no existing starting window, and the caller doesn't - // want us to create one, so that's it! - if (!createIfNeeded) { - return; - } - - // If this is a translucent or wallpaper window, then don't - // show a starting window -- the current effect (a full-screen - // opaque starting window that fades away to the real contents - // when it is ready) does not work for this. - if (theme != 0) { - AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, - com.android.internal.R.styleable.Window); - if (ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { - return; - } - if (ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsFloating, false)) { - return; - } - if (ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { - return; - } - } - - mStartingIconInTransition = true; - wtoken.startingData = new StartingData( - pkg, theme, nonLocalizedLabel, - labelRes, icon, windowFlags); - Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); - // Note: we really want to do sendMessageAtFrontOfQueue() because we - // want to process the message ASAP, before any other queued - // messages. - mH.sendMessageAtFrontOfQueue(m); - } - } - - public void setAppWillBeHidden(IBinder token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppWillBeHidden()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - AppWindowToken wtoken; - - synchronized(mWindowMap) { - wtoken = findAppWindowToken(token); - if (wtoken == null) { - Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token); - return; - } - wtoken.willBeHidden = true; - } - } - - boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp, - boolean visible, int transit, boolean performLayout) { - boolean delayed = false; - - if (wtoken.clientHidden == visible) { - wtoken.clientHidden = !visible; - wtoken.sendAppVisibilityToClients(); - } - - wtoken.willBeHidden = false; - if (wtoken.hidden == visible) { - final int N = wtoken.allAppWindows.size(); - boolean changed = false; - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden - + " performLayout=" + performLayout); - - boolean runningAppAnimation = false; - - if (transit != WindowManagerPolicy.TRANSIT_UNSET) { - if (wtoken.animation == sDummyAnimation) { - wtoken.animation = null; - } - applyAnimationLocked(wtoken, lp, transit, visible); - changed = true; - if (wtoken.animation != null) { - delayed = runningAppAnimation = true; - } - } - - for (int i=0; i<N; i++) { - WindowState win = wtoken.allAppWindows.get(i); - if (win == wtoken.startingWindow) { - continue; - } - - if (win.isAnimating()) { - delayed = true; - } - - //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); - //win.dump(" "); - if (visible) { - if (!win.isVisibleNow()) { - if (!runningAppAnimation) { - applyAnimationLocked(win, - WindowManagerPolicy.TRANSIT_ENTER, true); - } - changed = true; - } - } else if (win.isVisibleNow()) { - if (!runningAppAnimation) { - applyAnimationLocked(win, - WindowManagerPolicy.TRANSIT_EXIT, false); - } - changed = true; - } - } - - wtoken.hidden = wtoken.hiddenRequested = !visible; - if (!visible) { - unsetAppFreezingScreenLocked(wtoken, true, true); - } else { - // If we are being set visible, and the starting window is - // not yet displayed, then make sure it doesn't get displayed. - WindowState swin = wtoken.startingWindow; - if (swin != null && (swin.mDrawPending - || swin.mCommitDrawPending)) { - swin.mPolicyVisibility = false; - swin.mPolicyVisibilityAfterAnim = false; - } - } - - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken - + ": hidden=" + wtoken.hidden + " hiddenRequested=" - + wtoken.hiddenRequested); - - if (changed) { - mLayoutNeeded = true; - mInputMonitor.setUpdateInputWindowsNeededLw(); - if (performLayout) { - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/); - performLayoutAndPlaceSurfacesLocked(); - } - mInputMonitor.updateInputWindowsLw(false /*force*/); - } - } - - if (wtoken.animation != null) { - delayed = true; - } - - return delayed; - } - - public void setAppVisibility(IBinder token, boolean visible) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppVisibility()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - AppWindowToken wtoken; - - synchronized(mWindowMap) { - wtoken = findAppWindowToken(token); - if (wtoken == null) { - Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token); - return; - } - - if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.v(TAG, "setAppVisibility(" + token + ", " + visible - + "): mNextAppTransition=" + mNextAppTransition - + " hidden=" + wtoken.hidden - + " hiddenRequested=" + wtoken.hiddenRequested, e); - } - - // If we are preparing an app transition, then delay changing - // the visibility of this token until we execute that transition. - if (!mDisplayFrozen && mPolicy.isScreenOn() - && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - // Already in requested state, don't do anything more. - if (wtoken.hiddenRequested != visible) { - return; - } - wtoken.hiddenRequested = !visible; - - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Setting dummy animation on: " + wtoken); - wtoken.setDummyAnimation(); - mOpeningApps.remove(wtoken); - mClosingApps.remove(wtoken); - wtoken.waitingToShow = wtoken.waitingToHide = false; - wtoken.inPendingTransaction = true; - if (visible) { - mOpeningApps.add(wtoken); - wtoken.startingDisplayed = false; - wtoken.startingMoved = false; - - // If the token is currently hidden (should be the - // common case), then we need to set up to wait for - // its windows to be ready. - if (wtoken.hidden) { - wtoken.allDrawn = false; - wtoken.waitingToShow = true; - - if (wtoken.clientHidden) { - // In the case where we are making an app visible - // but holding off for a transition, we still need - // to tell the client to make its windows visible so - // they get drawn. Otherwise, we will wait on - // performing the transition until all windows have - // been drawn, they never will be, and we are sad. - wtoken.clientHidden = false; - wtoken.sendAppVisibilityToClients(); - } - } - } else { - mClosingApps.add(wtoken); - - // If the token is currently visible (should be the - // common case), then set up to wait for it to be hidden. - if (!wtoken.hidden) { - wtoken.waitingToHide = true; - } - } - return; - } - - final long origId = Binder.clearCallingIdentity(); - setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true); - wtoken.updateReportedVisibilityLocked(); - Binder.restoreCallingIdentity(origId); - } - } - - void unsetAppFreezingScreenLocked(AppWindowToken wtoken, - boolean unfreezeSurfaceNow, boolean force) { - if (wtoken.freezingScreen) { - if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken - + " force=" + force); - final int N = wtoken.allAppWindows.size(); - boolean unfrozeWindows = false; - for (int i=0; i<N; i++) { - WindowState w = wtoken.allAppWindows.get(i); - if (w.mAppFreezing) { - w.mAppFreezing = false; - if (w.mSurface != null && !w.mOrientationChanging) { - w.mOrientationChanging = true; - } - unfrozeWindows = true; - } - } - if (force || unfrozeWindows) { - if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken); - wtoken.freezingScreen = false; - mAppsFreezingScreen--; - } - if (unfreezeSurfaceNow) { - if (unfrozeWindows) { - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - } - stopFreezingDisplayLocked(); - } - } - } - - public void startAppFreezingScreenLocked(AppWindowToken wtoken, - int configChanges) { - if (DEBUG_ORIENTATION) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.i(TAG, "Set freezing of " + wtoken.appToken - + ": hidden=" + wtoken.hidden + " freezing=" - + wtoken.freezingScreen, e); - } - if (!wtoken.hiddenRequested) { - if (!wtoken.freezingScreen) { - wtoken.freezingScreen = true; - mAppsFreezingScreen++; - if (mAppsFreezingScreen == 1) { - startFreezingDisplayLocked(false); - mH.removeMessages(H.APP_FREEZE_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT), - 5000); - } - } - final int N = wtoken.allAppWindows.size(); - for (int i=0; i<N; i++) { - WindowState w = wtoken.allAppWindows.get(i); - w.mAppFreezing = true; - } - } - } - - public void startAppFreezingScreen(IBinder token, int configChanges) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppFreezingScreen()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) { - if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token); - return; - } - - AppWindowToken wtoken = findAppWindowToken(token); - if (wtoken == null || wtoken.appToken == null) { - Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken); - return; - } - final long origId = Binder.clearCallingIdentity(); - startAppFreezingScreenLocked(wtoken, configChanges); - Binder.restoreCallingIdentity(origId); - } - } - - public void stopAppFreezingScreen(IBinder token, boolean force) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppFreezingScreen()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - AppWindowToken wtoken = findAppWindowToken(token); - if (wtoken == null || wtoken.appToken == null) { - return; - } - final long origId = Binder.clearCallingIdentity(); - if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token - + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen); - unsetAppFreezingScreenLocked(wtoken, true, force); - Binder.restoreCallingIdentity(origId); - } - } - - public void removeAppToken(IBinder token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "removeAppToken()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - AppWindowToken wtoken = null; - AppWindowToken startingToken = null; - boolean delayed = false; - - final long origId = Binder.clearCallingIdentity(); - synchronized(mWindowMap) { - WindowToken basewtoken = mTokenMap.remove(token); - if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) { - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken); - delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true); - wtoken.inPendingTransaction = false; - mOpeningApps.remove(wtoken); - wtoken.waitingToShow = false; - if (mClosingApps.contains(wtoken)) { - delayed = true; - } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mClosingApps.add(wtoken); - wtoken.waitingToHide = true; - delayed = true; - } - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Removing app " + wtoken + " delayed=" + delayed - + " animation=" + wtoken.animation - + " animating=" + wtoken.animating); - if (delayed) { - // set the token aside because it has an active animation to be finished - if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "removeAppToken make exiting: " + wtoken); - mExitingAppTokens.add(wtoken); - } else { - // Make sure there is no animation running on this token, - // so any windows associated with it will be removed as - // soon as their animations are complete - wtoken.animation = null; - wtoken.animating = false; - } - if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "removeAppToken: " + wtoken); - mAppTokens.remove(wtoken); - wtoken.removed = true; - if (wtoken.startingData != null) { - startingToken = wtoken; - } - unsetAppFreezingScreenLocked(wtoken, true, true); - if (mFocusedApp == wtoken) { - if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken); - mFocusedApp = null; - updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); - mInputMonitor.setFocusedAppLw(null); - } - } else { - Slog.w(TAG, "Attempted to remove non-existing app token: " + token); - } - - if (!delayed && wtoken != null) { - wtoken.updateReportedVisibilityLocked(); - } - } - Binder.restoreCallingIdentity(origId); - - if (startingToken != null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting " - + startingToken + ": app token removed"); - Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken); - mH.sendMessage(m); - } - } - - private boolean tmpRemoveAppWindowsLocked(WindowToken token) { - final int NW = token.windows.size(); - for (int i=0; i<NW; i++) { - WindowState win = token.windows.get(i); - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); - mWindows.remove(win); - mWindowsChanged = true; - int j = win.mChildWindows.size(); - while (j > 0) { - j--; - WindowState cwin = win.mChildWindows.get(j); - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, - "Tmp removing child window " + cwin); - mWindows.remove(cwin); - } - } - return NW > 0; - } - - void dumpAppTokensLocked() { - for (int i=mAppTokens.size()-1; i>=0; i--) { - Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token); - } - } - - void dumpWindowsLocked() { - for (int i=mWindows.size()-1; i>=0; i--) { - Slog.v(TAG, " #" + i + ": " + mWindows.get(i)); - } - } - - private int findWindowOffsetLocked(int tokenPos) { - final int NW = mWindows.size(); - - if (tokenPos >= mAppTokens.size()) { - int i = NW; - while (i > 0) { - i--; - WindowState win = mWindows.get(i); - if (win.getAppToken() != null) { - return i+1; - } - } - } - - while (tokenPos > 0) { - // Find the first app token below the new position that has - // a window displayed. - final AppWindowToken wtoken = mAppTokens.get(tokenPos-1); - if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ " - + tokenPos + " -- " + wtoken.token); - if (wtoken.sendingToBottom) { - if (DEBUG_REORDER) Slog.v(TAG, - "Skipping token -- currently sending to bottom"); - tokenPos--; - continue; - } - int i = wtoken.windows.size(); - while (i > 0) { - i--; - WindowState win = wtoken.windows.get(i); - int j = win.mChildWindows.size(); - while (j > 0) { - j--; - WindowState cwin = win.mChildWindows.get(j); - if (cwin.mSubLayer >= 0) { - for (int pos=NW-1; pos>=0; pos--) { - if (mWindows.get(pos) == cwin) { - if (DEBUG_REORDER) Slog.v(TAG, - "Found child win @" + (pos+1)); - return pos+1; - } - } - } - } - for (int pos=NW-1; pos>=0; pos--) { - if (mWindows.get(pos) == win) { - if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1)); - return pos+1; - } - } - } - tokenPos--; - } - - return 0; - } - - private final int reAddWindowLocked(int index, WindowState win) { - final int NCW = win.mChildWindows.size(); - boolean added = false; - for (int j=0; j<NCW; j++) { - WindowState cwin = win.mChildWindows.get(j); - if (!added && cwin.mSubLayer >= 0) { - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " - + index + ": " + cwin); - win.mRebuilding = false; - mWindows.add(index, win); - index++; - added = true; - } - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " - + index + ": " + cwin); - cwin.mRebuilding = false; - mWindows.add(index, cwin); - index++; - } - if (!added) { - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " - + index + ": " + win); - win.mRebuilding = false; - mWindows.add(index, win); - index++; - } - mWindowsChanged = true; - return index; - } - - private final int reAddAppWindowsLocked(int index, WindowToken token) { - final int NW = token.windows.size(); - for (int i=0; i<NW; i++) { - index = reAddWindowLocked(index, token.windows.get(i)); - } - return index; - } - - public void moveAppToken(int index, IBinder token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "moveAppToken()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized(mWindowMap) { - if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:"); - if (DEBUG_REORDER) dumpAppTokensLocked(); - final AppWindowToken wtoken = findAppWindowToken(token); - if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, - "Start moving token " + wtoken + " initially at " - + mAppTokens.indexOf(wtoken)); - if (wtoken == null || !mAppTokens.remove(wtoken)) { - Slog.w(TAG, "Attempting to reorder token that doesn't exist: " - + token + " (" + wtoken + ")"); - return; - } - mAppTokens.add(index, wtoken); - if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":"); - else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index); - if (DEBUG_REORDER) dumpAppTokensLocked(); - - final long origId = Binder.clearCallingIdentity(); - if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":"); - if (DEBUG_REORDER) dumpWindowsLocked(); - if (tmpRemoveAppWindowsLocked(wtoken)) { - if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:"); - if (DEBUG_REORDER) dumpWindowsLocked(); - reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken); - if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); - if (DEBUG_REORDER) dumpWindowsLocked(); - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/); - mLayoutNeeded = true; - mInputMonitor.setUpdateInputWindowsNeededLw(); - performLayoutAndPlaceSurfacesLocked(); - mInputMonitor.updateInputWindowsLw(false /*force*/); - } - Binder.restoreCallingIdentity(origId); - } - } - - private void removeAppTokensLocked(List<IBinder> tokens) { - // XXX This should be done more efficiently! - // (take advantage of the fact that both lists should be - // ordered in the same way.) - int N = tokens.size(); - for (int i=0; i<N; i++) { - IBinder token = tokens.get(i); - final AppWindowToken wtoken = findAppWindowToken(token); - if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken)); - if (!mAppTokens.remove(wtoken)) { - Slog.w(TAG, "Attempting to reorder token that doesn't exist: " - + token + " (" + wtoken + ")"); - i--; - N--; - } - } - } - - private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos, - boolean updateFocusAndLayout) { - // First remove all of the windows from the list. - tmpRemoveAppWindowsLocked(wtoken); - - // Where to start adding? - int pos = findWindowOffsetLocked(tokenPos); - - // And now add them back at the correct place. - pos = reAddAppWindowsLocked(pos, wtoken); - - if (updateFocusAndLayout) { - mInputMonitor.setUpdateInputWindowsNeededLw(); - if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/)) { - assignLayersLocked(); - } - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - mInputMonitor.updateInputWindowsLw(false /*force*/); - } - } - - private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) { - // First remove all of the windows from the list. - final int N = tokens.size(); - int i; - for (i=0; i<N; i++) { - WindowToken token = mTokenMap.get(tokens.get(i)); - if (token != null) { - tmpRemoveAppWindowsLocked(token); - } - } - - // Where to start adding? - int pos = findWindowOffsetLocked(tokenPos); - - // And now add them back at the correct place. - for (i=0; i<N; i++) { - WindowToken token = mTokenMap.get(tokens.get(i)); - if (token != null) { - pos = reAddAppWindowsLocked(pos, token); - } - } - - mInputMonitor.setUpdateInputWindowsNeededLw(); - if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/)) { - assignLayersLocked(); - } - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - mInputMonitor.updateInputWindowsLw(false /*force*/); - - //dump(); - } - - public void moveAppTokensToTop(List<IBinder> tokens) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "moveAppTokensToTop()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - final long origId = Binder.clearCallingIdentity(); - synchronized(mWindowMap) { - removeAppTokensLocked(tokens); - final int N = tokens.size(); - for (int i=0; i<N; i++) { - AppWindowToken wt = findAppWindowToken(tokens.get(i)); - if (wt != null) { - if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, - "Adding next to top: " + wt); - mAppTokens.add(wt); - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mToTopApps.remove(wt); - mToBottomApps.remove(wt); - mToTopApps.add(wt); - wt.sendingToBottom = false; - wt.sendingToTop = true; - } - } - } - - if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) { - moveAppWindowsLocked(tokens, mAppTokens.size()); - } - } - Binder.restoreCallingIdentity(origId); - } - - public void moveAppTokensToBottom(List<IBinder> tokens) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "moveAppTokensToBottom()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - final long origId = Binder.clearCallingIdentity(); - synchronized(mWindowMap) { - removeAppTokensLocked(tokens); - final int N = tokens.size(); - int pos = 0; - for (int i=0; i<N; i++) { - AppWindowToken wt = findAppWindowToken(tokens.get(i)); - if (wt != null) { - if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "Adding next to bottom: " + wt + " at " + pos); - mAppTokens.add(pos, wt); - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mToTopApps.remove(wt); - mToBottomApps.remove(wt); - mToBottomApps.add(i, wt); - wt.sendingToTop = false; - wt.sendingToBottom = true; - } - pos++; - } - } - - if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) { - moveAppWindowsLocked(tokens, 0); - } - } - Binder.restoreCallingIdentity(origId); - } - - // ------------------------------------------------------------- - // Misc IWindowSession methods - // ------------------------------------------------------------- - - private boolean shouldAllowDisableKeyguard() - { - // We fail safe and prevent disabling keyguard in the unlikely event this gets - // called before DevicePolicyManagerService has started. - if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) { - DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (dpm != null) { - mAllowDisableKeyguard = dpm.getPasswordQuality(null) - == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ? - ALLOW_DISABLE_YES : ALLOW_DISABLE_NO; - } - } - return mAllowDisableKeyguard == ALLOW_DISABLE_YES; - } - - public void disableKeyguard(IBinder token, String tag) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires DISABLE_KEYGUARD permission"); - } - - synchronized (mKeyguardTokenWatcher) { - mKeyguardTokenWatcher.acquire(token, tag); - } - } - - public void reenableKeyguard(IBinder token) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires DISABLE_KEYGUARD permission"); - } - - synchronized (mKeyguardTokenWatcher) { - mKeyguardTokenWatcher.release(token); - - if (!mKeyguardTokenWatcher.isAcquired()) { - // If we are the last one to reenable the keyguard wait until - // we have actually finished reenabling until returning. - // It is possible that reenableKeyguard() can be called before - // the previous disableKeyguard() is handled, in which case - // neither mKeyguardTokenWatcher.acquired() or released() would - // be called. In that case mKeyguardDisabled will be false here - // and we have nothing to wait for. - while (mKeyguardDisabled) { - try { - mKeyguardTokenWatcher.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - } - - /** - * @see android.app.KeyguardManager#exitKeyguardSecurely - */ - public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires DISABLE_KEYGUARD permission"); - } - mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() { - public void onKeyguardExitResult(boolean success) { - try { - callback.onKeyguardExitResult(success); - } catch (RemoteException e) { - // Client has died, we don't care. - } - } - }); - } - - public boolean inKeyguardRestrictedInputMode() { - return mPolicy.inKeyguardRestrictedKeyInputMode(); - } - - public void closeSystemDialogs(String reason) { - synchronized(mWindowMap) { - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mSurface != null) { - try { - w.mClient.closeSystemDialogs(reason); - } catch (RemoteException e) { - } - } - } - } - } - - static float fixScale(float scale) { - if (scale < 0) scale = 0; - else if (scale > 20) scale = 20; - return Math.abs(scale); - } - - public void setAnimationScale(int which, float scale) { - if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, - "setAnimationScale()")) { - throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); - } - - if (scale < 0) scale = 0; - else if (scale > 20) scale = 20; - scale = Math.abs(scale); - switch (which) { - case 0: mWindowAnimationScale = fixScale(scale); break; - case 1: mTransitionAnimationScale = fixScale(scale); break; - } - - // Persist setting - mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); - } - - public void setAnimationScales(float[] scales) { - if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE, - "setAnimationScale()")) { - throw new SecurityException("Requires SET_ANIMATION_SCALE permission"); - } - - if (scales != null) { - if (scales.length >= 1) { - mWindowAnimationScale = fixScale(scales[0]); - } - if (scales.length >= 2) { - mTransitionAnimationScale = fixScale(scales[1]); - } - } - - // Persist setting - mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget(); - } - - public float getAnimationScale(int which) { - switch (which) { - case 0: return mWindowAnimationScale; - case 1: return mTransitionAnimationScale; - } - return 0; - } - - public float[] getAnimationScales() { - return new float[] { mWindowAnimationScale, mTransitionAnimationScale }; - } - - public int getSwitchState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getSwitchStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public int getKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getKeycodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public boolean hasKeys(int[] keycodes, boolean[] keyExists) { - return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists); - } - - public InputChannel monitorInput(String inputChannelName) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "monitorInput()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.monitorInput(inputChannelName); - } - - public InputDevice getInputDevice(int deviceId) { - return mInputManager.getInputDevice(deviceId); - } - - public int[] getInputDeviceIds() { - return mInputManager.getInputDeviceIds(); - } - - public void enableScreenAfterBoot() { - synchronized(mWindowMap) { - if (mSystemBooted) { - return; - } - mSystemBooted = true; - } - - performEnableScreen(); - } - - public void enableScreenIfNeededLocked() { - if (mDisplayEnabled) { - return; - } - if (!mSystemBooted) { - return; - } - mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN)); - } - - public void performEnableScreen() { - synchronized(mWindowMap) { - if (mDisplayEnabled) { - return; - } - if (!mSystemBooted) { - return; - } - - // Don't enable the screen until all existing windows - // have been drawn. - final int N = mWindows.size(); - for (int i=0; i<N; i++) { - WindowState w = mWindows.get(i); - if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { - return; - } - } - - mDisplayEnabled = true; - if (false) { - Slog.i(TAG, "ENABLING SCREEN!"); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - this.dump(null, pw, null); - Slog.i(TAG, sw.toString()); - } - try { - IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); - if (surfaceFlinger != null) { - //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); - Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, - data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); - } - } - - mPolicy.enableScreenAfterBoot(); - - // Make sure the last requested orientation has been applied. - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); - } - - public void setInTouchMode(boolean mode) { - synchronized(mWindowMap) { - mInTouchMode = mode; - } - } - - // TODO: more accounting of which pid(s) turned it on, keep count, - // only allow disables from pids which have count on, etc. - public void showStrictModeViolation(boolean on) { - int pid = Binder.getCallingPid(); - synchronized(mWindowMap) { - // Ignoring requests to enable the red border from clients - // which aren't on screen. (e.g. Broadcast Receivers in - // the background..) - if (on) { - boolean isVisible = false; - for (WindowState ws : mWindows) { - if (ws.mSession.mPid == pid && ws.isVisibleLw()) { - isVisible = true; - break; - } - } - if (!isVisible) { - return; - } - } - - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION showStrictModeViolation"); - Surface.openTransaction(); - try { - if (mStrictModeFlash == null) { - mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession); - } - mStrictModeFlash.setVisibility(on); - } finally { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION showStrictModeViolation"); - } - } - } - - public void setStrictModeVisualIndicatorPreference(String value) { - SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); - } - - public Bitmap screenshotApplications(IBinder appToken, int maxWidth, int maxHeight) { - if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, - "screenshotApplications()")) { - throw new SecurityException("Requires READ_FRAME_BUFFER permission"); - } - - Bitmap rawss; - - int maxLayer = 0; - final Rect frame = new Rect(); - - float scale; - int sw, sh, dw, dh; - int rot; - - synchronized(mWindowMap) { - long ident = Binder.clearCallingIdentity(); - - dw = mDisplay.getWidth(); - dh = mDisplay.getHeight(); - - int aboveAppLayer = mPolicy.windowTypeToLayerLw( - WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; - aboveAppLayer += TYPE_LAYER_MULTIPLIER; - - boolean isImeTarget = mInputMethodTarget != null - && mInputMethodTarget.mAppToken != null - && mInputMethodTarget.mAppToken.appToken != null - && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken; - - // Figure out the part of the screen that is actually the app. - boolean including = false; - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState ws = mWindows.get(i); - if (ws.mSurface == null) { - continue; - } - if (ws.mLayer >= aboveAppLayer) { - continue; - } - // When we will skip windows: when we are not including - // ones behind a window we didn't skip, and we are actually - // taking a screenshot of a specific app. - if (!including && appToken != null) { - // Also, we can possibly skip this window if it is not - // an IME target or the application for the screenshot - // is not the current IME target. - if (!ws.mIsImWindow || !isImeTarget) { - // And finally, this window is of no interest if it - // is not associated with the screenshot app. - if (ws.mAppToken == null || ws.mAppToken.token != appToken) { - continue; - } - } - } - - // We keep on including windows until we go past a full-screen - // window. - including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh); - - if (maxLayer < ws.mAnimLayer) { - maxLayer = ws.mAnimLayer; - } - final Rect wf = ws.mFrame; - final Rect cr = ws.mContentInsets; - int left = wf.left + cr.left; - int top = wf.top + cr.top; - int right = wf.right - cr.right; - int bottom = wf.bottom - cr.bottom; - frame.union(left, top, right, bottom); - } - Binder.restoreCallingIdentity(ident); - - // Constrain frame to the screen size. - frame.intersect(0, 0, dw, dh); - - if (frame.isEmpty() || maxLayer == 0) { - return null; - } - - // The screenshot API does not apply the current screen rotation. - rot = mDisplay.getRotation(); - int fw = frame.width(); - int fh = frame.height(); - - // First try reducing to fit in x dimension. - scale = maxWidth/(float)fw; - sw = maxWidth; - sh = (int)(fh*scale); - if (sh > maxHeight) { - // y dimension became too long; constrain by that. - scale = maxHeight/(float)fh; - sw = (int)(fw*scale); - sh = maxHeight; - } - - // The screen shot will contain the entire screen. - dw = (int)(dw*scale); - dh = (int)(dh*scale); - if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { - int tmp = dw; - dw = dh; - dh = tmp; - rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; - } - rawss = Surface.screenshot(dw, dh, 0, maxLayer); - } - - if (rawss == null) { - Log.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh - + ") to layer " + maxLayer); - return null; - } - - Bitmap bm = Bitmap.createBitmap(sw, sh, rawss.getConfig()); - Matrix matrix = new Matrix(); - ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix); - matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale)); - Canvas canvas = new Canvas(bm); - canvas.drawBitmap(rawss, matrix, null); - - rawss.recycle(); - return bm; - } - - public void freezeRotation() { - if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { - throw new SecurityException("Requires SET_ORIENTATION permission"); - } - - mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); - } - - public void thawRotation() { - if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { - throw new SecurityException("Requires SET_ORIENTATION permission"); - } - - mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 0); - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); - } - - public void setRotation(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { - throw new SecurityException("Requires SET_ORIENTATION permission"); - } - - setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags); - } - - public void setRotationUnchecked(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if(DEBUG_ORIENTATION) Slog.v(TAG, - "setRotationUnchecked(rotation=" + rotation + - " alwaysSendConfiguration=" + alwaysSendConfiguration + - " animFlags=" + animFlags); - - long origId = Binder.clearCallingIdentity(); - boolean changed; - synchronized(mWindowMap) { - changed = setRotationUncheckedLocked(rotation, animFlags, false); - } - - if (changed || alwaysSendConfiguration) { - sendNewConfiguration(); - } - - Binder.restoreCallingIdentity(origId); - } - - /** - * Apply a new rotation to the screen, respecting the requests of - * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply - * re-evaluate the desired rotation. - * - * Returns null if the rotation has been changed. In this case YOU - * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN. - */ - public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) { - if (mDragState != null || mScreenRotationAnimation != null) { - // Potential rotation during a drag. Don't do the rotation now, but make - // a note to perform the rotation later. - if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation."); - if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) { - mDeferredRotation = rotation; - mDeferredRotationAnimFlags = animFlags; - } - return false; - } - - boolean changed; - if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { - if (mDeferredRotation != WindowManagerPolicy.USE_LAST_ROTATION) { - rotation = mDeferredRotation; - mRequestedRotation = rotation; - mLastRotationFlags = mDeferredRotationAnimFlags; - } - rotation = mRequestedRotation; - } else { - mRequestedRotation = rotation; - mLastRotationFlags = animFlags; - } - mDeferredRotation = WindowManagerPolicy.USE_LAST_ROTATION; - if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation); - rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, - mRotation, mDisplayEnabled); - if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation); - changed = mDisplayEnabled && mRotation != rotation; - - if (changed) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Rotation changed to " + rotation - + " from " + mRotation - + " (forceApp=" + mForcedAppOrientation - + ", req=" + mRequestedRotation + ")"); - mRotation = rotation; - mWindowsFreezingScreen = true; - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), - 2000); - mWaitingForConfig = true; - mLayoutNeeded = true; - startFreezingDisplayLocked(inTransaction); - Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); - mInputManager.setDisplayOrientation(0, rotation); - if (mDisplayEnabled) { - // NOTE: We disable the rotation in the emulator because - // it doesn't support hardware OpenGL emulation yet. - if (CUSTOM_SCREEN_ROTATION && !mInEmulator) { - Surface.freezeDisplay(0); - if (!inTransaction) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setRotationUnchecked"); - Surface.openTransaction(); - } - try { - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.setRotation(rotation); - } - } finally { - if (!inTransaction) { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, - "<<< CLOSE TRANSACTION setRotationUnchecked"); - } - } - Surface.setOrientation(0, rotation, animFlags); - Surface.unfreezeDisplay(0); - } else { - Surface.setOrientation(0, rotation, animFlags); - } - } - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mSurface != null) { - w.mOrientationChanging = true; - } - } - for (int i=mRotationWatchers.size()-1; i>=0; i--) { - try { - mRotationWatchers.get(i).onRotationChanged(rotation); - } catch (RemoteException e) { - } - } - } //end if changed - - return changed; - } - - public int getRotation() { - return mRotation; - } - - public int watchRotation(IRotationWatcher watcher) { - final IBinder watcherBinder = watcher.asBinder(); - IBinder.DeathRecipient dr = new IBinder.DeathRecipient() { - public void binderDied() { - synchronized (mWindowMap) { - for (int i=0; i<mRotationWatchers.size(); i++) { - if (watcherBinder == mRotationWatchers.get(i).asBinder()) { - IRotationWatcher removed = mRotationWatchers.remove(i); - if (removed != null) { - removed.asBinder().unlinkToDeath(this, 0); - } - i--; - } - } - } - } - }; - - synchronized (mWindowMap) { - try { - watcher.asBinder().linkToDeath(dr, 0); - mRotationWatchers.add(watcher); - } catch (RemoteException e) { - // Client died, no cleanup needed. - } - - return mRotation; - } - } - - /** - * Starts the view server on the specified port. - * - * @param port The port to listener to. - * - * @return True if the server was successfully started, false otherwise. - * - * @see com.android.server.ViewServer - * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT - */ - public boolean startViewServer(int port) { - if (isSystemSecure()) { - return false; - } - - if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) { - return false; - } - - if (port < 1024) { - return false; - } - - if (mViewServer != null) { - if (!mViewServer.isRunning()) { - try { - return mViewServer.start(); - } catch (IOException e) { - Slog.w(TAG, "View server did not start"); - } - } - return false; - } - - try { - mViewServer = new ViewServer(this, port); - return mViewServer.start(); - } catch (IOException e) { - Slog.w(TAG, "View server did not start"); - } - return false; - } - - private boolean isSystemSecure() { - return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) && - "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); - } - - /** - * Stops the view server if it exists. - * - * @return True if the server stopped, false if it wasn't started or - * couldn't be stopped. - * - * @see com.android.server.ViewServer - */ - public boolean stopViewServer() { - if (isSystemSecure()) { - return false; - } - - if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) { - return false; - } - - if (mViewServer != null) { - return mViewServer.stop(); - } - return false; - } - - /** - * Indicates whether the view server is running. - * - * @return True if the server is running, false otherwise. - * - * @see com.android.server.ViewServer - */ - public boolean isViewServerRunning() { - if (isSystemSecure()) { - return false; - } - - if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) { - return false; - } - - return mViewServer != null && mViewServer.isRunning(); - } - - /** - * Lists all availble windows in the system. The listing is written in the - * specified Socket's output stream with the following syntax: - * windowHashCodeInHexadecimal windowName - * Each line of the ouput represents a different window. - * - * @param client The remote client to send the listing to. - * @return False if an error occured, true otherwise. - */ - boolean viewServerListWindows(Socket client) { - if (isSystemSecure()) { - return false; - } - - boolean result = true; - - WindowState[] windows; - synchronized (mWindowMap) { - //noinspection unchecked - windows = mWindows.toArray(new WindowState[mWindows.size()]); - } - - BufferedWriter out = null; - - // Any uncaught exception will crash the system process - try { - OutputStream clientStream = client.getOutputStream(); - out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); - - final int count = windows.length; - for (int i = 0; i < count; i++) { - final WindowState w = windows[i]; - out.write(Integer.toHexString(System.identityHashCode(w))); - out.write(' '); - out.append(w.mAttrs.getTitle()); - out.write('\n'); - } - - out.write("DONE.\n"); - out.flush(); - } catch (Exception e) { - result = false; - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - result = false; - } - } - } - - return result; - } - - /** - * Returns the focused window in the following format: - * windowHashCodeInHexadecimal windowName - * - * @param client The remote client to send the listing to. - * @return False if an error occurred, true otherwise. - */ - boolean viewServerGetFocusedWindow(Socket client) { - if (isSystemSecure()) { - return false; - } - - boolean result = true; - - WindowState focusedWindow = getFocusedWindow(); - - BufferedWriter out = null; - - // Any uncaught exception will crash the system process - try { - OutputStream clientStream = client.getOutputStream(); - out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024); - - if(focusedWindow != null) { - out.write(Integer.toHexString(System.identityHashCode(focusedWindow))); - out.write(' '); - out.append(focusedWindow.mAttrs.getTitle()); - } - out.write('\n'); - out.flush(); - } catch (Exception e) { - result = false; - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - result = false; - } - } - } - - return result; - } - - /** - * Sends a command to a target window. The result of the command, if any, will be - * written in the output stream of the specified socket. - * - * The parameters must follow this syntax: - * windowHashcode extra - * - * Where XX is the length in characeters of the windowTitle. - * - * The first parameter is the target window. The window with the specified hashcode - * will be the target. If no target can be found, nothing happens. The extra parameters - * will be delivered to the target window and as parameters to the command itself. - * - * @param client The remote client to sent the result, if any, to. - * @param command The command to execute. - * @param parameters The command parameters. - * - * @return True if the command was successfully delivered, false otherwise. This does - * not indicate whether the command itself was successful. - */ - boolean viewServerWindowCommand(Socket client, String command, String parameters) { - if (isSystemSecure()) { - return false; - } - - boolean success = true; - Parcel data = null; - Parcel reply = null; - - BufferedWriter out = null; - - // Any uncaught exception will crash the system process - try { - // Find the hashcode of the window - int index = parameters.indexOf(' '); - if (index == -1) { - index = parameters.length(); - } - final String code = parameters.substring(0, index); - int hashCode = (int) Long.parseLong(code, 16); - - // Extract the command's parameter after the window description - if (index < parameters.length()) { - parameters = parameters.substring(index + 1); - } else { - parameters = ""; - } - - final WindowManagerService.WindowState window = findWindow(hashCode); - if (window == null) { - return false; - } - - data = Parcel.obtain(); - data.writeInterfaceToken("android.view.IWindow"); - data.writeString(command); - data.writeString(parameters); - data.writeInt(1); - ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0); - - reply = Parcel.obtain(); - - final IBinder binder = window.mClient.asBinder(); - // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER - binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); - - reply.readException(); - - if (!client.isOutputShutdown()) { - out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); - out.write("DONE\n"); - out.flush(); - } - - } catch (Exception e) { - Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); - success = false; - } finally { - if (data != null) { - data.recycle(); - } - if (reply != null) { - reply.recycle(); - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - - } - } - } - - return success; - } - - public void addWindowChangeListener(WindowChangeListener listener) { - synchronized(mWindowMap) { - mWindowChangeListeners.add(listener); - } - } - - public void removeWindowChangeListener(WindowChangeListener listener) { - synchronized(mWindowMap) { - mWindowChangeListeners.remove(listener); - } - } - - private void notifyWindowsChanged() { - WindowChangeListener[] windowChangeListeners; - synchronized(mWindowMap) { - if(mWindowChangeListeners.isEmpty()) { - return; - } - windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; - windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); - } - int N = windowChangeListeners.length; - for(int i = 0; i < N; i++) { - windowChangeListeners[i].windowsChanged(); - } - } - - private void notifyFocusChanged() { - WindowChangeListener[] windowChangeListeners; - synchronized(mWindowMap) { - if(mWindowChangeListeners.isEmpty()) { - return; - } - windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()]; - windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners); - } - int N = windowChangeListeners.length; - for(int i = 0; i < N; i++) { - windowChangeListeners[i].focusChanged(); - } - } - - private WindowState findWindow(int hashCode) { - if (hashCode == -1) { - return getFocusedWindow(); - } - - synchronized (mWindowMap) { - final ArrayList<WindowState> windows = mWindows; - final int count = windows.size(); - - for (int i = 0; i < count; i++) { - WindowState w = windows.get(i); - if (System.identityHashCode(w) == hashCode) { - return w; - } - } - } - - return null; - } - - /* - * Instruct the Activity Manager to fetch the current configuration and broadcast - * that to config-changed listeners if appropriate. - */ - void sendNewConfiguration() { - try { - mActivityManager.updateConfiguration(null); - } catch (RemoteException e) { - } - } - - public Configuration computeNewConfiguration() { - synchronized (mWindowMap) { - Configuration config = computeNewConfigurationLocked(); - if (config == null && mWaitingForConfig) { - // Nothing changed but we are waiting for something... stop that! - mWaitingForConfig = false; - performLayoutAndPlaceSurfacesLocked(); - } - return config; - } - } - - Configuration computeNewConfigurationLocked() { - Configuration config = new Configuration(); - if (!computeNewConfigurationLocked(config)) { - return null; - } - return config; - } - - boolean computeNewConfigurationLocked(Configuration config) { - if (mDisplay == null) { - return false; - } - - mInputManager.getInputConfiguration(config); - - // Use the effective "visual" dimensions based on current rotation - final boolean rotated = (mRotation == Surface.ROTATION_90 - || mRotation == Surface.ROTATION_270); - final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth; - final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight; - - int orientation = Configuration.ORIENTATION_SQUARE; - if (dw < dh) { - orientation = Configuration.ORIENTATION_PORTRAIT; - } else if (dw > dh) { - orientation = Configuration.ORIENTATION_LANDSCAPE; - } - config.orientation = orientation; - - DisplayMetrics dm = new DisplayMetrics(); - mDisplay.getMetrics(dm); - CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame); - - if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) { - // Note we only do this once because at this point we don't - // expect the screen to change in this way at runtime, and want - // to avoid all of this computation for every config change. - int longSize = dw; - int shortSize = dh; - if (longSize < shortSize) { - int tmp = longSize; - longSize = shortSize; - shortSize = tmp; - } - longSize = (int)(longSize/dm.density); - shortSize = (int)(shortSize/dm.density); - - // These semi-magic numbers define our compatibility modes for - // applications with different screens. Don't change unless you - // make sure to test lots and lots of apps! - if (longSize < 470) { - // This is shorter than an HVGA normal density screen (which - // is 480 pixels on its long side). - mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL - | Configuration.SCREENLAYOUT_LONG_NO; - } else { - // What size is this screen screen? - if (longSize >= 800 && shortSize >= 600) { - // SVGA or larger screens at medium density are the point - // at which we consider it to be an extra large screen. - mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE; - } else if (longSize >= 530 && shortSize >= 400) { - // SVGA or larger screens at high density are the point - // at which we consider it to be a large screen. - mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; - } else { - mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL; - } - - // If this screen is wider than normal HVGA, or taller - // than FWVGA, then for old apps we want to run in size - // compatibility mode. - if (shortSize > 321 || longSize > 570) { - mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; - } - - // Is this a long screen? - if (((longSize*3)/5) >= (shortSize-1)) { - // Anything wider than WVGA (5:3) is considering to be long. - mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES; - } else { - mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO; - } - } - } - config.screenLayout = mScreenLayout; - - // Determine whether a hard keyboard is available and enabled. - boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; - if (hardKeyboardAvailable != mHardKeyboardAvailable) { - mHardKeyboardAvailable = hardKeyboardAvailable; - mHardKeyboardEnabled = hardKeyboardAvailable; - - mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); - mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); - } - if (!mHardKeyboardEnabled) { - config.keyboard = Configuration.KEYBOARD_NOKEYS; - } - - // Update value of keyboardHidden, hardKeyboardHidden and navigationHidden - // based on whether a hard or soft keyboard is present, whether navigation keys - // are present and the lid switch state. - config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; - config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; - config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; - mPolicy.adjustConfigurationLw(config); - return true; - } - - public boolean isHardKeyboardAvailable() { - synchronized (mWindowMap) { - return mHardKeyboardAvailable; - } - } - - public boolean isHardKeyboardEnabled() { - synchronized (mWindowMap) { - return mHardKeyboardEnabled; - } - } - - public void setHardKeyboardEnabled(boolean enabled) { - synchronized (mWindowMap) { - if (mHardKeyboardEnabled != enabled) { - mHardKeyboardEnabled = enabled; - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - } - } - - public void setOnHardKeyboardStatusChangeListener( - OnHardKeyboardStatusChangeListener listener) { - synchronized (mWindowMap) { - mHardKeyboardStatusChangeListener = listener; - } - } - - void notifyHardKeyboardStatusChange() { - final boolean available, enabled; - final OnHardKeyboardStatusChangeListener listener; - synchronized (mWindowMap) { - listener = mHardKeyboardStatusChangeListener; - available = mHardKeyboardAvailable; - enabled = mHardKeyboardEnabled; - } - if (listener != null) { - listener.onHardKeyboardStatusChange(available, enabled); - } - } - - // ------------------------------------------------------------- - // Drag and drop - // ------------------------------------------------------------- - - IBinder prepareDragSurface(IWindow window, SurfaceSession session, - int flags, int width, int height, Surface outSurface) { - if (DEBUG_DRAG) { - Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height - + " flags=" + Integer.toHexString(flags) + " win=" + window - + " asbinder=" + window.asBinder()); - } - - final int callerPid = Binder.getCallingPid(); - final long origId = Binder.clearCallingIdentity(); - IBinder token = null; - - try { - synchronized (mWindowMap) { - try { - if (mDragState == null) { - Surface surface = new Surface(session, callerPid, "drag surface", 0, - width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN); - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG " - + surface + ": CREATE"); - outSurface.copyFrom(surface); - final IBinder winBinder = window.asBinder(); - token = new Binder(); - mDragState = new DragState(token, surface, /*flags*/ 0, winBinder); - mDragState.mSurface = surface; - token = mDragState.mToken = new Binder(); - - // 5 second timeout for this window to actually begin the drag - mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); - Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); - mH.sendMessageDelayed(msg, 5000); - } else { - Slog.w(TAG, "Drag already in progress"); - } - } catch (Surface.OutOfResourcesException e) { - Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e); - if (mDragState != null) { - mDragState.reset(); - mDragState = null; - } - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - - return token; - } - - // ------------------------------------------------------------- - // Input Events and Focus Management - // ------------------------------------------------------------- - - InputMonitor mInputMonitor = new InputMonitor(); - - /* Tracks the progress of input dispatch and ensures that input dispatch state - * is kept in sync with changes in window focus, visibility, registration, and - * other relevant Window Manager state transitions. */ - final class InputMonitor { - // Current window with input focus for keys and other non-touch events. May be null. - private WindowState mInputFocus; - - // When true, prevents input dispatch from proceeding until set to false again. - private boolean mInputDispatchFrozen; - - // When true, input dispatch proceeds normally. Otherwise all events are dropped. - private boolean mInputDispatchEnabled = true; - - // When true, need to call updateInputWindowsLw(). - private boolean mUpdateInputWindowsNeeded = true; - - // Temporary list of windows information to provide to the input dispatcher. - private InputWindowList mTempInputWindows = new InputWindowList(); - - // Temporary input application object to provide to the input dispatcher. - private InputApplication mTempInputApplication = new InputApplication(); - - // Set to true when the first input device configuration change notification - // is received to indicate that the input devices are ready. - private final Object mInputDevicesReadyMonitor = new Object(); - private boolean mInputDevicesReady; - - /* Notifies the window manager about a broken input channel. - * - * Called by the InputManager. - */ - public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) { - if (inputWindowHandle == null) { - return; - } - - synchronized (mWindowMap) { - WindowState windowState = (WindowState) inputWindowHandle.windowState; - Slog.i(TAG, "WINDOW DIED " + windowState); - removeWindowLocked(windowState.mSession, windowState); - } - } - - /* Notifies the window manager about an application that is not responding. - * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. - * - * Called by the InputManager. - */ - public long notifyANR(InputApplicationHandle inputApplicationHandle, - InputWindowHandle inputWindowHandle) { - AppWindowToken appWindowToken = null; - if (inputWindowHandle != null) { - synchronized (mWindowMap) { - WindowState windowState = (WindowState) inputWindowHandle.windowState; - if (windowState != null) { - Slog.i(TAG, "Input event dispatching timed out sending to " - + windowState.mAttrs.getTitle()); - appWindowToken = windowState.mAppToken; - } - } - } - - if (appWindowToken == null && inputApplicationHandle != null) { - appWindowToken = inputApplicationHandle.appWindowToken; - Slog.i(TAG, "Input event dispatching timed out sending to application " - + appWindowToken.stringName); - } - - if (appWindowToken != null && appWindowToken.appToken != null) { - try { - // Notify the activity manager about the timeout and let it decide whether - // to abort dispatching or keep waiting. - boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(); - if (! abort) { - // The activity manager declined to abort dispatching. - // Wait a bit longer and timeout again later. - return appWindowToken.inputDispatchingTimeoutNanos; - } - } catch (RemoteException ex) { - } - } - return 0; // abort dispatching - } - - private void addDragInputWindowLw(InputWindowList windowList) { - final InputWindow inputWindow = windowList.add(); - inputWindow.inputChannel = mDragState.mServerChannel; - inputWindow.name = "drag"; - inputWindow.layoutParamsFlags = 0; - inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; - inputWindow.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - inputWindow.visible = true; - inputWindow.canReceiveKeys = false; - inputWindow.hasFocus = true; - inputWindow.hasWallpaper = false; - inputWindow.paused = false; - inputWindow.layer = mDragState.getDragLayerLw(); - inputWindow.ownerPid = Process.myPid(); - inputWindow.ownerUid = Process.myUid(); - - // The drag window covers the entire display - inputWindow.frameLeft = 0; - inputWindow.frameTop = 0; - inputWindow.frameRight = mDisplay.getWidth(); - inputWindow.frameBottom = mDisplay.getHeight(); - - // The drag window cannot receive new touches. - inputWindow.touchableRegion.setEmpty(); - } - - public void setUpdateInputWindowsNeededLw() { - mUpdateInputWindowsNeeded = true; - } - - /* Updates the cached window information provided to the input dispatcher. */ - public void updateInputWindowsLw(boolean force) { - if (!force && !mUpdateInputWindowsNeeded) { - return; - } - mUpdateInputWindowsNeeded = false; - - // Populate the input window list with information about all of the windows that - // could potentially receive input. - // As an optimization, we could try to prune the list of windows but this turns - // out to be difficult because only the native code knows for sure which window - // currently has touch focus. - final ArrayList<WindowState> windows = mWindows; - - // If there's a drag in flight, provide a pseudowindow to catch drag input - final boolean inDrag = (mDragState != null); - if (inDrag) { - if (DEBUG_DRAG) { - Log.d(TAG, "Inserting drag window"); - } - addDragInputWindowLw(mTempInputWindows); - } - - final int N = windows.size(); - for (int i = N - 1; i >= 0; i--) { - final WindowState child = windows.get(i); - if (child.mInputChannel == null || child.mRemoved) { - // Skip this window because it cannot possibly receive input. - continue; - } - - final int flags = child.mAttrs.flags; - final int type = child.mAttrs.type; - - final boolean hasFocus = (child == mInputFocus); - final boolean isVisible = child.isVisibleLw(); - final boolean hasWallpaper = (child == mWallpaperTarget) - && (type != WindowManager.LayoutParams.TYPE_KEYGUARD); - - // If there's a drag in progress and 'child' is a potential drop target, - // make sure it's been told about the drag - if (inDrag && isVisible) { - mDragState.sendDragStartedIfNeededLw(child); - } - - // Add a window to our list of input windows. - final InputWindow inputWindow = mTempInputWindows.add(); - inputWindow.inputWindowHandle = child.mInputWindowHandle; - inputWindow.inputChannel = child.mInputChannel; - inputWindow.name = child.toString(); - inputWindow.layoutParamsFlags = flags; - inputWindow.layoutParamsType = type; - inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); - inputWindow.visible = isVisible; - inputWindow.canReceiveKeys = child.canReceiveKeys(); - inputWindow.hasFocus = hasFocus; - inputWindow.hasWallpaper = hasWallpaper; - inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false; - inputWindow.layer = child.mLayer; - inputWindow.ownerPid = child.mSession.mPid; - inputWindow.ownerUid = child.mSession.mUid; - - final Rect frame = child.mFrame; - inputWindow.frameLeft = frame.left; - inputWindow.frameTop = frame.top; - inputWindow.frameRight = frame.right; - inputWindow.frameBottom = frame.bottom; - - child.getTouchableRegion(inputWindow.touchableRegion); - } - - // Send windows to native code. - mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray()); - - // Clear the list in preparation for the next round. - // Also avoids keeping InputChannel objects referenced unnecessarily. - mTempInputWindows.clear(); - } - - /* Notifies that the input device configuration has changed. */ - public void notifyConfigurationChanged() { - sendNewConfiguration(); - - synchronized (mInputDevicesReadyMonitor) { - if (!mInputDevicesReady) { - mInputDevicesReady = true; - mInputDevicesReadyMonitor.notifyAll(); - } - } - } - - /* Waits until the built-in input devices have been configured. */ - public boolean waitForInputDevicesReady(long timeoutMillis) { - synchronized (mInputDevicesReadyMonitor) { - if (!mInputDevicesReady) { - try { - mInputDevicesReadyMonitor.wait(timeoutMillis); - } catch (InterruptedException ex) { - } - } - return mInputDevicesReady; - } - } - - /* Notifies that the lid switch changed state. */ - public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { - mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); - } - - /* Provides an opportunity for the window manager policy to intercept early key - * processing as soon as the key has been read from the device. */ - public int interceptKeyBeforeQueueing( - KeyEvent event, int policyFlags, boolean isScreenOn) { - return mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn); - } - - /* Provides an opportunity for the window manager policy to process a key before - * ordinary dispatch. */ - public boolean interceptKeyBeforeDispatching( - InputWindowHandle focus, KeyEvent event, int policyFlags) { - WindowState windowState = focus != null ? (WindowState) focus.windowState : null; - return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags); - } - - /* Provides an opportunity for the window manager policy to process a key that - * the application did not handle. */ - public KeyEvent dispatchUnhandledKey( - InputWindowHandle focus, KeyEvent event, int policyFlags) { - WindowState windowState = focus != null ? (WindowState) focus.windowState : null; - return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags); - } - - /* Called when the current input focus changes. - * Layer assignment is assumed to be complete by the time this is called. - */ - public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { - if (DEBUG_INPUT) { - Slog.d(TAG, "Input focus has changed to " + newWindow); - } - - if (newWindow != mInputFocus) { - if (newWindow != null && newWindow.canReceiveKeys()) { - // Displaying a window implicitly causes dispatching to be unpaused. - // This is to protect against bugs if someone pauses dispatching but - // forgets to resume. - newWindow.mToken.paused = false; - } - - mInputFocus = newWindow; - setUpdateInputWindowsNeededLw(); - - if (updateInputWindows) { - updateInputWindowsLw(false /*force*/); - } - } - } - - public void setFocusedAppLw(AppWindowToken newApp) { - // Focused app has changed. - if (newApp == null) { - mInputManager.setFocusedApplication(null); - } else { - mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle; - mTempInputApplication.name = newApp.toString(); - mTempInputApplication.dispatchingTimeoutNanos = - newApp.inputDispatchingTimeoutNanos; - - mInputManager.setFocusedApplication(mTempInputApplication); - - mTempInputApplication.recycle(); - } - } - - public void pauseDispatchingLw(WindowToken window) { - if (! window.paused) { - if (DEBUG_INPUT) { - Slog.v(TAG, "Pausing WindowToken " + window); - } - - window.paused = true; - updateInputWindowsLw(true /*force*/); - } - } - - public void resumeDispatchingLw(WindowToken window) { - if (window.paused) { - if (DEBUG_INPUT) { - Slog.v(TAG, "Resuming WindowToken " + window); - } - - window.paused = false; - updateInputWindowsLw(true /*force*/); - } - } - - public void freezeInputDispatchingLw() { - if (! mInputDispatchFrozen) { - if (DEBUG_INPUT) { - Slog.v(TAG, "Freezing input dispatching"); - } - - mInputDispatchFrozen = true; - updateInputDispatchModeLw(); - } - } - - public void thawInputDispatchingLw() { - if (mInputDispatchFrozen) { - if (DEBUG_INPUT) { - Slog.v(TAG, "Thawing input dispatching"); - } - - mInputDispatchFrozen = false; - updateInputDispatchModeLw(); - } - } - - public void setEventDispatchingLw(boolean enabled) { - if (mInputDispatchEnabled != enabled) { - if (DEBUG_INPUT) { - Slog.v(TAG, "Setting event dispatching to " + enabled); - } - - mInputDispatchEnabled = enabled; - updateInputDispatchModeLw(); - } - } - - private void updateInputDispatchModeLw() { - mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen); - } - } - - public void pauseKeyDispatching(IBinder _token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "pauseKeyDispatching()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized (mWindowMap) { - WindowToken token = mTokenMap.get(_token); - if (token != null) { - mInputMonitor.pauseDispatchingLw(token); - } - } - } - - public void resumeKeyDispatching(IBinder _token) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "resumeKeyDispatching()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized (mWindowMap) { - WindowToken token = mTokenMap.get(_token); - if (token != null) { - mInputMonitor.resumeDispatchingLw(token); - } - } - } - - public void setEventDispatching(boolean enabled) { - if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "resumeKeyDispatching()")) { - throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); - } - - synchronized (mWindowMap) { - mInputMonitor.setEventDispatchingLw(enabled); - } - } - - /** - * Injects a keystroke event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the keystroke action. (Be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectKeyEvent(KeyEvent ev, boolean sync) { - long downTime = ev.getDownTime(); - long eventTime = ev.getEventTime(); - - int action = ev.getAction(); - int code = ev.getKeyCode(); - int repeatCount = ev.getRepeatCount(); - int metaState = ev.getMetaState(); - int deviceId = ev.getDeviceId(); - int scancode = ev.getScanCode(); - int source = ev.getSource(); - int flags = ev.getFlags(); - - if (source == InputDevice.SOURCE_UNKNOWN) { - source = InputDevice.SOURCE_KEYBOARD; - } - - if (eventTime == 0) eventTime = SystemClock.uptimeMillis(); - if (downTime == 0) downTime = eventTime; - - KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, - deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); - - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); - } - - /** - * Inject a pointer (touch) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the pointer (touch) action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectPointerEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { - newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); - } - - /** - * Inject a trackball (navigation device) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the trackball action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectTrackballEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { - newEvent.setSource(InputDevice.SOURCE_TRACKBALL); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); - } - - /** - * Inject an input event into the UI without waiting for dispatch to commence. - * This variant is useful for fire-and-forget input event injection. It does not - * block any longer than it takes to enqueue the input event. - * - * @param ev An input event. (Be sure to set the input source correctly.) - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectInputEventNoWait(InputEvent ev) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(ev, pid, uid, - InputManager.INPUT_EVENT_INJECTION_SYNC_NONE, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result); - } - - private boolean reportInjectionResult(int result) { - switch (result) { - case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: - Slog.w(TAG, "Input event injection permission denied."); - throw new SecurityException( - "Injecting to another application requires INJECT_EVENTS permission"); - case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: - //Slog.v(TAG, "Input event injection succeeded."); - return true; - case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: - Slog.w(TAG, "Input event injection timed out."); - return false; - case InputManager.INPUT_EVENT_INJECTION_FAILED: - default: - Slog.w(TAG, "Input event injection failed."); - return false; - } - } - - private WindowState getFocusedWindow() { - synchronized (mWindowMap) { - return getFocusedWindowLocked(); - } - } - - private WindowState getFocusedWindowLocked() { - return mCurrentFocus; - } - - public boolean detectSafeMode() { - if (!mInputMonitor.waitForInputDevicesReady( - INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { - Slog.w(TAG, "Devices still not ready after waiting " - + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS - + " milliseconds before attempting to detect safe mode."); - } - - mSafeMode = mPolicy.detectSafeMode(); - return mSafeMode; - } - - public void systemReady() { - synchronized(mWindowMap) { - if (mDisplay != null) { - throw new IllegalStateException("Display already initialized"); - } - WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); - mDisplay = wm.getDefaultDisplay(); - mInitialDisplayWidth = mDisplay.getWidth(); - mInitialDisplayHeight = mDisplay.getHeight(); - mInputManager.setDisplaySize(0, Display.unmapDisplaySize(mInitialDisplayWidth), - Display.unmapDisplaySize(mInitialDisplayHeight)); - } - - try { - mActivityManager.updateConfiguration(null); - } catch (RemoteException e) { - } - - mPolicy.systemReady(); - } - - // ------------------------------------------------------------- - // Client Session State - // ------------------------------------------------------------- - - private final class Session extends IWindowSession.Stub - implements IBinder.DeathRecipient { - final IInputMethodClient mClient; - final IInputContext mInputContext; - final int mUid; - final int mPid; - final String mStringName; - SurfaceSession mSurfaceSession; - int mNumWindow = 0; - boolean mClientDead = false; - - public Session(IInputMethodClient client, IInputContext inputContext) { - mClient = client; - mInputContext = inputContext; - mUid = Binder.getCallingUid(); - mPid = Binder.getCallingPid(); - StringBuilder sb = new StringBuilder(); - sb.append("Session{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" uid "); - sb.append(mUid); - sb.append("}"); - mStringName = sb.toString(); - - synchronized (mWindowMap) { - if (mInputMethodManager == null && mHaveInputMethods) { - IBinder b = ServiceManager.getService( - Context.INPUT_METHOD_SERVICE); - mInputMethodManager = IInputMethodManager.Stub.asInterface(b); - } - } - long ident = Binder.clearCallingIdentity(); - try { - // Note: it is safe to call in to the input method manager - // here because we are not holding our lock. - if (mInputMethodManager != null) { - mInputMethodManager.addClient(client, inputContext, - mUid, mPid); - } else { - client.setUsingInputMethod(false); - } - client.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - // The caller has died, so we can just forget about this. - try { - if (mInputMethodManager != null) { - mInputMethodManager.removeClient(client); - } - } catch (RemoteException ee) { - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (RuntimeException e) { - // Log all 'real' exceptions thrown to the caller - if (!(e instanceof SecurityException)) { - Slog.e(TAG, "Window Session Crash", e); - } - throw e; - } - } - - public void binderDied() { - // Note: it is safe to call in to the input method manager - // here because we are not holding our lock. - try { - if (mInputMethodManager != null) { - mInputMethodManager.removeClient(mClient); - } - } catch (RemoteException e) { - } - synchronized(mWindowMap) { - mClient.asBinder().unlinkToDeath(this, 0); - mClientDead = true; - killSessionLocked(); - } - } - - public int add(IWindow window, WindowManager.LayoutParams attrs, - int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) { - return addWindow(this, window, attrs, viewVisibility, outContentInsets, - outInputChannel); - } - - public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs, - int viewVisibility, Rect outContentInsets) { - return addWindow(this, window, attrs, viewVisibility, outContentInsets, null); - } - - public void remove(IWindow window) { - removeWindow(this, window); - } - - public int relayout(IWindow window, WindowManager.LayoutParams attrs, - int requestedWidth, int requestedHeight, int viewFlags, - boolean insetsPending, Rect outFrame, Rect outContentInsets, - Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { - //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); - int res = relayoutWindow(this, window, attrs, - requestedWidth, requestedHeight, viewFlags, insetsPending, - outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface); - //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); - return res; - } - - public void setTransparentRegion(IWindow window, Region region) { - setTransparentRegionWindow(this, window, region); - } - - public void setInsets(IWindow window, int touchableInsets, - Rect contentInsets, Rect visibleInsets, Region touchableArea) { - setInsetsWindow(this, window, touchableInsets, contentInsets, - visibleInsets, touchableArea); - } - - public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { - getWindowDisplayFrame(this, window, outDisplayFrame); - } - - public void finishDrawing(IWindow window) { - if (localLOGV) Slog.v( - TAG, "IWindow finishDrawing called for " + window); - finishDrawingWindow(this, window); - } - - public void setInTouchMode(boolean mode) { - synchronized(mWindowMap) { - mInTouchMode = mode; - } - } - - public boolean getInTouchMode() { - synchronized(mWindowMap) { - return mInTouchMode; - } - } - - public boolean performHapticFeedback(IWindow window, int effectId, - boolean always) { - synchronized(mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - return mPolicy.performHapticFeedbackLw( - windowForClientLocked(this, window, true), - effectId, always); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - /* Drag/drop */ - public IBinder prepareDrag(IWindow window, int flags, - int width, int height, Surface outSurface) { - return prepareDragSurface(window, mSurfaceSession, flags, - width, height, outSurface); - } - - public boolean performDrag(IWindow window, IBinder dragToken, - float touchX, float touchY, float thumbCenterX, float thumbCenterY, - ClipData data) { - if (DEBUG_DRAG) { - Slog.d(TAG, "perform drag: win=" + window + " data=" + data); - } - - synchronized (mWindowMap) { - if (mDragState == null) { - Slog.w(TAG, "No drag prepared"); - throw new IllegalStateException("performDrag() without prepareDrag()"); - } - - if (dragToken != mDragState.mToken) { - Slog.w(TAG, "Performing mismatched drag"); - throw new IllegalStateException("performDrag() does not match prepareDrag()"); - } - - WindowState callingWin = windowForClientLocked(null, window, false); - if (callingWin == null) { - Slog.w(TAG, "Bad requesting window " + window); - return false; // !!! TODO: throw here? - } - - // !!! TODO: if input is not still focused on the initiating window, fail - // the drag initiation (e.g. an alarm window popped up just as the application - // called performDrag() - - mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder()); - - // !!! TODO: extract the current touch (x, y) in screen coordinates. That - // will let us eliminate the (touchX,touchY) parameters from the API. - - // !!! FIXME: put all this heavy stuff onto the mH looper, as well as - // the actual drag event dispatch stuff in the dragstate - - mDragState.register(); - mInputMonitor.updateInputWindowsLw(true /*force*/); - if (!mInputManager.transferTouchFocus(callingWin.mInputChannel, - mDragState.mServerChannel)) { - Slog.e(TAG, "Unable to transfer touch focus"); - mDragState.unregister(); - mDragState = null; - mInputMonitor.updateInputWindowsLw(true /*force*/); - return false; - } - - mDragState.mData = data; - mDragState.mCurrentX = touchX; - mDragState.mCurrentY = touchY; - mDragState.broadcastDragStartedLw(touchX, touchY); - - // remember the thumb offsets for later - mDragState.mThumbOffsetX = thumbCenterX; - mDragState.mThumbOffsetY = thumbCenterY; - - // Make the surface visible at the proper location - final Surface surface = mDragState.mSurface; - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performDrag"); - Surface.openTransaction(); - try { - surface.setPosition((int)(touchX - thumbCenterX), - (int)(touchY - thumbCenterY)); - surface.setAlpha(.7071f); - surface.setLayer(mDragState.getDragLayerLw()); - surface.show(); - } finally { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performDrag"); - } - } - - return true; // success! - } - - public void reportDropResult(IWindow window, boolean consumed) { - IBinder token = window.asBinder(); - if (DEBUG_DRAG) { - Slog.d(TAG, "Drop result=" + consumed + " reported by " + token); - } - - synchronized (mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - if (mDragState == null || mDragState.mToken != token) { - Slog.w(TAG, "Invalid drop-result claim by " + window); - throw new IllegalStateException("reportDropResult() by non-recipient"); - } - - // The right window has responded, even if it's no longer around, - // so be sure to halt the timeout even if the later WindowState - // lookup fails. - mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder()); - WindowState callingWin = windowForClientLocked(null, window, false); - if (callingWin == null) { - Slog.w(TAG, "Bad result-reporting window " + window); - return; // !!! TODO: throw here? - } - - mDragState.mDragResult = consumed; - mDragState.endDragLw(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - public void dragRecipientEntered(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG, "Drag into new candidate view @ " + window.asBinder()); - } - } - - public void dragRecipientExited(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG, "Drag from old candidate view @ " + window.asBinder()); - } - } - - public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { - synchronized(mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - setWindowWallpaperPositionLocked( - windowForClientLocked(this, window, true), - x, y, xStep, yStep); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - public void wallpaperOffsetsComplete(IBinder window) { - WindowManagerService.this.wallpaperOffsetsComplete(window); - } - - public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, - int z, Bundle extras, boolean sync) { - synchronized(mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - return sendWindowWallpaperCommandLocked( - windowForClientLocked(this, window, true), - action, x, y, z, extras, sync); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - public void wallpaperCommandComplete(IBinder window, Bundle result) { - WindowManagerService.this.wallpaperCommandComplete(window, result); - } - - void windowAddedLocked() { - if (mSurfaceSession == null) { - if (localLOGV) Slog.v( - TAG, "First window added to " + this + ", creating SurfaceSession"); - mSurfaceSession = new SurfaceSession(); - if (SHOW_TRANSACTIONS) Slog.i( - TAG, " NEW SURFACE SESSION " + mSurfaceSession); - mSessions.add(this); - } - mNumWindow++; - } - - void windowRemovedLocked() { - mNumWindow--; - killSessionLocked(); - } - - void killSessionLocked() { - if (mNumWindow <= 0 && mClientDead) { - mSessions.remove(this); - if (mSurfaceSession != null) { - if (localLOGV) Slog.v( - TAG, "Last window removed from " + this - + ", destroying " + mSurfaceSession); - if (SHOW_TRANSACTIONS) Slog.i( - TAG, " KILL SURFACE SESSION " + mSurfaceSession); - try { - mSurfaceSession.kill(); - } catch (Exception e) { - Slog.w(TAG, "Exception thrown when killing surface session " - + mSurfaceSession + " in session " + this - + ": " + e.toString()); - } - mSurfaceSession = null; - } - } - } - - void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); - pw.print(" mClientDead="); pw.print(mClientDead); - pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); - } - - @Override - public String toString() { - return mStringName; - } - } - - // ------------------------------------------------------------- - // Client Window State - // ------------------------------------------------------------- - - private final class WindowState implements WindowManagerPolicy.WindowState { - final Session mSession; - final IWindow mClient; - WindowToken mToken; - WindowToken mRootToken; - AppWindowToken mAppToken; - AppWindowToken mTargetAppToken; - final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams(); - final DeathRecipient mDeathRecipient; - final WindowState mAttachedWindow; - final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>(); - final int mBaseLayer; - final int mSubLayer; - final boolean mLayoutAttached; - final boolean mIsImWindow; - final boolean mIsWallpaper; - final boolean mIsFloatingLayer; - int mViewVisibility; - boolean mPolicyVisibility = true; - boolean mPolicyVisibilityAfterAnim = true; - boolean mAppFreezing; - Surface mSurface; - boolean mReportDestroySurface; - boolean mSurfacePendingDestroy; - boolean mAttachedHidden; // is our parent window hidden? - boolean mLastHidden; // was this window last hidden? - boolean mWallpaperVisible; // for wallpaper, what was last vis report? - int mRequestedWidth; - int mRequestedHeight; - int mLastRequestedWidth; - int mLastRequestedHeight; - int mLayer; - int mAnimLayer; - int mLastLayer; - boolean mHaveFrame; - boolean mObscured; - boolean mTurnOnScreen; - - int mLayoutSeq = -1; - - Configuration mConfiguration = null; - - // Actual frame shown on-screen (may be modified by animation) - final Rect mShownFrame = new Rect(); - final Rect mLastShownFrame = new Rect(); - - /** - * Set when we have changed the size of the surface, to know that - * we must tell them application to resize (and thus redraw itself). - */ - boolean mSurfaceResized; - - /** - * Insets that determine the actually visible area - */ - final Rect mVisibleInsets = new Rect(); - final Rect mLastVisibleInsets = new Rect(); - boolean mVisibleInsetsChanged; - - /** - * Insets that are covered by system windows - */ - final Rect mContentInsets = new Rect(); - final Rect mLastContentInsets = new Rect(); - boolean mContentInsetsChanged; - - /** - * Set to true if we are waiting for this window to receive its - * given internal insets before laying out other windows based on it. - */ - boolean mGivenInsetsPending; - - /** - * These are the content insets that were given during layout for - * this window, to be applied to windows behind it. - */ - final Rect mGivenContentInsets = new Rect(); - - /** - * These are the visible insets that were given during layout for - * this window, to be applied to windows behind it. - */ - final Rect mGivenVisibleInsets = new Rect(); - - /** - * This is the given touchable area relative to the window frame, or null if none. - */ - final Region mGivenTouchableRegion = new Region(); - - /** - * Flag indicating whether the touchable region should be adjusted by - * the visible insets; if false the area outside the visible insets is - * NOT touchable, so we must use those to adjust the frame during hit - * tests. - */ - int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; - - // Current transformation being applied. - boolean mHaveMatrix; - float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1; - float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1; - float mHScale=1, mVScale=1; - float mLastHScale=1, mLastVScale=1; - final Matrix mTmpMatrix = new Matrix(); - - // "Real" frame that the application sees. - final Rect mFrame = new Rect(); - final Rect mLastFrame = new Rect(); - - final Rect mContainingFrame = new Rect(); - final Rect mDisplayFrame = new Rect(); - final Rect mContentFrame = new Rect(); - final Rect mParentFrame = new Rect(); - final Rect mVisibleFrame = new Rect(); - - boolean mContentChanged; - - float mShownAlpha = 1; - float mAlpha = 1; - float mLastAlpha = 1; - - // Set to true if, when the window gets displayed, it should perform - // an enter animation. - boolean mEnterAnimationPending; - - // Currently running animation. - boolean mAnimating; - boolean mLocalAnimating; - Animation mAnimation; - boolean mAnimationIsEntrance; - boolean mHasTransformation; - boolean mHasLocalTransformation; - final Transformation mTransformation = new Transformation(); - - // If a window showing a wallpaper: the requested offset for the - // wallpaper; if a wallpaper window: the currently applied offset. - float mWallpaperX = -1; - float mWallpaperY = -1; - - // If a window showing a wallpaper: what fraction of the offset - // range corresponds to a full virtual screen. - float mWallpaperXStep = -1; - float mWallpaperYStep = -1; - - // Wallpaper windows: pixels offset based on above variables. - int mXOffset; - int mYOffset; - - // This is set after IWindowSession.relayout() has been called at - // least once for the window. It allows us to detect the situation - // where we don't yet have a surface, but should have one soon, so - // we can give the window focus before waiting for the relayout. - boolean mRelayoutCalled; - - // This is set after the Surface has been created but before the - // window has been drawn. During this time the surface is hidden. - boolean mDrawPending; - - // This is set after the window has finished drawing for the first - // time but before its surface is shown. The surface will be - // displayed when the next layout is run. - boolean mCommitDrawPending; - - // This is set during the time after the window's drawing has been - // committed, and before its surface is actually shown. It is used - // to delay showing the surface until all windows in a token are ready - // to be shown. - boolean mReadyToShow; - - // Set when the window has been shown in the screen the first time. - boolean mHasDrawn; - - // Currently running an exit animation? - boolean mExiting; - - // Currently on the mDestroySurface list? - boolean mDestroying; - - // Completely remove from window manager after exit animation? - boolean mRemoveOnExit; - - // Set when the orientation is changing and this window has not yet - // been updated for the new orientation. - boolean mOrientationChanging; - - // Is this window now (or just being) removed? - boolean mRemoved; - - // Temp for keeping track of windows that have been removed when - // rebuilding window list. - boolean mRebuilding; - - // For debugging, this is the last information given to the surface flinger. - boolean mSurfaceShown; - int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH; - int mSurfaceLayer; - float mSurfaceAlpha; - - // Input channel and input window handle used by the input dispatcher. - InputWindowHandle mInputWindowHandle; - InputChannel mInputChannel; - - // Used to improve performance of toString() - String mStringNameCache; - CharSequence mLastTitle; - boolean mWasPaused; - - WindowState(Session s, IWindow c, WindowToken token, - WindowState attachedWindow, WindowManager.LayoutParams a, - int viewVisibility) { - mSession = s; - mClient = c; - mToken = token; - mAttrs.copyFrom(a); - mViewVisibility = viewVisibility; - DeathRecipient deathRecipient = new DeathRecipient(); - mAlpha = a.alpha; - if (localLOGV) Slog.v( - TAG, "Window " + this + " client=" + c.asBinder() - + " token=" + token + " (" + mAttrs.token + ")"); - try { - c.asBinder().linkToDeath(deathRecipient, 0); - } catch (RemoteException e) { - mDeathRecipient = null; - mAttachedWindow = null; - mLayoutAttached = false; - mIsImWindow = false; - mIsWallpaper = false; - mIsFloatingLayer = false; - mBaseLayer = 0; - mSubLayer = 0; - return; - } - mDeathRecipient = deathRecipient; - - if ((mAttrs.type >= FIRST_SUB_WINDOW && - mAttrs.type <= LAST_SUB_WINDOW)) { - // The multiplier here is to reserve space for multiple - // windows in the same type layer. - mBaseLayer = mPolicy.windowTypeToLayerLw( - attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; - mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type); - mAttachedWindow = attachedWindow; - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow); - mAttachedWindow.mChildWindows.add(this); - mLayoutAttached = mAttrs.type != - WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; - mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD - || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG; - mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER; - mIsFloatingLayer = mIsImWindow || mIsWallpaper; - } else { - // The multiplier here is to reserve space for multiple - // windows in the same type layer. - mBaseLayer = mPolicy.windowTypeToLayerLw(a.type) - * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; - mSubLayer = 0; - mAttachedWindow = null; - mLayoutAttached = false; - mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD - || mAttrs.type == TYPE_INPUT_METHOD_DIALOG; - mIsWallpaper = mAttrs.type == TYPE_WALLPAPER; - mIsFloatingLayer = mIsImWindow || mIsWallpaper; - } - - WindowState appWin = this; - while (appWin.mAttachedWindow != null) { - appWin = mAttachedWindow; - } - WindowToken appToken = appWin.mToken; - while (appToken.appWindowToken == null) { - WindowToken parent = mTokenMap.get(appToken.token); - if (parent == null || appToken == parent) { - break; - } - appToken = parent; - } - mRootToken = appToken; - mAppToken = appToken.appWindowToken; - - mSurface = null; - mRequestedWidth = 0; - mRequestedHeight = 0; - mLastRequestedWidth = 0; - mLastRequestedHeight = 0; - mXOffset = 0; - mYOffset = 0; - mLayer = 0; - mAnimLayer = 0; - mLastLayer = 0; - mInputWindowHandle = new InputWindowHandle( - mAppToken != null ? mAppToken.mInputApplicationHandle : null, this); - } - - void attach() { - if (localLOGV) Slog.v( - TAG, "Attaching " + this + " token=" + mToken - + ", list=" + mToken.windows); - mSession.windowAddedLocked(); - } - - public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { - mHaveFrame = true; - - final Rect container = mContainingFrame; - container.set(pf); - - final Rect display = mDisplayFrame; - display.set(df); - - if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) { - container.intersect(mCompatibleScreenFrame); - if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) { - display.intersect(mCompatibleScreenFrame); - } - } - - final int pw = container.right - container.left; - final int ph = container.bottom - container.top; - - int w,h; - if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) { - w = mAttrs.width < 0 ? pw : mAttrs.width; - h = mAttrs.height< 0 ? ph : mAttrs.height; - } else { - w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth; - h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight; - } - - if (!mParentFrame.equals(pf)) { - //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame - // + " to " + pf); - mParentFrame.set(pf); - mContentChanged = true; - } - - final Rect content = mContentFrame; - content.set(cf); - - final Rect visible = mVisibleFrame; - visible.set(vf); - - final Rect frame = mFrame; - final int fw = frame.width(); - final int fh = frame.height(); - - //System.out.println("In: w=" + w + " h=" + h + " container=" + - // container + " x=" + mAttrs.x + " y=" + mAttrs.y); - - Gravity.apply(mAttrs.gravity, w, h, container, - (int) (mAttrs.x + mAttrs.horizontalMargin * pw), - (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame); - - //System.out.println("Out: " + mFrame); - - // Now make sure the window fits in the overall display. - Gravity.applyDisplay(mAttrs.gravity, df, frame); - - // Make sure the content and visible frames are inside of the - // final window frame. - if (content.left < frame.left) content.left = frame.left; - if (content.top < frame.top) content.top = frame.top; - if (content.right > frame.right) content.right = frame.right; - if (content.bottom > frame.bottom) content.bottom = frame.bottom; - if (visible.left < frame.left) visible.left = frame.left; - if (visible.top < frame.top) visible.top = frame.top; - if (visible.right > frame.right) visible.right = frame.right; - if (visible.bottom > frame.bottom) visible.bottom = frame.bottom; - - final Rect contentInsets = mContentInsets; - contentInsets.left = content.left-frame.left; - contentInsets.top = content.top-frame.top; - contentInsets.right = frame.right-content.right; - contentInsets.bottom = frame.bottom-content.bottom; - - final Rect visibleInsets = mVisibleInsets; - visibleInsets.left = visible.left-frame.left; - visibleInsets.top = visible.top-frame.top; - visibleInsets.right = frame.right-visible.right; - visibleInsets.bottom = frame.bottom-visible.bottom; - - if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { - updateWallpaperOffsetLocked(this, mDisplay.getWidth(), - mDisplay.getHeight(), false); - } - - if (localLOGV) { - //if ("com.google.android.youtube".equals(mAttrs.packageName) - // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - Slog.v(TAG, "Resolving (mRequestedWidth=" - + mRequestedWidth + ", mRequestedheight=" - + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph - + "): frame=" + mFrame.toShortString() - + " ci=" + contentInsets.toShortString() - + " vi=" + visibleInsets.toShortString()); - //} - } - } - - public Rect getFrameLw() { - return mFrame; - } - - public Rect getShownFrameLw() { - return mShownFrame; - } - - public Rect getDisplayFrameLw() { - return mDisplayFrame; - } - - public Rect getContentFrameLw() { - return mContentFrame; - } - - public Rect getVisibleFrameLw() { - return mVisibleFrame; - } - - public boolean getGivenInsetsPendingLw() { - return mGivenInsetsPending; - } - - public Rect getGivenContentInsetsLw() { - return mGivenContentInsets; - } - - public Rect getGivenVisibleInsetsLw() { - return mGivenVisibleInsets; - } - - public WindowManager.LayoutParams getAttrs() { - return mAttrs; - } - - public int getSurfaceLayer() { - return mLayer; - } - - public IApplicationToken getAppToken() { - return mAppToken != null ? mAppToken.appToken : null; - } - - public long getInputDispatchingTimeoutNanos() { - return mAppToken != null - ? mAppToken.inputDispatchingTimeoutNanos - : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - } - - public boolean hasAppShownWindows() { - return mAppToken != null ? mAppToken.firstWindowDrawn : false; - } - - public void setAnimation(Animation anim) { - if (localLOGV) Slog.v( - TAG, "Setting animation in " + this + ": " + anim); - mAnimating = false; - mLocalAnimating = false; - mAnimation = anim; - mAnimation.restrictDuration(MAX_ANIMATION_DURATION); - mAnimation.scaleCurrentDuration(mWindowAnimationScale); - } - - public void clearAnimation() { - if (mAnimation != null) { - mAnimating = true; - mLocalAnimating = false; - mAnimation.cancel(); - mAnimation = null; - } - } - - Surface createSurfaceLocked() { - if (mSurface == null) { - mReportDestroySurface = false; - mSurfacePendingDestroy = false; - mDrawPending = true; - mCommitDrawPending = false; - mReadyToShow = false; - if (mAppToken != null) { - mAppToken.allDrawn = false; - } - - int flags = 0; - - if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) { - flags |= Surface.SECURE; - } - if (DEBUG_VISIBILITY) Slog.v( - TAG, "Creating surface in session " - + mSession.mSurfaceSession + " window " + this - + " w=" + mFrame.width() - + " h=" + mFrame.height() + " format=" - + mAttrs.format + " flags=" + flags); - - int w = mFrame.width(); - int h = mFrame.height(); - if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { - // for a scaled surface, we always want the requested - // size. - w = mRequestedWidth; - h = mRequestedHeight; - } - - // Something is wrong and SurfaceFlinger will not like this, - // try to revert to sane values - if (w <= 0) w = 1; - if (h <= 0) h = 1; - - mSurfaceShown = false; - mSurfaceLayer = 0; - mSurfaceAlpha = 1; - mSurfaceX = 0; - mSurfaceY = 0; - mSurfaceW = w; - mSurfaceH = h; - try { - final boolean isHwAccelerated = (mAttrs.flags & - WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; - final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format; - if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) { - flags |= Surface.OPAQUE; - } - mSurface = new Surface( - mSession.mSurfaceSession, mSession.mPid, - mAttrs.getTitle().toString(), - 0, w, h, format, flags); - if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE " - + mSurface + " IN SESSION " - + mSession.mSurfaceSession - + ": pid=" + mSession.mPid + " format=" - + mAttrs.format + " flags=0x" - + Integer.toHexString(flags) - + " / " + this); - } catch (Surface.OutOfResourcesException e) { - Slog.w(TAG, "OutOfResourcesException creating surface"); - reclaimSomeSurfaceMemoryLocked(this, "create"); - return null; - } catch (Exception e) { - Slog.e(TAG, "Exception creating surface", e); - return null; - } - - if (localLOGV) Slog.v( - TAG, "Got surface: " + mSurface - + ", set left=" + mFrame.left + " top=" + mFrame.top - + ", animLayer=" + mAnimLayer); - if (SHOW_TRANSACTIONS) { - Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); - logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" + - mFrame.width() + "x" + mFrame.height() + "), layer=" + - mAnimLayer + " HIDE", null); - } - Surface.openTransaction(); - try { - try { - mSurfaceX = mFrame.left + mXOffset; - mSurfaceY = mFrame.top + mYOffset; - mSurface.setPosition(mSurfaceX, mSurfaceY); - mSurfaceLayer = mAnimLayer; - mSurface.setLayer(mAnimLayer); - mSurfaceShown = false; - mSurface.hide(); - if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) { - if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null); - mSurface.setFlags(Surface.SURFACE_DITHER, - Surface.SURFACE_DITHER); - } - } catch (RuntimeException e) { - Slog.w(TAG, "Error creating surface in " + w, e); - reclaimSomeSurfaceMemoryLocked(this, "create-init"); - } - mLastHidden = true; - } finally { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked"); - } - if (localLOGV) Slog.v( - TAG, "Created surface " + this); - } - return mSurface; - } - - void destroySurfaceLocked() { - if (mAppToken != null && this == mAppToken.startingWindow) { - mAppToken.startingDisplayed = false; - } - - if (mSurface != null) { - mDrawPending = false; - mCommitDrawPending = false; - mReadyToShow = false; - - int i = mChildWindows.size(); - while (i > 0) { - i--; - WindowState c = mChildWindows.get(i); - c.mAttachedHidden = true; - } - - if (mReportDestroySurface) { - mReportDestroySurface = false; - mSurfacePendingDestroy = true; - try { - mClient.dispatchGetNewSurface(); - // We'll really destroy on the next time around. - return; - } catch (RemoteException e) { - } - } - - try { - if (DEBUG_VISIBILITY) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.w(TAG, "Window " + this + " destroying surface " - + mSurface + ", session " + mSession, e); - } - if (SHOW_TRANSACTIONS) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e); - } - mSurface.destroy(); - } catch (RuntimeException e) { - Slog.w(TAG, "Exception thrown when destroying Window " + this - + " surface " + mSurface + " session " + mSession - + ": " + e.toString()); - } - - mSurfaceShown = false; - mSurface = null; - } - } - - boolean finishDrawingLocked() { - if (mDrawPending) { - if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v( - TAG, "finishDrawingLocked: " + mSurface); - mCommitDrawPending = true; - mDrawPending = false; - return true; - } - return false; - } - - // This must be called while inside a transaction. - boolean commitFinishDrawingLocked(long currentTime) { - //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface); - if (!mCommitDrawPending) { - return false; - } - mCommitDrawPending = false; - mReadyToShow = true; - final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING; - final AppWindowToken atoken = mAppToken; - if (atoken == null || atoken.allDrawn || starting) { - performShowLocked(); - } - return true; - } - - // This must be called while inside a transaction. - boolean performShowLocked() { - if (DEBUG_VISIBILITY) { - RuntimeException e = null; - if (!HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } - Slog.v(TAG, "performShow on " + this - + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay() - + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e); - } - if (mReadyToShow && isReadyForDisplay()) { - if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this, - "SHOW (performShowLocked)", null); - if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this - + " during animation: policyVis=" + mPolicyVisibility - + " attHidden=" + mAttachedHidden - + " tok.hiddenRequested=" - + (mAppToken != null ? mAppToken.hiddenRequested : false) - + " tok.hidden=" - + (mAppToken != null ? mAppToken.hidden : false) - + " animating=" + mAnimating - + " tok animating=" - + (mAppToken != null ? mAppToken.animating : false)); - if (!showSurfaceRobustlyLocked(this)) { - return false; - } - mLastAlpha = -1; - mHasDrawn = true; - mLastHidden = false; - mReadyToShow = false; - enableScreenIfNeededLocked(); - - applyEnterAnimationLocked(this); - - int i = mChildWindows.size(); - while (i > 0) { - i--; - WindowState c = mChildWindows.get(i); - if (c.mAttachedHidden) { - c.mAttachedHidden = false; - if (c.mSurface != null) { - c.performShowLocked(); - // It hadn't been shown, which means layout not - // performed on it, so now we want to make sure to - // do a layout. If called from within the transaction - // loop, this will cause it to restart with a new - // layout. - mLayoutNeeded = true; - } - } - } - - if (mAttrs.type != TYPE_APPLICATION_STARTING - && mAppToken != null) { - mAppToken.firstWindowDrawn = true; - - if (mAppToken.startingData != null) { - if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, - "Finish starting " + mToken - + ": first real window is shown, no animation"); - // If this initial window is animating, stop it -- we - // will do an animation to reveal it from behind the - // starting window, so there is no need for it to also - // be doing its own stuff. - if (mAnimation != null) { - mAnimation.cancel(); - mAnimation = null; - // Make sure we clean up the animation. - mAnimating = true; - } - mFinishedStarting.add(mAppToken); - mH.sendEmptyMessage(H.FINISHED_STARTING); - } - mAppToken.updateReportedVisibilityLocked(); - } - } - return true; - } - - // This must be called while inside a transaction. Returns true if - // there is more animation to run. - boolean stepAnimationLocked(long currentTime, int dw, int dh) { - if (!mDisplayFrozen && mPolicy.isScreenOn()) { - // We will run animations as long as the display isn't frozen. - - if (!mDrawPending && !mCommitDrawPending && mAnimation != null) { - mHasTransformation = true; - mHasLocalTransformation = true; - if (!mLocalAnimating) { - if (DEBUG_ANIM) Slog.v( - TAG, "Starting animation in " + this + - " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() + - " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale); - mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh); - mAnimation.setStartTime(currentTime); - mLocalAnimating = true; - mAnimating = true; - } - mTransformation.clear(); - final boolean more = mAnimation.getTransformation( - currentTime, mTransformation); - if (DEBUG_ANIM) Slog.v( - TAG, "Stepped animation in " + this + - ": more=" + more + ", xform=" + mTransformation); - if (more) { - // we're not done! - return true; - } - if (DEBUG_ANIM) Slog.v( - TAG, "Finished animation in " + this + - " @ " + currentTime); - - if (mAnimation != null) { - mAnimation.cancel(); - mAnimation = null; - } - //WindowManagerService.this.dump(); - } - mHasLocalTransformation = false; - if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null - && mAppToken.animation != null) { - // When our app token is animating, we kind-of pretend like - // we are as well. Note the mLocalAnimating mAnimationIsEntrance - // part of this check means that we will only do this if - // our window is not currently exiting, or it is not - // locally animating itself. The idea being that one that - // is exiting and doing a local animation should be removed - // once that animation is done. - mAnimating = true; - mHasTransformation = true; - mTransformation.clear(); - return false; - } else if (mHasTransformation) { - // Little trick to get through the path below to act like - // we have finished an animation. - mAnimating = true; - } else if (isAnimating()) { - mAnimating = true; - } - } else if (mAnimation != null) { - // If the display is frozen, and there is a pending animation, - // clear it and make sure we run the cleanup code. - mAnimating = true; - mLocalAnimating = true; - mAnimation.cancel(); - mAnimation = null; - } - - if (!mAnimating && !mLocalAnimating) { - return false; - } - - if (DEBUG_ANIM) Slog.v( - TAG, "Animation done in " + this + ": exiting=" + mExiting - + ", reportedVisible=" - + (mAppToken != null ? mAppToken.reportedVisible : false)); - - mAnimating = false; - mLocalAnimating = false; - if (mAnimation != null) { - mAnimation.cancel(); - mAnimation = null; - } - mAnimLayer = mLayer; - if (mIsImWindow) { - mAnimLayer += mInputMethodAnimLayerAdjustment; - } else if (mIsWallpaper) { - mAnimLayer += mWallpaperAnimLayerAdjustment; - } - if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this - + " anim layer: " + mAnimLayer); - mHasTransformation = false; - mHasLocalTransformation = false; - if (mPolicyVisibility != mPolicyVisibilityAfterAnim) { - if (DEBUG_VISIBILITY) { - Slog.v(TAG, "Policy visibility changing after anim in " + this + ": " - + mPolicyVisibilityAfterAnim); - } - mPolicyVisibility = mPolicyVisibilityAfterAnim; - if (!mPolicyVisibility) { - if (mCurrentFocus == this) { - mFocusMayChange = true; - } - // Window is no longer visible -- make sure if we were waiting - // for it to be displayed before enabling the display, that - // we allow the display to be enabled now. - enableScreenIfNeededLocked(); - } - } - mTransformation.clear(); - if (mHasDrawn - && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING - && mAppToken != null - && mAppToken.firstWindowDrawn - && mAppToken.startingData != null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " - + mToken + ": first real window done animating"); - mFinishedStarting.add(mAppToken); - mH.sendEmptyMessage(H.FINISHED_STARTING); - } - - finishExit(); - - if (mAppToken != null) { - mAppToken.updateReportedVisibilityLocked(); - } - - return false; - } - - void finishExit() { - if (DEBUG_ANIM) Slog.v( - TAG, "finishExit in " + this - + ": exiting=" + mExiting - + " remove=" + mRemoveOnExit - + " windowAnimating=" + isWindowAnimating()); - - final int N = mChildWindows.size(); - for (int i=0; i<N; i++) { - mChildWindows.get(i).finishExit(); - } - - if (!mExiting) { - return; - } - - if (isWindowAnimating()) { - return; - } - - if (localLOGV) Slog.v( - TAG, "Exit animation finished in " + this - + ": remove=" + mRemoveOnExit); - if (mSurface != null) { - mDestroySurface.add(this); - mDestroying = true; - if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null); - mSurfaceShown = false; - try { - mSurface.hide(); - } catch (RuntimeException e) { - Slog.w(TAG, "Error hiding surface in " + this, e); - } - mLastHidden = true; - } - mExiting = false; - if (mRemoveOnExit) { - mPendingRemove.add(this); - mRemoveOnExit = false; - } - } - - boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - if (dsdx < .99999f || dsdx > 1.00001f) return false; - if (dtdy < .99999f || dtdy > 1.00001f) return false; - if (dtdx < -.000001f || dtdx > .000001f) return false; - if (dsdy < -.000001f || dsdy > .000001f) return false; - return true; - } - - void computeShownFrameLocked() { - final boolean selfTransformation = mHasLocalTransformation; - Transformation attachedTransformation = - (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation) - ? mAttachedWindow.mTransformation : null; - Transformation appTransformation = - (mAppToken != null && mAppToken.hasTransformation) - ? mAppToken.transformation : null; - - // Wallpapers are animated based on the "real" window they - // are currently targeting. - if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null - && mWallpaperTarget != null) { - if (mWallpaperTarget.mHasLocalTransformation && - mWallpaperTarget.mAnimation != null && - !mWallpaperTarget.mAnimation.getDetachWallpaper()) { - attachedTransformation = mWallpaperTarget.mTransformation; - if (DEBUG_WALLPAPER && attachedTransformation != null) { - Slog.v(TAG, "WP target attached xform: " + attachedTransformation); - } - } - if (mWallpaperTarget.mAppToken != null && - mWallpaperTarget.mAppToken.hasTransformation && - mWallpaperTarget.mAppToken.animation != null && - !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) { - appTransformation = mWallpaperTarget.mAppToken.transformation; - if (DEBUG_WALLPAPER && appTransformation != null) { - Slog.v(TAG, "WP target app xform: " + appTransformation); - } - } - } - - final boolean screenAnimation = mScreenRotationAnimation != null - && mScreenRotationAnimation.isAnimating(); - if (selfTransformation || attachedTransformation != null - || appTransformation != null || screenAnimation) { - // cache often used attributes locally - final Rect frame = mFrame; - final float tmpFloats[] = mTmpFloats; - final Matrix tmpMatrix = mTmpMatrix; - - // Compute the desired transformation. - tmpMatrix.setTranslate(0, 0); - if (selfTransformation) { - tmpMatrix.postConcat(mTransformation.getMatrix()); - } - tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset); - if (attachedTransformation != null) { - tmpMatrix.postConcat(attachedTransformation.getMatrix()); - } - if (appTransformation != null) { - tmpMatrix.postConcat(appTransformation.getMatrix()); - } - if (screenAnimation) { - tmpMatrix.postConcat( - mScreenRotationAnimation.getEnterTransformation().getMatrix()); - } - - // "convert" it into SurfaceFlinger's format - // (a 2x2 matrix + an offset) - // Here we must not transform the position of the surface - // since it is already included in the transformation. - //Slog.i(TAG, "Transform: " + matrix); - - mHaveMatrix = true; - tmpMatrix.getValues(tmpFloats); - mDsDx = tmpFloats[Matrix.MSCALE_X]; - mDtDx = tmpFloats[Matrix.MSKEW_Y]; - mDsDy = tmpFloats[Matrix.MSKEW_X]; - mDtDy = tmpFloats[Matrix.MSCALE_Y]; - int x = (int)tmpFloats[Matrix.MTRANS_X]; - int y = (int)tmpFloats[Matrix.MTRANS_Y]; - int w = frame.width(); - int h = frame.height(); - mShownFrame.set(x, y, x+w, y+h); - - // Now set the alpha... but because our current hardware - // can't do alpha transformation on a non-opaque surface, - // turn it off if we are running an animation that is also - // transforming since it is more important to have that - // animation be smooth. - mShownAlpha = mAlpha; - if (!mLimitedAlphaCompositing - || (!PixelFormat.formatHasAlpha(mAttrs.format) - || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) - && x == frame.left && y == frame.top))) { - //Slog.i(TAG, "Applying alpha transform"); - if (selfTransformation) { - mShownAlpha *= mTransformation.getAlpha(); - } - if (attachedTransformation != null) { - mShownAlpha *= attachedTransformation.getAlpha(); - } - if (appTransformation != null) { - mShownAlpha *= appTransformation.getAlpha(); - } - if (screenAnimation) { - mShownAlpha *= - mScreenRotationAnimation.getEnterTransformation().getAlpha(); - } - } else { - //Slog.i(TAG, "Not applying alpha transform"); - } - - if (localLOGV) Slog.v( - TAG, "Continuing animation in " + this + - ": " + mShownFrame + - ", alpha=" + mTransformation.getAlpha()); - return; - } - - mShownFrame.set(mFrame); - if (mXOffset != 0 || mYOffset != 0) { - mShownFrame.offset(mXOffset, mYOffset); - } - mShownAlpha = mAlpha; - mHaveMatrix = false; - mDsDx = 1; - mDtDx = 0; - mDsDy = 0; - mDtDy = 1; - } - - /** - * Is this window visible? It is not visible if there is no - * surface, or we are in the process of running an exit animation - * that will remove the surface, or its app token has been hidden. - */ - public boolean isVisibleLw() { - final AppWindowToken atoken = mAppToken; - return mSurface != null && mPolicyVisibility && !mAttachedHidden - && (atoken == null || !atoken.hiddenRequested) - && !mExiting && !mDestroying; - } - - /** - * Like {@link #isVisibleLw}, but also counts a window that is currently - * "hidden" behind the keyguard as visible. This allows us to apply - * things like window flags that impact the keyguard. - * XXX I am starting to think we need to have ANOTHER visibility flag - * for this "hidden behind keyguard" state rather than overloading - * mPolicyVisibility. Ungh. - */ - public boolean isVisibleOrBehindKeyguardLw() { - final AppWindowToken atoken = mAppToken; - return mSurface != null && !mAttachedHidden - && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) - && !mDrawPending && !mCommitDrawPending - && !mExiting && !mDestroying; - } - - /** - * Is this window visible, ignoring its app token? It is not visible - * if there is no surface, or we are in the process of running an exit animation - * that will remove the surface. - */ - public boolean isWinVisibleLw() { - final AppWindowToken atoken = mAppToken; - return mSurface != null && mPolicyVisibility && !mAttachedHidden - && (atoken == null || !atoken.hiddenRequested || atoken.animating) - && !mExiting && !mDestroying; - } - - /** - * The same as isVisible(), but follows the current hidden state of - * the associated app token, not the pending requested hidden state. - */ - boolean isVisibleNow() { - return mSurface != null && mPolicyVisibility && !mAttachedHidden - && !mRootToken.hidden && !mExiting && !mDestroying; - } - - /** - * Can this window possibly be a drag/drop target? The test here is - * a combination of the above "visible now" with the check that the - * Input Manager uses when discarding windows from input consideration. - */ - boolean isPotentialDragTarget() { - return isVisibleNow() && (mInputChannel != null) && !mRemoved; - } - - /** - * Same as isVisible(), but we also count it as visible between the - * call to IWindowSession.add() and the first relayout(). - */ - boolean isVisibleOrAdding() { - final AppWindowToken atoken = mAppToken; - return ((mSurface != null && !mReportDestroySurface) - || (!mRelayoutCalled && mViewVisibility == View.VISIBLE)) - && mPolicyVisibility && !mAttachedHidden - && (atoken == null || !atoken.hiddenRequested) - && !mExiting && !mDestroying; - } - - /** - * Is this window currently on-screen? It is on-screen either if it - * is visible or it is currently running an animation before no longer - * being visible. - */ - boolean isOnScreen() { - final AppWindowToken atoken = mAppToken; - if (atoken != null) { - return mSurface != null && mPolicyVisibility && !mDestroying - && ((!mAttachedHidden && !atoken.hiddenRequested) - || mAnimation != null || atoken.animation != null); - } else { - return mSurface != null && mPolicyVisibility && !mDestroying - && (!mAttachedHidden || mAnimation != null); - } - } - - /** - * Like isOnScreen(), but we don't return true if the window is part - * of a transition that has not yet been started. - */ - boolean isReadyForDisplay() { - if (mRootToken.waitingToShow && - mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - return false; - } - final AppWindowToken atoken = mAppToken; - final boolean animating = atoken != null - ? (atoken.animation != null) : false; - return mSurface != null && mPolicyVisibility && !mDestroying - && ((!mAttachedHidden && mViewVisibility == View.VISIBLE - && !mRootToken.hidden) - || mAnimation != null || animating); - } - - /** Is the window or its container currently animating? */ - boolean isAnimating() { - final WindowState attached = mAttachedWindow; - final AppWindowToken atoken = mAppToken; - return mAnimation != null - || (attached != null && attached.mAnimation != null) - || (atoken != null && - (atoken.animation != null - || atoken.inPendingTransaction)); - } - - /** Is this window currently animating? */ - boolean isWindowAnimating() { - return mAnimation != null; - } - - /** - * Like isOnScreen, but returns false if the surface hasn't yet - * been drawn. - */ - public boolean isDisplayedLw() { - final AppWindowToken atoken = mAppToken; - return mSurface != null && mPolicyVisibility && !mDestroying - && !mDrawPending && !mCommitDrawPending - && ((!mAttachedHidden && - (atoken == null || !atoken.hiddenRequested)) - || mAnimating); - } - - /** - * Returns true if the window has a surface that it has drawn a - * complete UI in to. - */ - public boolean isDrawnLw() { - final AppWindowToken atoken = mAppToken; - return mSurface != null && !mDestroying - && !mDrawPending && !mCommitDrawPending; - } - - /** - * Return true if the window is opaque and fully drawn. This indicates - * it may obscure windows behind it. - */ - boolean isOpaqueDrawn() { - return (mAttrs.format == PixelFormat.OPAQUE - || mAttrs.type == TYPE_WALLPAPER) - && mSurface != null && mAnimation == null - && (mAppToken == null || mAppToken.animation == null) - && !mDrawPending && !mCommitDrawPending; - } - - /** - * Return whether this window is wanting to have a translation - * animation applied to it for an in-progress move. (Only makes - * sense to call from performLayoutAndPlaceSurfacesLockedInner().) - */ - boolean shouldAnimateMove() { - return mContentChanged && !mExiting && !mLastHidden && !mDisplayFrozen - && (mFrame.top != mLastFrame.top - || mFrame.left != mLastFrame.left) - && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove()) - && mPolicy.isScreenOn(); - } - - boolean needsBackgroundFiller(int screenWidth, int screenHeight) { - return - // only if the application is requesting compatible window - (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 && - // only if it's visible - mHasDrawn && mViewVisibility == View.VISIBLE && - // and only if the application fills the compatible screen - mFrame.left <= mCompatibleScreenFrame.left && - mFrame.top <= mCompatibleScreenFrame.top && - mFrame.right >= mCompatibleScreenFrame.right && - mFrame.bottom >= mCompatibleScreenFrame.bottom; - } - - boolean isFullscreen(int screenWidth, int screenHeight) { - return mFrame.left <= 0 && mFrame.top <= 0 && - mFrame.right >= screenWidth && mFrame.bottom >= screenHeight; - } - - void removeLocked() { - disposeInputChannel(); - - if (mAttachedWindow != null) { - if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow); - mAttachedWindow.mChildWindows.remove(this); - } - destroySurfaceLocked(); - mSession.windowRemovedLocked(); - try { - mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); - } catch (RuntimeException e) { - // Ignore if it has already been removed (usually because - // we are doing this as part of processing a death note.) - } - } - - void disposeInputChannel() { - if (mInputChannel != null) { - mInputManager.unregisterInputChannel(mInputChannel); - - mInputChannel.dispose(); - mInputChannel = null; - } - } - - private class DeathRecipient implements IBinder.DeathRecipient { - public void binderDied() { - try { - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(mSession, mClient, false); - Slog.i(TAG, "WIN DEATH: " + win); - if (win != null) { - removeWindowLocked(mSession, win); - } - } - } catch (IllegalArgumentException ex) { - // This will happen if the window has already been - // removed. - } - } - } - - /** Returns true if this window desires key events. */ - public final boolean canReceiveKeys() { - return isVisibleOrAdding() - && (mViewVisibility == View.VISIBLE) - && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0); - } - - public boolean hasDrawnLw() { - return mHasDrawn; - } - - public boolean showLw(boolean doAnimation) { - return showLw(doAnimation, true); - } - - boolean showLw(boolean doAnimation, boolean requestAnim) { - if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { - return false; - } - if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this); - if (doAnimation) { - if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" - + mPolicyVisibility + " mAnimation=" + mAnimation); - if (mDisplayFrozen || !mPolicy.isScreenOn()) { - doAnimation = false; - } else if (mPolicyVisibility && mAnimation == null) { - // Check for the case where we are currently visible and - // not animating; we do not want to do animation at such a - // point to become visible when we already are. - doAnimation = false; - } - } - mPolicyVisibility = true; - mPolicyVisibilityAfterAnim = true; - if (doAnimation) { - applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); - } - if (requestAnim) { - requestAnimationLocked(0); - } - return true; - } - - public boolean hideLw(boolean doAnimation) { - return hideLw(doAnimation, true); - } - - boolean hideLw(boolean doAnimation, boolean requestAnim) { - if (doAnimation) { - if (mDisplayFrozen || !mPolicy.isScreenOn()) { - doAnimation = false; - } - } - boolean current = doAnimation ? mPolicyVisibilityAfterAnim - : mPolicyVisibility; - if (!current) { - return false; - } - if (doAnimation) { - applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false); - if (mAnimation == null) { - doAnimation = false; - } - } - if (doAnimation) { - mPolicyVisibilityAfterAnim = false; - } else { - if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this); - mPolicyVisibilityAfterAnim = false; - mPolicyVisibility = false; - // Window is no longer visible -- make sure if we were waiting - // for it to be displayed before enabling the display, that - // we allow the display to be enabled now. - enableScreenIfNeededLocked(); - if (mCurrentFocus == this) { - mFocusMayChange = true; - } - } - if (requestAnim) { - requestAnimationLocked(0); - } - return true; - } - - public void getTouchableRegion(Region outRegion) { - final Rect frame = mFrame; - switch (mTouchableInsets) { - default: - case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME: - outRegion.set(frame); - break; - case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: { - final Rect inset = mGivenContentInsets; - outRegion.set( - frame.left + inset.left, frame.top + inset.top, - frame.right - inset.right, frame.bottom - inset.bottom); - break; - } - case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: { - final Rect inset = mGivenVisibleInsets; - outRegion.set( - frame.left + inset.left, frame.top + inset.top, - frame.right - inset.right, frame.bottom - inset.bottom); - break; - } - case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: { - final Region givenTouchableRegion = mGivenTouchableRegion; - outRegion.set(givenTouchableRegion); - outRegion.translate(frame.left, frame.top); - break; - } - } - } - - void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("mSession="); pw.print(mSession); - pw.print(" mClient="); pw.println(mClient.asBinder()); - pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); - if (mAttachedWindow != null || mLayoutAttached) { - pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow); - pw.print(" mLayoutAttached="); pw.println(mLayoutAttached); - } - if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { - pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); - pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); - pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); - pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); - } - pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); - pw.print(" mSubLayer="); pw.print(mSubLayer); - pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+"); - pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment - : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))); - pw.print("="); pw.print(mAnimLayer); - pw.print(" mLastLayer="); pw.println(mLastLayer); - if (mSurface != null) { - pw.print(prefix); pw.print("mSurface="); pw.println(mSurface); - pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown); - pw.print(" layer="); pw.print(mSurfaceLayer); - pw.print(" alpha="); pw.print(mSurfaceAlpha); - pw.print(" rect=("); pw.print(mSurfaceX); - pw.print(","); pw.print(mSurfaceY); - pw.print(") "); pw.print(mSurfaceW); - pw.print(" x "); pw.println(mSurfaceH); - } - pw.print(prefix); pw.print("mToken="); pw.println(mToken); - pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); - if (mAppToken != null) { - pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); - } - if (mTargetAppToken != null) { - pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken); - } - pw.print(prefix); pw.print("mViewVisibility=0x"); - pw.print(Integer.toHexString(mViewVisibility)); - pw.print(" mLastHidden="); pw.print(mLastHidden); - pw.print(" mHaveFrame="); pw.print(mHaveFrame); - pw.print(" mObscured="); pw.println(mObscured); - if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) { - pw.print(prefix); pw.print("mPolicyVisibility="); - pw.print(mPolicyVisibility); - pw.print(" mPolicyVisibilityAfterAnim="); - pw.print(mPolicyVisibilityAfterAnim); - pw.print(" mAttachedHidden="); pw.println(mAttachedHidden); - } - if (!mRelayoutCalled) { - pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled); - } - pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); - pw.print(" h="); pw.print(mRequestedHeight); - pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); - if (mXOffset != 0 || mYOffset != 0) { - pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); - pw.print(" y="); pw.println(mYOffset); - } - pw.print(prefix); pw.print("mGivenContentInsets="); - mGivenContentInsets.printShortString(pw); - pw.print(" mGivenVisibleInsets="); - mGivenVisibleInsets.printShortString(pw); - pw.println(); - if (mTouchableInsets != 0 || mGivenInsetsPending) { - pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets); - pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending); - } - pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration); - pw.print(prefix); pw.print("mShownFrame="); - mShownFrame.printShortString(pw); - pw.print(" last="); mLastShownFrame.printShortString(pw); - pw.println(); - pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); - pw.print(" last="); mLastFrame.printShortString(pw); - pw.println(); - pw.print(prefix); pw.print("mContainingFrame="); - mContainingFrame.printShortString(pw); - pw.print(" mParentFrame="); - mParentFrame.printShortString(pw); - pw.print(" mDisplayFrame="); - mDisplayFrame.printShortString(pw); - pw.println(); - pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw); - pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw); - pw.println(); - pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw); - pw.print(" last="); mLastContentInsets.printShortString(pw); - pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw); - pw.print(" last="); mLastVisibleInsets.printShortString(pw); - pw.println(); - if (mAnimating || mLocalAnimating || mAnimationIsEntrance - || mAnimation != null) { - pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating); - pw.print(" mLocalAnimating="); pw.print(mLocalAnimating); - pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance); - pw.print(" mAnimation="); pw.println(mAnimation); - } - if (mHasTransformation || mHasLocalTransformation) { - pw.print(prefix); pw.print("XForm: has="); - pw.print(mHasTransformation); - pw.print(" hasLocal="); pw.print(mHasLocalTransformation); - pw.print(" "); mTransformation.printShortString(pw); - pw.println(); - } - if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { - pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); - pw.print(" mAlpha="); pw.print(mAlpha); - pw.print(" mLastAlpha="); pw.println(mLastAlpha); - } - if (mHaveMatrix) { - pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx); - pw.print(" mDtDx="); pw.print(mDtDx); - pw.print(" mDsDy="); pw.print(mDsDy); - pw.print(" mDtDy="); pw.println(mDtDy); - } - pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending); - pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending); - pw.print(" mReadyToShow="); pw.print(mReadyToShow); - pw.print(" mHasDrawn="); pw.println(mHasDrawn); - if (mExiting || mRemoveOnExit || mDestroying || mRemoved) { - pw.print(prefix); pw.print("mExiting="); pw.print(mExiting); - pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit); - pw.print(" mDestroying="); pw.print(mDestroying); - pw.print(" mRemoved="); pw.println(mRemoved); - } - if (mOrientationChanging || mAppFreezing || mTurnOnScreen) { - pw.print(prefix); pw.print("mOrientationChanging="); - pw.print(mOrientationChanging); - pw.print(" mAppFreezing="); pw.print(mAppFreezing); - pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen); - } - if (mHScale != 1 || mVScale != 1) { - pw.print(prefix); pw.print("mHScale="); pw.print(mHScale); - pw.print(" mVScale="); pw.println(mVScale); - } - if (mWallpaperX != -1 || mWallpaperY != -1) { - pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX); - pw.print(" mWallpaperY="); pw.println(mWallpaperY); - } - if (mWallpaperXStep != -1 || mWallpaperYStep != -1) { - pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep); - pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep); - } - } - - String makeInputChannelName() { - return Integer.toHexString(System.identityHashCode(this)) - + " " + mAttrs.getTitle(); - } - - @Override - public String toString() { - if (mStringNameCache == null || mLastTitle != mAttrs.getTitle() - || mWasPaused != mToken.paused) { - mLastTitle = mAttrs.getTitle(); - mWasPaused = mToken.paused; - mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this)) - + " " + mLastTitle + " paused=" + mWasPaused + "}"; - } - return mStringNameCache; - } - } - - // ------------------------------------------------------------- - // Window Token State - // ------------------------------------------------------------- - - class WindowToken { - // The actual token. - final IBinder token; - - // The type of window this token is for, as per WindowManager.LayoutParams. - final int windowType; - - // Set if this token was explicitly added by a client, so should - // not be removed when all windows are removed. - final boolean explicit; - - // For printing. - String stringName; - - // If this is an AppWindowToken, this is non-null. - AppWindowToken appWindowToken; - - // All of the windows associated with this token. - final ArrayList<WindowState> windows = new ArrayList<WindowState>(); - - // Is key dispatching paused for this token? - boolean paused = false; - - // Should this token's windows be hidden? - boolean hidden; - - // Temporary for finding which tokens no longer have visible windows. - boolean hasVisible; - - // Set to true when this token is in a pending transaction where it - // will be shown. - boolean waitingToShow; - - // Set to true when this token is in a pending transaction where it - // will be hidden. - boolean waitingToHide; - - // Set to true when this token is in a pending transaction where its - // windows will be put to the bottom of the list. - boolean sendingToBottom; - - // Set to true when this token is in a pending transaction where its - // windows will be put to the top of the list. - boolean sendingToTop; - - WindowToken(IBinder _token, int type, boolean _explicit) { - token = _token; - windowType = type; - explicit = _explicit; - } - - void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("token="); pw.println(token); - pw.print(prefix); pw.print("windows="); pw.println(windows); - pw.print(prefix); pw.print("windowType="); pw.print(windowType); - pw.print(" hidden="); pw.print(hidden); - pw.print(" hasVisible="); pw.println(hasVisible); - if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) { - pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow); - pw.print(" waitingToHide="); pw.print(waitingToHide); - pw.print(" sendingToBottom="); pw.print(sendingToBottom); - pw.print(" sendingToTop="); pw.println(sendingToTop); - } - } - - @Override - public String toString() { - if (stringName == null) { - StringBuilder sb = new StringBuilder(); - sb.append("WindowToken{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" token="); sb.append(token); sb.append('}'); - stringName = sb.toString(); - } - return stringName; - } - }; - - class AppWindowToken extends WindowToken { - // Non-null only for application tokens. - final IApplicationToken appToken; - - // All of the windows and child windows that are included in this - // application token. Note this list is NOT sorted! - final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>(); - - int groupId = -1; - boolean appFullscreen; - int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; - - // The input dispatching timeout for this application token in nanoseconds. - long inputDispatchingTimeoutNanos; - - // These are used for determining when all windows associated with - // an activity have been drawn, so they can be made visible together - // at the same time. - int lastTransactionSequence = mTransactionSequence-1; - int numInterestingWindows; - int numDrawnWindows; - boolean inPendingTransaction; - boolean allDrawn; - - // Is this token going to be hidden in a little while? If so, it - // won't be taken into account for setting the screen orientation. - boolean willBeHidden; - - // Is this window's surface needed? This is almost like hidden, except - // it will sometimes be true a little earlier: when the token has - // been shown, but is still waiting for its app transition to execute - // before making its windows shown. - boolean hiddenRequested; - - // Have we told the window clients to hide themselves? - boolean clientHidden; - - // Last visibility state we reported to the app token. - boolean reportedVisible; - - // Set to true when the token has been removed from the window mgr. - boolean removed; - - // Have we been asked to have this token keep the screen frozen? - boolean freezingScreen; - - boolean animating; - Animation animation; - boolean hasTransformation; - final Transformation transformation = new Transformation(); - - // Offset to the window of all layers in the token, for use by - // AppWindowToken animations. - int animLayerAdjustment; - - // Information about an application starting window if displayed. - StartingData startingData; - WindowState startingWindow; - View startingView; - boolean startingDisplayed; - boolean startingMoved; - boolean firstWindowDrawn; - - // Input application handle used by the input dispatcher. - InputApplicationHandle mInputApplicationHandle; - - AppWindowToken(IApplicationToken _token) { - super(_token.asBinder(), - WindowManager.LayoutParams.TYPE_APPLICATION, true); - appWindowToken = this; - appToken = _token; - mInputApplicationHandle = new InputApplicationHandle(this); - } - - public void setAnimation(Animation anim) { - if (localLOGV) Slog.v( - TAG, "Setting animation in " + this + ": " + anim); - animation = anim; - animating = false; - anim.restrictDuration(MAX_ANIMATION_DURATION); - anim.scaleCurrentDuration(mTransitionAnimationScale); - int zorder = anim.getZAdjustment(); - int adj = 0; - if (zorder == Animation.ZORDER_TOP) { - adj = TYPE_LAYER_OFFSET; - } else if (zorder == Animation.ZORDER_BOTTOM) { - adj = -TYPE_LAYER_OFFSET; - } - - if (animLayerAdjustment != adj) { - animLayerAdjustment = adj; - updateLayers(); - } - } - - public void setDummyAnimation() { - if (animation == null) { - if (localLOGV) Slog.v( - TAG, "Setting dummy animation in " + this); - animation = sDummyAnimation; - } - } - - public void clearAnimation() { - if (animation != null) { - animation = null; - animating = true; - } - } - - void updateLayers() { - final int N = allAppWindows.size(); - final int adj = animLayerAdjustment; - for (int i=0; i<N; i++) { - WindowState w = allAppWindows.get(i); - w.mAnimLayer = w.mLayer + adj; - if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " - + w.mAnimLayer); - if (w == mInputMethodTarget && !mInputMethodTargetWaitingAnim) { - setInputMethodAnimLayerAdjustment(adj); - } - if (w == mWallpaperTarget && mLowerWallpaperTarget == null) { - setWallpaperAnimLayerAdjustmentLocked(adj); - } - } - } - - void sendAppVisibilityToClients() { - final int N = allAppWindows.size(); - for (int i=0; i<N; i++) { - WindowState win = allAppWindows.get(i); - if (win == startingWindow && clientHidden) { - // Don't hide the starting window. - continue; - } - try { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "Setting visibility of " + win + ": " + (!clientHidden)); - win.mClient.dispatchAppVisibility(!clientHidden); - } catch (RemoteException e) { - } - } - } - - void showAllWindowsLocked() { - final int NW = allAppWindows.size(); - for (int i=0; i<NW; i++) { - WindowState w = allAppWindows.get(i); - if (DEBUG_VISIBILITY) Slog.v(TAG, - "performing show on: " + w); - w.performShowLocked(); - } - } - - // This must be called while inside a transaction. - boolean stepAnimationLocked(long currentTime, int dw, int dh) { - if (!mDisplayFrozen && mPolicy.isScreenOn()) { - // We will run animations as long as the display isn't frozen. - - if (animation == sDummyAnimation) { - // This guy is going to animate, but not yet. For now count - // it as not animating for purposes of scheduling transactions; - // when it is really time to animate, this will be set to - // a real animation and the next call will execute normally. - return false; - } - - if ((allDrawn || animating || startingDisplayed) && animation != null) { - if (!animating) { - if (DEBUG_ANIM) Slog.v( - TAG, "Starting animation in " + this + - " @ " + currentTime + ": dw=" + dw + " dh=" + dh - + " scale=" + mTransitionAnimationScale - + " allDrawn=" + allDrawn + " animating=" + animating); - animation.initialize(dw, dh, dw, dh); - animation.setStartTime(currentTime); - animating = true; - } - transformation.clear(); - final boolean more = animation.getTransformation( - currentTime, transformation); - if (DEBUG_ANIM) Slog.v( - TAG, "Stepped animation in " + this + - ": more=" + more + ", xform=" + transformation); - if (more) { - // we're done! - hasTransformation = true; - return true; - } - if (DEBUG_ANIM) Slog.v( - TAG, "Finished animation in " + this + - " @ " + currentTime); - animation = null; - } - } else if (animation != null) { - // If the display is frozen, and there is a pending animation, - // clear it and make sure we run the cleanup code. - animating = true; - animation = null; - } - - hasTransformation = false; - - if (!animating) { - return false; - } - - clearAnimation(); - animating = false; - if (animLayerAdjustment != 0) { - animLayerAdjustment = 0; - updateLayers(); - } - if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) { - moveInputMethodWindowsIfNeededLocked(true); - } - - if (DEBUG_ANIM) Slog.v( - TAG, "Animation done in " + this - + ": reportedVisible=" + reportedVisible); - - transformation.clear(); - - final int N = windows.size(); - for (int i=0; i<N; i++) { - windows.get(i).finishExit(); - } - updateReportedVisibilityLocked(); - - return false; - } - - void updateReportedVisibilityLocked() { - if (appToken == null) { - return; - } - - int numInteresting = 0; - int numVisible = 0; - boolean nowGone = true; - - if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this); - final int N = allAppWindows.size(); - for (int i=0; i<N; i++) { - WindowState win = allAppWindows.get(i); - if (win == startingWindow || win.mAppFreezing - || win.mViewVisibility != View.VISIBLE - || win.mAttrs.type == TYPE_APPLICATION_STARTING - || win.mDestroying) { - continue; - } - if (DEBUG_VISIBILITY) { - Slog.v(TAG, "Win " + win + ": isDrawn=" - + win.isDrawnLw() - + ", isAnimating=" + win.isAnimating()); - if (!win.isDrawnLw()) { - Slog.v(TAG, "Not displayed: s=" + win.mSurface - + " pv=" + win.mPolicyVisibility - + " dp=" + win.mDrawPending - + " cdp=" + win.mCommitDrawPending - + " ah=" + win.mAttachedHidden - + " th=" - + (win.mAppToken != null - ? win.mAppToken.hiddenRequested : false) - + " a=" + win.mAnimating); - } - } - numInteresting++; - if (win.isDrawnLw()) { - if (!win.isAnimating()) { - numVisible++; - } - nowGone = false; - } else if (win.isAnimating()) { - nowGone = false; - } - } - - boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting; - if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting=" - + numInteresting + " visible=" + numVisible); - if (nowVisible != reportedVisible) { - if (DEBUG_VISIBILITY) Slog.v( - TAG, "Visibility changed in " + this - + ": vis=" + nowVisible); - reportedVisible = nowVisible; - Message m = mH.obtainMessage( - H.REPORT_APPLICATION_TOKEN_WINDOWS, - nowVisible ? 1 : 0, - nowGone ? 1 : 0, - this); - mH.sendMessage(m); - } - } - - WindowState findMainWindow() { - int j = windows.size(); - while (j > 0) { - j--; - WindowState win = windows.get(j); - if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION - || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { - return win; - } - } - return null; - } - - void dump(PrintWriter pw, String prefix) { - super.dump(pw, prefix); - if (appToken != null) { - pw.print(prefix); pw.println("app=true"); - } - if (allAppWindows.size() > 0) { - pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); - } - pw.print(prefix); pw.print("groupId="); pw.print(groupId); - pw.print(" appFullscreen="); pw.print(appFullscreen); - pw.print(" requestedOrientation="); pw.println(requestedOrientation); - pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); - pw.print(" clientHidden="); pw.print(clientHidden); - pw.print(" willBeHidden="); pw.print(willBeHidden); - pw.print(" reportedVisible="); pw.println(reportedVisible); - if (paused || freezingScreen) { - pw.print(prefix); pw.print("paused="); pw.print(paused); - pw.print(" freezingScreen="); pw.println(freezingScreen); - } - if (numInterestingWindows != 0 || numDrawnWindows != 0 - || inPendingTransaction || allDrawn) { - pw.print(prefix); pw.print("numInterestingWindows="); - pw.print(numInterestingWindows); - pw.print(" numDrawnWindows="); pw.print(numDrawnWindows); - pw.print(" inPendingTransaction="); pw.print(inPendingTransaction); - pw.print(" allDrawn="); pw.println(allDrawn); - } - if (animating || animation != null) { - pw.print(prefix); pw.print("animating="); pw.print(animating); - pw.print(" animation="); pw.println(animation); - } - if (hasTransformation) { - pw.print(prefix); pw.print("XForm: "); - transformation.printShortString(pw); - pw.println(); - } - if (animLayerAdjustment != 0) { - pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment); - } - if (startingData != null || removed || firstWindowDrawn) { - pw.print(prefix); pw.print("startingData="); pw.print(startingData); - pw.print(" removed="); pw.print(removed); - pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn); - } - if (startingWindow != null || startingView != null - || startingDisplayed || startingMoved) { - pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); - pw.print(" startingView="); pw.print(startingView); - pw.print(" startingDisplayed="); pw.print(startingDisplayed); - pw.print(" startingMoved"); pw.println(startingMoved); - } - } - - @Override - public String toString() { - if (stringName == null) { - StringBuilder sb = new StringBuilder(); - sb.append("AppWindowToken{"); - sb.append(Integer.toHexString(System.identityHashCode(this))); - sb.append(" token="); sb.append(token); sb.append('}'); - stringName = sb.toString(); - } - return stringName; - } - } - - // ------------------------------------------------------------- - // DummyAnimation - // ------------------------------------------------------------- - - // This is an animation that does nothing: it just immediately finishes - // itself every time it is called. It is used as a stub animation in cases - // where we want to synchronize multiple things that may be animating. - static final class DummyAnimation extends Animation { - public boolean getTransformation(long currentTime, Transformation outTransformation) { - return false; - } - } - static final Animation sDummyAnimation = new DummyAnimation(); - - // ------------------------------------------------------------- - // Async Handler - // ------------------------------------------------------------- - - static final class StartingData { - final String pkg; - final int theme; - final CharSequence nonLocalizedLabel; - final int labelRes; - final int icon; - final int windowFlags; - - StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel, - int _labelRes, int _icon, int _windowFlags) { - pkg = _pkg; - theme = _theme; - nonLocalizedLabel = _nonLocalizedLabel; - labelRes = _labelRes; - icon = _icon; - windowFlags = _windowFlags; - } - } - - private final class H extends Handler { - public static final int REPORT_FOCUS_CHANGE = 2; - public static final int REPORT_LOSING_FOCUS = 3; - public static final int ANIMATE = 4; - public static final int ADD_STARTING = 5; - public static final int REMOVE_STARTING = 6; - public static final int FINISHED_STARTING = 7; - public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8; - public static final int WINDOW_FREEZE_TIMEOUT = 11; - public static final int HOLD_SCREEN_CHANGED = 12; - public static final int APP_TRANSITION_TIMEOUT = 13; - public static final int PERSIST_ANIMATION_SCALE = 14; - public static final int FORCE_GC = 15; - public static final int ENABLE_SCREEN = 16; - public static final int APP_FREEZE_TIMEOUT = 17; - public static final int SEND_NEW_CONFIGURATION = 18; - public static final int REPORT_WINDOWS_CHANGE = 19; - public static final int DRAG_START_TIMEOUT = 20; - public static final int DRAG_END_TIMEOUT = 21; - public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; - - private Session mLastReportedHold; - - public H() { - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case REPORT_FOCUS_CHANGE: { - WindowState lastFocus; - WindowState newFocus; - - synchronized(mWindowMap) { - lastFocus = mLastFocus; - newFocus = mCurrentFocus; - if (lastFocus == newFocus) { - // Focus is not changing, so nothing to do. - return; - } - mLastFocus = newFocus; - //Slog.i(TAG, "Focus moving from " + lastFocus - // + " to " + newFocus); - if (newFocus != null && lastFocus != null - && !newFocus.isDisplayedLw()) { - //Slog.i(TAG, "Delaying loss of focus..."); - mLosingFocus.add(lastFocus); - lastFocus = null; - } - } - - if (lastFocus != newFocus) { - //System.out.println("Changing focus from " + lastFocus - // + " to " + newFocus); - if (newFocus != null) { - try { - //Slog.i(TAG, "Gaining focus: " + newFocus); - newFocus.mClient.windowFocusChanged(true, mInTouchMode); - } catch (RemoteException e) { - // Ignore if process has died. - } - notifyFocusChanged(); - } - - if (lastFocus != null) { - try { - //Slog.i(TAG, "Losing focus: " + lastFocus); - lastFocus.mClient.windowFocusChanged(false, mInTouchMode); - } catch (RemoteException e) { - // Ignore if process has died. - } - } - - mPolicy.focusChanged(lastFocus, newFocus); - } - } break; - - case REPORT_LOSING_FOCUS: { - ArrayList<WindowState> losers; - - synchronized(mWindowMap) { - losers = mLosingFocus; - mLosingFocus = new ArrayList<WindowState>(); - } - - final int N = losers.size(); - for (int i=0; i<N; i++) { - try { - //Slog.i(TAG, "Losing delayed focus: " + losers.get(i)); - losers.get(i).mClient.windowFocusChanged(false, mInTouchMode); - } catch (RemoteException e) { - // Ignore if process has died. - } - } - } break; - - case ANIMATE: { - synchronized(mWindowMap) { - mAnimationPending = false; - performLayoutAndPlaceSurfacesLocked(); - } - } break; - - case ADD_STARTING: { - final AppWindowToken wtoken = (AppWindowToken)msg.obj; - final StartingData sd = wtoken.startingData; - - if (sd == null) { - // Animation has been canceled... do nothing. - return; - } - - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting " - + wtoken + ": pkg=" + sd.pkg); - - View view = null; - try { - view = mPolicy.addStartingWindow( - wtoken.token, sd.pkg, - sd.theme, sd.nonLocalizedLabel, sd.labelRes, - sd.icon, sd.windowFlags); - } catch (Exception e) { - Slog.w(TAG, "Exception when adding starting window", e); - } - - if (view != null) { - boolean abort = false; - - synchronized(mWindowMap) { - if (wtoken.removed || wtoken.startingData == null) { - // If the window was successfully added, then - // we need to remove it. - if (wtoken.startingWindow != null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, - "Aborted starting " + wtoken - + ": removed=" + wtoken.removed - + " startingData=" + wtoken.startingData); - wtoken.startingWindow = null; - wtoken.startingData = null; - abort = true; - } - } else { - wtoken.startingView = view; - } - if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG, - "Added starting " + wtoken - + ": startingWindow=" - + wtoken.startingWindow + " startingView=" - + wtoken.startingView); - } - - if (abort) { - try { - mPolicy.removeStartingWindow(wtoken.token, view); - } catch (Exception e) { - Slog.w(TAG, "Exception when removing starting window", e); - } - } - } - } break; - - case REMOVE_STARTING: { - final AppWindowToken wtoken = (AppWindowToken)msg.obj; - IBinder token = null; - View view = null; - synchronized (mWindowMap) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting " - + wtoken + ": startingWindow=" - + wtoken.startingWindow + " startingView=" - + wtoken.startingView); - if (wtoken.startingWindow != null) { - view = wtoken.startingView; - token = wtoken.token; - wtoken.startingData = null; - wtoken.startingView = null; - wtoken.startingWindow = null; - } - } - if (view != null) { - try { - mPolicy.removeStartingWindow(token, view); - } catch (Exception e) { - Slog.w(TAG, "Exception when removing starting window", e); - } - } - } break; - - case FINISHED_STARTING: { - IBinder token = null; - View view = null; - while (true) { - synchronized (mWindowMap) { - final int N = mFinishedStarting.size(); - if (N <= 0) { - break; - } - AppWindowToken wtoken = mFinishedStarting.remove(N-1); - - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, - "Finished starting " + wtoken - + ": startingWindow=" + wtoken.startingWindow - + " startingView=" + wtoken.startingView); - - if (wtoken.startingWindow == null) { - continue; - } - - view = wtoken.startingView; - token = wtoken.token; - wtoken.startingData = null; - wtoken.startingView = null; - wtoken.startingWindow = null; - } - - try { - mPolicy.removeStartingWindow(token, view); - } catch (Exception e) { - Slog.w(TAG, "Exception when removing starting window", e); - } - } - } break; - - case REPORT_APPLICATION_TOKEN_WINDOWS: { - final AppWindowToken wtoken = (AppWindowToken)msg.obj; - - boolean nowVisible = msg.arg1 != 0; - boolean nowGone = msg.arg2 != 0; - - try { - if (DEBUG_VISIBILITY) Slog.v( - TAG, "Reporting visible in " + wtoken - + " visible=" + nowVisible - + " gone=" + nowGone); - if (nowVisible) { - wtoken.appToken.windowsVisible(); - } else { - wtoken.appToken.windowsGone(); - } - } catch (RemoteException ex) { - } - } break; - - case WINDOW_FREEZE_TIMEOUT: { - synchronized (mWindowMap) { - Slog.w(TAG, "Window freeze timeout expired."); - int i = mWindows.size(); - while (i > 0) { - i--; - WindowState w = mWindows.get(i); - if (w.mOrientationChanging) { - w.mOrientationChanging = false; - Slog.w(TAG, "Force clearing orientation change: " + w); - } - } - performLayoutAndPlaceSurfacesLocked(); - } - break; - } - - case HOLD_SCREEN_CHANGED: { - Session oldHold; - Session newHold; - synchronized (mWindowMap) { - oldHold = mLastReportedHold; - newHold = (Session)msg.obj; - mLastReportedHold = newHold; - } - - if (oldHold != newHold) { - try { - if (oldHold != null) { - mBatteryStats.noteStopWakelock(oldHold.mUid, -1, - "window", - BatteryStats.WAKE_TYPE_WINDOW); - } - if (newHold != null) { - mBatteryStats.noteStartWakelock(newHold.mUid, -1, - "window", - BatteryStats.WAKE_TYPE_WINDOW); - } - } catch (RemoteException e) { - } - } - break; - } - - case APP_TRANSITION_TIMEOUT: { - synchronized (mWindowMap) { - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "*** APP TRANSITION TIMEOUT"); - mAppTransitionReady = true; - mAppTransitionTimeout = true; - performLayoutAndPlaceSurfacesLocked(); - } - } - break; - } - - case PERSIST_ANIMATION_SCALE: { - Settings.System.putFloat(mContext.getContentResolver(), - Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); - Settings.System.putFloat(mContext.getContentResolver(), - Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); - break; - } - - case FORCE_GC: { - synchronized(mWindowMap) { - if (mAnimationPending) { - // If we are animating, don't do the gc now but - // delay a bit so we don't interrupt the animation. - mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), - 2000); - return; - } - // If we are currently rotating the display, it will - // schedule a new message when done. - if (mDisplayFrozen) { - return; - } - mFreezeGcPending = 0; - } - Runtime.getRuntime().gc(); - break; - } - - case ENABLE_SCREEN: { - performEnableScreen(); - break; - } - - case APP_FREEZE_TIMEOUT: { - synchronized (mWindowMap) { - Slog.w(TAG, "App freeze timeout expired."); - int i = mAppTokens.size(); - while (i > 0) { - i--; - AppWindowToken tok = mAppTokens.get(i); - if (tok.freezingScreen) { - Slog.w(TAG, "Force clearing freeze: " + tok); - unsetAppFreezingScreenLocked(tok, true, true); - } - } - } - break; - } - - case SEND_NEW_CONFIGURATION: { - removeMessages(SEND_NEW_CONFIGURATION); - sendNewConfiguration(); - break; - } - - case REPORT_WINDOWS_CHANGE: { - if (mWindowsChanged) { - synchronized (mWindowMap) { - mWindowsChanged = false; - } - notifyWindowsChanged(); - } - break; - } - - case DRAG_START_TIMEOUT: { - IBinder win = (IBinder)msg.obj; - if (DEBUG_DRAG) { - Slog.w(TAG, "Timeout starting drag by win " + win); - } - synchronized (mWindowMap) { - // !!! TODO: ANR the app that has failed to start the drag in time - if (mDragState != null) { - mDragState.unregister(); - mInputMonitor.updateInputWindowsLw(true /*force*/); - mDragState.reset(); - mDragState = null; - } - } - break; - } - - case DRAG_END_TIMEOUT: { - IBinder win = (IBinder)msg.obj; - if (DEBUG_DRAG) { - Slog.w(TAG, "Timeout ending drag to win " + win); - } - synchronized (mWindowMap) { - // !!! TODO: ANR the drag-receiving app - mDragState.mDragResult = false; - mDragState.endDragLw(); - } - break; - } - - case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { - notifyHardKeyboardStatusChange(); - break; - } - } - } - } - - // ------------------------------------------------------------- - // IWindowManager API - // ------------------------------------------------------------- - - public IWindowSession openSession(IInputMethodClient client, - IInputContext inputContext) { - if (client == null) throw new IllegalArgumentException("null client"); - if (inputContext == null) throw new IllegalArgumentException("null inputContext"); - Session session = new Session(client, inputContext); - return session; - } - - public boolean inputMethodClientHasFocus(IInputMethodClient client) { - synchronized (mWindowMap) { - // The focus for the client is the window immediately below - // where we would place the input method window. - int idx = findDesiredInputMethodWindowIndexLocked(false); - WindowState imFocus; - if (idx > 0) { - imFocus = mWindows.get(idx-1); - //Log.i(TAG, "Desired input method target: " + imFocus); - //Log.i(TAG, "Current focus: " + this.mCurrentFocus); - //Log.i(TAG, "Last focus: " + this.mLastFocus); - if (imFocus != null) { - // This may be a starting window, in which case we still want - // to count it as okay. - if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING - && imFocus.mAppToken != null) { - // The client has definitely started, so it really should - // have a window in this app token. Let's look for it. - for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { - WindowState w = imFocus.mAppToken.windows.get(i); - if (w != imFocus) { - //Log.i(TAG, "Switching to real app window: " + w); - imFocus = w; - break; - } - } - } - //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); - //if (imFocus.mSession.mClient != null) { - // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); - // Log.i(TAG, "Requesting client binder: " + client.asBinder()); - //} - if (imFocus.mSession.mClient != null && - imFocus.mSession.mClient.asBinder() == client.asBinder()) { - return true; - } - - // Okay, how about this... what is the current focus? - // It seems in some cases we may not have moved the IM - // target window, such as when it was in a pop-up window, - // so let's also look at the current focus. (An example: - // go to Gmail, start searching so the keyboard goes up, - // press home. Sometimes the IME won't go down.) - // Would be nice to fix this more correctly, but it's - // way at the end of a release, and this should be good enough. - if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && - mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { - return true; - } - } - } - } - return false; - } - - // ------------------------------------------------------------- - // Internals - // ------------------------------------------------------------- - - final WindowState windowForClientLocked(Session session, IWindow client, - boolean throwOnError) { - return windowForClientLocked(session, client.asBinder(), throwOnError); - } - - final WindowState windowForClientLocked(Session session, IBinder client, - boolean throwOnError) { - WindowState win = mWindowMap.get(client); - if (localLOGV) Slog.v( - TAG, "Looking up client " + client + ": " + win); - if (win == null) { - RuntimeException ex = new IllegalArgumentException( - "Requested window " + client + " does not exist"); - if (throwOnError) { - throw ex; - } - Slog.w(TAG, "Failed looking up window", ex); - return null; - } - if (session != null && win.mSession != session) { - RuntimeException ex = new IllegalArgumentException( - "Requested window " + client + " is in session " + - win.mSession + ", not " + session); - if (throwOnError) { - throw ex; - } - Slog.w(TAG, "Failed looking up window", ex); - return null; - } - - return win; - } - - final void rebuildAppWindowListLocked() { - int NW = mWindows.size(); - int i; - int lastWallpaper = -1; - int numRemoved = 0; - - if (mRebuildTmp.length < NW) { - mRebuildTmp = new WindowState[NW+10]; - } - - // First remove all existing app windows. - i=0; - while (i < NW) { - WindowState w = mWindows.get(i); - if (w.mAppToken != null) { - WindowState win = mWindows.remove(i); - win.mRebuilding = true; - mRebuildTmp[numRemoved] = win; - mWindowsChanged = true; - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, - "Rebuild removing window: " + win); - NW--; - numRemoved++; - continue; - } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER - && lastWallpaper == i-1) { - lastWallpaper = i; - } - i++; - } - - // The wallpaper window(s) typically live at the bottom of the stack, - // so skip them before adding app tokens. - lastWallpaper++; - i = lastWallpaper; - - // First add all of the exiting app tokens... these are no longer - // in the main app list, but still have windows shown. We put them - // in the back because now that the animation is over we no longer - // will care about them. - int NT = mExitingAppTokens.size(); - for (int j=0; j<NT; j++) { - i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j)); - } - - // And add in the still active app tokens in Z order. - NT = mAppTokens.size(); - for (int j=0; j<NT; j++) { - i = reAddAppWindowsLocked(i, mAppTokens.get(j)); - } - - i -= lastWallpaper; - if (i != numRemoved) { - Slog.w(TAG, "Rebuild removed " + numRemoved - + " windows but added " + i); - for (i=0; i<numRemoved; i++) { - WindowState ws = mRebuildTmp[i]; - if (ws.mRebuilding) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - ws.dump(pw, ""); - pw.flush(); - Slog.w(TAG, "This window was lost: " + ws); - Slog.w(TAG, sw.toString()); - } - } - Slog.w(TAG, "Current app token list:"); - dumpAppTokensLocked(); - Slog.w(TAG, "Final window list:"); - dumpWindowsLocked(); - } - } - - private final void assignLayersLocked() { - int N = mWindows.size(); - int curBaseLayer = 0; - int curLayer = 0; - int i; - - if (DEBUG_LAYERS) { - RuntimeException here = new RuntimeException("here"); - here.fillInStackTrace(); - Log.v(TAG, "Assigning layers", here); - } - - for (i=0; i<N; i++) { - WindowState w = mWindows.get(i); - if (w.mBaseLayer == curBaseLayer || w.mIsImWindow - || (i > 0 && w.mIsWallpaper)) { - curLayer += WINDOW_LAYER_MULTIPLIER; - w.mLayer = curLayer; - } else { - curBaseLayer = curLayer = w.mBaseLayer; - w.mLayer = curLayer; - } - if (w.mTargetAppToken != null) { - w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment; - } else if (w.mAppToken != null) { - w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment; - } else { - w.mAnimLayer = w.mLayer; - } - if (w.mIsImWindow) { - w.mAnimLayer += mInputMethodAnimLayerAdjustment; - } else if (w.mIsWallpaper) { - w.mAnimLayer += mWallpaperAnimLayerAdjustment; - } - if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": " - + w.mAnimLayer); - //System.out.println( - // "Assigned layer " + curLayer + " to " + w.mClient.asBinder()); - } - } - - private boolean mInLayout = false; - private final void performLayoutAndPlaceSurfacesLocked() { - if (mInLayout) { - if (DEBUG) { - throw new RuntimeException("Recursive call!"); - } - Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout"); - return; - } - - if (mWaitingForConfig) { - // Our configuration has changed (most likely rotation), but we - // don't yet have the complete configuration to report to - // applications. Don't do any window layout until we have it. - return; - } - - if (mDisplay == null) { - // Not yet initialized, nothing to do. - return; - } - - mInLayout = true; - boolean recoveringMemory = false; - - try { - if (mForceRemoves != null) { - recoveringMemory = true; - // Wait a little bit for things to settle down, and off we go. - for (int i=0; i<mForceRemoves.size(); i++) { - WindowState ws = mForceRemoves.get(i); - Slog.i(TAG, "Force removing: " + ws); - removeWindowInnerLocked(ws.mSession, ws); - } - mForceRemoves = null; - Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); - Object tmp = new Object(); - synchronized (tmp) { - try { - tmp.wait(250); - } catch (InterruptedException e) { - } - } - } - } catch (RuntimeException e) { - Slog.e(TAG, "Unhandled exception while force removing for memory", e); - } - - try { - performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); - - int N = mPendingRemove.size(); - if (N > 0) { - if (mPendingRemoveTmp.length < N) { - mPendingRemoveTmp = new WindowState[N+10]; - } - mPendingRemove.toArray(mPendingRemoveTmp); - mPendingRemove.clear(); - for (int i=0; i<N; i++) { - WindowState w = mPendingRemoveTmp[i]; - removeWindowInnerLocked(w.mSession, w); - } - - mInLayout = false; - assignLayersLocked(); - mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - - } else { - mInLayout = false; - if (mLayoutNeeded) { - requestAnimationLocked(0); - } - } - if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) { - mH.removeMessages(H.REPORT_WINDOWS_CHANGE); - mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE)); - } - } catch (RuntimeException e) { - mInLayout = false; - Slog.e(TAG, "Unhandled exception while layout out windows", e); - } - } - - private final int performLayoutLockedInner(boolean initial, boolean updateInputWindows) { - if (!mLayoutNeeded) { - return 0; - } - - mLayoutNeeded = false; - - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - - final int N = mWindows.size(); - int i; - - if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed=" - + mLayoutNeeded + " dw=" + dw + " dh=" + dh); - - mPolicy.beginLayoutLw(dw, dh); - - int seq = mLayoutSeq+1; - if (seq < 0) seq = 0; - mLayoutSeq = seq; - - // First perform layout of any root windows (not attached - // to another window). - int topAttached = -1; - for (i = N-1; i >= 0; i--) { - WindowState win = mWindows.get(i); - - // Don't do layout of a window if it is not visible, or - // soon won't be visible, to avoid wasting time and funky - // changes while a window is animating away. - final AppWindowToken atoken = win.mAppToken; - final boolean gone = win.mViewVisibility == View.GONE - || !win.mRelayoutCalled - || (atoken == null && win.mRootToken.hidden) - || (atoken != null && atoken.hiddenRequested) - || win.mAttachedHidden - || win.mExiting || win.mDestroying; - - if (DEBUG_LAYOUT && !win.mLayoutAttached) { - Slog.v(TAG, "First pass " + win - + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame - + " mLayoutAttached=" + win.mLayoutAttached); - if (gone) Slog.v(TAG, " (mViewVisibility=" - + win.mViewVisibility + " mRelayoutCalled=" - + win.mRelayoutCalled + " hidden=" - + win.mRootToken.hidden + " hiddenRequested=" - + (atoken != null && atoken.hiddenRequested) - + " mAttachedHidden=" + win.mAttachedHidden); - } - - // If this view is GONE, then skip it -- keep the current - // frame, and let the caller know so they can ignore it - // if they want. (We do the normal layout for INVISIBLE - // windows, since that means "perform layout as normal, - // just don't display"). - if (!gone || !win.mHaveFrame) { - if (!win.mLayoutAttached) { - if (initial) { - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); - win.mContentChanged = false; - } - mPolicy.layoutWindowLw(win, win.mAttrs, null); - win.mLayoutSeq = seq; - if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" - + win.mFrame + " mContainingFrame=" - + win.mContainingFrame + " mDisplayFrame=" - + win.mDisplayFrame); - } else { - if (topAttached < 0) topAttached = i; - } - } - } - - // Now perform layout of attached windows, which usually - // depend on the position of the window they are attached to. - // XXX does not deal with windows that are attached to windows - // that are themselves attached. - for (i = topAttached; i >= 0; i--) { - WindowState win = mWindows.get(i); - - if (win.mLayoutAttached) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win - + " mHaveFrame=" + win.mHaveFrame - + " mViewVisibility=" + win.mViewVisibility - + " mRelayoutCalled=" + win.mRelayoutCalled); - // If this view is GONE, then skip it -- keep the current - // frame, and let the caller know so they can ignore it - // if they want. (We do the normal layout for INVISIBLE - // windows, since that means "perform layout as normal, - // just don't display"). - if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled) - || !win.mHaveFrame) { - if (initial) { - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); - win.mContentChanged = false; - } - mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow); - win.mLayoutSeq = seq; - if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame=" - + win.mFrame + " mContainingFrame=" - + win.mContainingFrame + " mDisplayFrame=" - + win.mDisplayFrame); - } - } - } - - // Window frames may have changed. Tell the input dispatcher about it. - mInputMonitor.setUpdateInputWindowsNeededLw(); - if (updateInputWindows) { - mInputMonitor.updateInputWindowsLw(false /*force*/); - } - - return mPolicy.finishLayoutLw(); - } - - // "Something has changed! Let's make it correct now." - private final void performLayoutAndPlaceSurfacesLockedInner( - boolean recoveringMemory) { - if (mDisplay == null) { - Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); - return; - } - - final long currentTime = SystemClock.uptimeMillis(); - final int dw = mDisplay.getWidth(); - final int dh = mDisplay.getHeight(); - - int i; - - if (mFocusMayChange) { - mFocusMayChange = false; - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/); - } - - // Initialize state of exiting tokens. - for (i=mExitingTokens.size()-1; i>=0; i--) { - mExitingTokens.get(i).hasVisible = false; - } - - // Initialize state of exiting applications. - for (i=mExitingAppTokens.size()-1; i>=0; i--) { - mExitingAppTokens.get(i).hasVisible = false; - } - - boolean orientationChangeComplete = true; - Session holdScreen = null; - float screenBrightness = -1; - float buttonBrightness = -1; - boolean focusDisplayed = false; - boolean animating = false; - boolean createWatermark = false; - boolean updateRotation = false; - boolean screenRotationFinished = false; - - if (mFxSession == null) { - mFxSession = new SurfaceSession(); - createWatermark = true; - } - - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); - - Surface.openTransaction(); - - if (createWatermark) { - createWatermark(); - } - if (mWatermark != null) { - mWatermark.positionSurface(dw, dh); - } - if (mStrictModeFlash != null) { - mStrictModeFlash.positionSurface(dw, dh); - } - - try { - boolean wallpaperForceHidingChanged = false; - int repeats = 0; - int changes = 0; - - do { - repeats++; - if (repeats > 6) { - Slog.w(TAG, "Animation repeat aborted after too many iterations"); - mLayoutNeeded = false; - break; - } - - if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER - | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG - | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) { - if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { - if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { - assignLayersLocked(); - mLayoutNeeded = true; - } - } - if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); - if (updateOrientationFromAppTokensLocked(true)) { - mLayoutNeeded = true; - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - } - if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { - mLayoutNeeded = true; - } - } - - // FIRST LOOP: Perform a layout, if needed. - if (repeats < 4) { - changes = performLayoutLockedInner(repeats == 0, false /*updateInputWindows*/); - if (changes != 0) { - continue; - } - } else { - Slog.w(TAG, "Layout repeat skipped after too many iterations"); - changes = 0; - } - - final int transactionSequence = ++mTransactionSequence; - - // Update animations of all applications, including those - // associated with exiting/removed apps - boolean tokensAnimating = false; - final int NAT = mAppTokens.size(); - for (i=0; i<NAT; i++) { - if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) { - tokensAnimating = true; - } - } - final int NEAT = mExitingAppTokens.size(); - for (i=0; i<NEAT; i++) { - if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) { - tokensAnimating = true; - } - } - - // SECOND LOOP: Execute animations and update visibility of windows. - - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq=" - + transactionSequence + " tokensAnimating=" - + tokensAnimating); - - animating = tokensAnimating; - - if (mScreenRotationAnimation != null) { - if (mScreenRotationAnimation.isAnimating()) { - if (mScreenRotationAnimation.stepAnimation(currentTime)) { - animating = true; - } else { - screenRotationFinished = true; - updateRotation = true; - } - } - } - - boolean tokenMayBeDrawn = false; - boolean wallpaperMayChange = false; - boolean forceHiding = false; - WindowState windowDetachedWallpaper = null; - - mPolicy.beginAnimationLw(dw, dh); - - final int N = mWindows.size(); - - for (i=N-1; i>=0; i--) { - WindowState w = mWindows.get(i); - - final WindowManager.LayoutParams attrs = w.mAttrs; - - if (w.mSurface != null) { - // Take care of the window being ready to display. - if (w.commitFinishDrawingLocked(currentTime)) { - if ((w.mAttrs.flags - & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "First draw done in potential wallpaper target " + w); - wallpaperMayChange = true; - } - } - - final boolean wasAnimating = w.mAnimating; - - int animDw = dw; - int animDh = dh; - - // If the window has moved due to its containing - // content frame changing, then we'd like to animate - // it. The checks here are ordered by what is least - // likely to be true first. - if (w.shouldAnimateMove()) { - // Frame has moved, containing content frame - // has also moved, and we're not currently animating... - // let's do something. - Animation a = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.window_move_from_decor); - w.setAnimation(a); - animDw = w.mLastFrame.left - w.mFrame.left; - animDh = w.mLastFrame.top - w.mFrame.top; - } - - // Execute animation. - final boolean nowAnimating = w.stepAnimationLocked(currentTime, - animDw, animDh); - - // If this window is animating, make a note that we have - // an animating window and take care of a request to run - // a detached wallpaper animation. - if (nowAnimating) { - if (w.mAnimation != null && w.mAnimation.getDetachWallpaper()) { - windowDetachedWallpaper = w; - } - animating = true; - } - - // If this window's app token is running a detached wallpaper - // animation, make a note so we can ensure the wallpaper is - // displayed behind it. - if (w.mAppToken != null && w.mAppToken.animation != null - && w.mAppToken.animation.getDetachWallpaper()) { - windowDetachedWallpaper = w; - } - - if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) { - wallpaperMayChange = true; - } - - if (mPolicy.doesForceHide(w, attrs)) { - if (!wasAnimating && nowAnimating) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "Animation started that could impact force hide: " - + w); - wallpaperForceHidingChanged = true; - mFocusMayChange = true; - } else if (w.isReadyForDisplay() && w.mAnimation == null) { - forceHiding = true; - } - } else if (mPolicy.canBeForceHidden(w, attrs)) { - boolean changed; - if (forceHiding) { - changed = w.hideLw(false, false); - if (DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy hidden: " + w); - } else { - changed = w.showLw(false, false); - if (DEBUG_VISIBILITY && changed) Slog.v(TAG, - "Now policy shown: " + w); - if (changed) { - if (wallpaperForceHidingChanged - && w.isVisibleNow() /*w.isReadyForDisplay()*/) { - // Assume we will need to animate. If - // we don't (because the wallpaper will - // stay with the lock screen), then we will - // clean up later. - Animation a = mPolicy.createForceHideEnterAnimation(); - if (a != null) { - w.setAnimation(a); - } - } - if (mCurrentFocus == null || - mCurrentFocus.mLayer < w.mLayer) { - // We are showing on to of the current - // focus, so re-evaluate focus to make - // sure it is correct. - mFocusMayChange = true; - } - } - } - if (changed && (attrs.flags - & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { - wallpaperMayChange = true; - } - } - - mPolicy.animatingWindowLw(w, attrs); - } - - final AppWindowToken atoken = w.mAppToken; - if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) { - if (atoken.lastTransactionSequence != transactionSequence) { - atoken.lastTransactionSequence = transactionSequence; - atoken.numInterestingWindows = atoken.numDrawnWindows = 0; - atoken.startingDisplayed = false; - } - if ((w.isOnScreen() || w.mAttrs.type - == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) - && !w.mExiting && !w.mDestroying) { - if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { - Slog.v(TAG, "Eval win " + w + ": isDrawn=" - + w.isDrawnLw() - + ", isAnimating=" + w.isAnimating()); - if (!w.isDrawnLw()) { - Slog.v(TAG, "Not displayed: s=" + w.mSurface - + " pv=" + w.mPolicyVisibility - + " dp=" + w.mDrawPending - + " cdp=" + w.mCommitDrawPending - + " ah=" + w.mAttachedHidden - + " th=" + atoken.hiddenRequested - + " a=" + w.mAnimating); - } - } - if (w != atoken.startingWindow) { - if (!atoken.freezingScreen || !w.mAppFreezing) { - atoken.numInterestingWindows++; - if (w.isDrawnLw()) { - atoken.numDrawnWindows++; - if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, - "tokenMayBeDrawn: " + atoken - + " freezingScreen=" + atoken.freezingScreen - + " mAppFreezing=" + w.mAppFreezing); - tokenMayBeDrawn = true; - } - } - } else if (w.isDrawnLw()) { - atoken.startingDisplayed = true; - } - } - } else if (w.mReadyToShow) { - w.performShowLocked(); - } - } - - changes |= mPolicy.finishAnimationLw(); - - if (tokenMayBeDrawn) { - // See if any windows have been drawn, so they (and others - // associated with them) can now be shown. - final int NT = mAppTokens.size(); - for (i=0; i<NT; i++) { - AppWindowToken wtoken = mAppTokens.get(i); - if (wtoken.freezingScreen) { - int numInteresting = wtoken.numInterestingWindows; - if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "allDrawn: " + wtoken - + " interesting=" + numInteresting - + " drawn=" + wtoken.numDrawnWindows); - wtoken.showAllWindowsLocked(); - unsetAppFreezingScreenLocked(wtoken, false, true); - orientationChangeComplete = true; - } - } else if (!wtoken.allDrawn) { - int numInteresting = wtoken.numInterestingWindows; - if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "allDrawn: " + wtoken - + " interesting=" + numInteresting - + " drawn=" + wtoken.numDrawnWindows); - wtoken.allDrawn = true; - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; - - // We can now show all of the drawn windows! - if (!mOpeningApps.contains(wtoken)) { - wtoken.showAllWindowsLocked(); - } - } - } - } - } - - // If we are ready to perform an app transition, check through - // all of the app tokens to be shown and see if they are ready - // to go. - if (mAppTransitionReady) { - int NN = mOpeningApps.size(); - boolean goodToGo = true; - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Checking " + NN + " opening apps (frozen=" - + mDisplayFrozen + " timeout=" - + mAppTransitionTimeout + ")..."); - if (!mDisplayFrozen && !mAppTransitionTimeout) { - // If the display isn't frozen, wait to do anything until - // all of the apps are ready. Otherwise just go because - // we'll unfreeze the display when everyone is ready. - for (i=0; i<NN && goodToGo; i++) { - AppWindowToken wtoken = mOpeningApps.get(i); - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Check opening app" + wtoken + ": allDrawn=" - + wtoken.allDrawn + " startingDisplayed=" - + wtoken.startingDisplayed); - if (!wtoken.allDrawn && !wtoken.startingDisplayed - && !wtoken.startingMoved) { - goodToGo = false; - } - } - } - if (goodToGo) { - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO"); - int transit = mNextAppTransition; - if (mSkipAppTransitionAnimation) { - transit = WindowManagerPolicy.TRANSIT_UNSET; - } - mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; - mAppTransitionReady = false; - mAppTransitionRunning = true; - mAppTransitionTimeout = false; - mStartingIconInTransition = false; - mSkipAppTransitionAnimation = false; - - mH.removeMessages(H.APP_TRANSITION_TIMEOUT); - - // If there are applications waiting to come to the - // top of the stack, now is the time to move their windows. - // (Note that we don't do apps going to the bottom - // here -- we want to keep their windows in the old - // Z-order until the animation completes.) - if (mToTopApps.size() > 0) { - NN = mAppTokens.size(); - for (i=0; i<NN; i++) { - AppWindowToken wtoken = mAppTokens.get(i); - if (wtoken.sendingToTop) { - wtoken.sendingToTop = false; - moveAppWindowsLocked(wtoken, NN, false); - } - } - mToTopApps.clear(); - } - - WindowState oldWallpaper = mWallpaperTarget; - - adjustWallpaperWindowsLocked(); - wallpaperMayChange = false; - - // The top-most window will supply the layout params, - // and we will determine it below. - LayoutParams animLp = null; - int bestAnimLayer = -1; - boolean fullscreenAnim = false; - - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "New wallpaper target=" + mWallpaperTarget - + ", lower target=" + mLowerWallpaperTarget - + ", upper target=" + mUpperWallpaperTarget); - int foundWallpapers = 0; - // Do a first pass through the tokens for two - // things: - // (1) Determine if both the closing and opening - // app token sets are wallpaper targets, in which - // case special animations are needed - // (since the wallpaper needs to stay static - // behind them). - // (2) Find the layout params of the top-most - // application window in the tokens, which is - // what will control the animation theme. - final int NC = mClosingApps.size(); - NN = NC + mOpeningApps.size(); - for (i=0; i<NN; i++) { - AppWindowToken wtoken; - int mode; - if (i < NC) { - wtoken = mClosingApps.get(i); - mode = 1; - } else { - wtoken = mOpeningApps.get(i-NC); - mode = 2; - } - if (mLowerWallpaperTarget != null) { - if (mLowerWallpaperTarget.mAppToken == wtoken - || mUpperWallpaperTarget.mAppToken == wtoken) { - foundWallpapers |= mode; - } - } - if (wtoken.appFullscreen) { - WindowState ws = wtoken.findMainWindow(); - if (ws != null) { - // If this is a compatibility mode - // window, we will always use its anim. - if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) { - animLp = ws.mAttrs; - bestAnimLayer = Integer.MAX_VALUE; - } else if (!fullscreenAnim || ws.mLayer > bestAnimLayer) { - animLp = ws.mAttrs; - bestAnimLayer = ws.mLayer; - } - fullscreenAnim = true; - } - } else if (!fullscreenAnim) { - WindowState ws = wtoken.findMainWindow(); - if (ws != null) { - if (ws.mLayer > bestAnimLayer) { - animLp = ws.mAttrs; - bestAnimLayer = ws.mLayer; - } - } - } - } - - if (foundWallpapers == 3) { - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Wallpaper animation!"); - switch (transit) { - case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: - case WindowManagerPolicy.TRANSIT_TASK_OPEN: - case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: - transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN; - break; - case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: - case WindowManagerPolicy.TRANSIT_TASK_CLOSE: - case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: - transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE; - break; - } - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "New transit: " + transit); - } else if (oldWallpaper != null) { - // We are transitioning from an activity with - // a wallpaper to one without. - transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE; - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "New transit away from wallpaper: " + transit); - } else if (mWallpaperTarget != null) { - // We are transitioning from an activity without - // a wallpaper to now showing the wallpaper - transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN; - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "New transit into wallpaper: " + transit); - } - - // If all closing windows are obscured, then there is - // no need to do an animation. This is the case, for - // example, when this transition is being done behind - // the lock screen. - if (!mPolicy.allowAppAnimationsLw()) { - animLp = null; - } - - NN = mOpeningApps.size(); - for (i=0; i<NN; i++) { - AppWindowToken wtoken = mOpeningApps.get(i); - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Now opening app" + wtoken); - wtoken.reportedVisible = false; - wtoken.inPendingTransaction = false; - wtoken.animation = null; - setTokenVisibilityLocked(wtoken, animLp, true, transit, false); - wtoken.updateReportedVisibilityLocked(); - wtoken.waitingToShow = false; - wtoken.showAllWindowsLocked(); - } - NN = mClosingApps.size(); - for (i=0; i<NN; i++) { - AppWindowToken wtoken = mClosingApps.get(i); - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, - "Now closing app" + wtoken); - wtoken.inPendingTransaction = false; - wtoken.animation = null; - setTokenVisibilityLocked(wtoken, animLp, false, transit, false); - wtoken.updateReportedVisibilityLocked(); - wtoken.waitingToHide = false; - // Force the allDrawn flag, because we want to start - // this guy's animations regardless of whether it's - // gotten drawn. - wtoken.allDrawn = true; - } - - mNextAppTransitionPackage = null; - - mOpeningApps.clear(); - mClosingApps.clear(); - - // This has changed the visibility of windows, so perform - // a new layout to get them all up-to-date. - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT - | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; - mLayoutNeeded = true; - if (!moveInputMethodWindowsIfNeededLocked(true)) { - assignLayersLocked(); - } - updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, - false /*updateInputWindows*/); - mFocusMayChange = false; - } - } - - int adjResult = 0; - - if (!animating && mAppTransitionRunning) { - // We have finished the animation of an app transition. To do - // this, we have delayed a lot of operations like showing and - // hiding apps, moving apps in Z-order, etc. The app token list - // reflects the correct Z-order, but the window list may now - // be out of sync with it. So here we will just rebuild the - // entire app window list. Fun! - mAppTransitionRunning = false; - // Clear information about apps that were moving. - mToBottomApps.clear(); - - rebuildAppWindowListLocked(); - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED; - moveInputMethodWindowsIfNeededLocked(false); - wallpaperMayChange = true; - // Since the window list has been rebuilt, focus might - // have to be recomputed since the actual order of windows - // might have changed again. - mFocusMayChange = true; - } - - if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) { - // At this point, there was a window with a wallpaper that - // was force hiding other windows behind it, but now it - // is going away. This may be simple -- just animate - // away the wallpaper and its window -- or it may be - // hard -- the wallpaper now needs to be shown behind - // something that was hidden. - WindowState oldWallpaper = mWallpaperTarget; - if (mLowerWallpaperTarget != null - && mLowerWallpaperTarget.mAppToken != null) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "wallpaperForceHiding changed with lower=" - + mLowerWallpaperTarget); - if (DEBUG_WALLPAPER) Slog.v(TAG, - "hidden=" + mLowerWallpaperTarget.mAppToken.hidden + - " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested); - if (mLowerWallpaperTarget.mAppToken.hidden) { - // The lower target has become hidden before we - // actually started the animation... let's completely - // re-evaluate everything. - mLowerWallpaperTarget = mUpperWallpaperTarget = null; - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; - } - } - adjResult |= adjustWallpaperWindowsLocked(); - wallpaperMayChange = false; - wallpaperForceHidingChanged = false; - if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper - + " NEW: " + mWallpaperTarget - + " LOWER: " + mLowerWallpaperTarget); - if (mLowerWallpaperTarget == null) { - // Whoops, we don't need a special wallpaper animation. - // Clear them out. - forceHiding = false; - for (i=N-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mSurface != null) { - final WindowManager.LayoutParams attrs = w.mAttrs; - if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { - if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); - forceHiding = true; - } else if (mPolicy.canBeForceHidden(w, attrs)) { - if (!w.mAnimating) { - // We set the animation above so it - // is not yet running. - w.clearAnimation(); - } - } - } - } - } - } - - if (mWindowDetachedWallpaper != windowDetachedWallpaper) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Detached wallpaper changed from " + mWindowDetachedWallpaper - + windowDetachedWallpaper); - mWindowDetachedWallpaper = windowDetachedWallpaper; - wallpaperMayChange = true; - } - - if (wallpaperMayChange) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Wallpaper may change! Adjusting"); - adjResult |= adjustWallpaperWindowsLocked(); - } - - if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Wallpaper layer changed: assigning layers + relayout"); - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - assignLayersLocked(); - } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { - if (DEBUG_WALLPAPER) Slog.v(TAG, - "Wallpaper visibility changed: relayout"); - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - } - - if (mFocusMayChange) { - mFocusMayChange = false; - if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, - false /*updateInputWindows*/)) { - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; - adjResult = 0; - } - } - - if (mLayoutNeeded) { - changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - } - - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x" - + Integer.toHexString(changes)); - } while (changes != 0); - - // THIRD LOOP: Update the surfaces of all windows. - - final boolean someoneLosingFocus = mLosingFocus.size() != 0; - - boolean obscured = false; - boolean blurring = false; - boolean dimming = false; - boolean covered = false; - boolean syswin = false; - boolean backgroundFillerWasShown = mBackgroundFillerTarget != null; - mBackgroundFillerTarget = null; - - final int N = mWindows.size(); - - for (i=N-1; i>=0; i--) { - WindowState w = mWindows.get(i); - - boolean displayed = false; - final WindowManager.LayoutParams attrs = w.mAttrs; - final int attrFlags = attrs.flags; - - if (w.mSurface != null) { - // XXX NOTE: The logic here could be improved. We have - // the decision about whether to resize a window separated - // from whether to hide the surface. This can cause us to - // resize a surface even if we are going to hide it. You - // can see this by (1) holding device in landscape mode on - // home screen; (2) tapping browser icon (device will rotate - // to landscape; (3) tap home. The wallpaper will be resized - // in step 2 but then immediately hidden, causing us to - // have to resize and then redraw it again in step 3. It - // would be nice to figure out how to avoid this, but it is - // difficult because we do need to resize surfaces in some - // cases while they are hidden such as when first showing a - // window. - - w.computeShownFrameLocked(); - if (localLOGV) Slog.v( - TAG, "Placing surface #" + i + " " + w.mSurface - + ": new=" + w.mShownFrame + ", old=" - + w.mLastShownFrame); - - int width, height; - if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) { - // for a scaled surface, we just want to use - // the requested size. - width = w.mRequestedWidth; - height = w.mRequestedHeight; - w.mLastRequestedWidth = width; - w.mLastRequestedHeight = height; - w.mLastShownFrame.set(w.mShownFrame); - } else { - width = w.mShownFrame.width(); - height = w.mShownFrame.height(); - w.mLastShownFrame.set(w.mShownFrame); - } - - if (w.mSurface != null) { - if (w.mSurfaceX != w.mShownFrame.left - || w.mSurfaceY != w.mShownFrame.top) { - try { - if (SHOW_TRANSACTIONS) logSurface(w, - "POS " + w.mShownFrame.left - + ", " + w.mShownFrame.top, null); - w.mSurfaceX = w.mShownFrame.left; - w.mSurfaceY = w.mShownFrame.top; - w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); - } catch (RuntimeException e) { - Slog.w(TAG, "Error positioning surface of " + w - + " pos=(" + w.mShownFrame.left - + "," + w.mShownFrame.top + ")", e); - if (!recoveringMemory) { - reclaimSomeSurfaceMemoryLocked(w, "position"); - } - } - } - - if (width < 1) { - width = 1; - } - if (height < 1) { - height = 1; - } - - if (w.mSurfaceW != width || w.mSurfaceH != height) { - try { - if (SHOW_TRANSACTIONS) logSurface(w, - "SIZE " + w.mShownFrame.width() + "x" - + w.mShownFrame.height(), null); - w.mSurfaceResized = true; - w.mSurfaceW = width; - w.mSurfaceH = height; - w.mSurface.setSize(width, height); - } catch (RuntimeException e) { - // If something goes wrong with the surface (such - // as running out of memory), don't take down the - // entire system. - Slog.e(TAG, "Error resizing surface of " + w - + " size=(" + width + "x" + height + ")", e); - if (!recoveringMemory) { - reclaimSomeSurfaceMemoryLocked(w, "size"); - } - } - } - } - - if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) { - w.mContentInsetsChanged = - !w.mLastContentInsets.equals(w.mContentInsets); - w.mVisibleInsetsChanged = - !w.mLastVisibleInsets.equals(w.mVisibleInsets); - boolean configChanged = - w.mConfiguration != mCurConfiguration - && (w.mConfiguration == null - || mCurConfiguration.diff(w.mConfiguration) != 0); - if (DEBUG_CONFIGURATION && configChanged) { - Slog.v(TAG, "Win " + w + " config changed: " - + mCurConfiguration); - } - if (localLOGV) Slog.v(TAG, "Resizing " + w - + ": configChanged=" + configChanged - + " last=" + w.mLastFrame + " frame=" + w.mFrame); - boolean frameChanged = !w.mLastFrame.equals(w.mFrame); - if (frameChanged - || w.mContentInsetsChanged - || w.mVisibleInsetsChanged - || w.mSurfaceResized - || configChanged) { - if (DEBUG_RESIZE || DEBUG_ORIENTATION) { - Slog.v(TAG, "Resize reasons: " - + "frameChanged=" + frameChanged - + " contentInsetsChanged=" + w.mContentInsetsChanged - + " visibleInsetsChanged=" + w.mVisibleInsetsChanged - + " surfaceResized=" + w.mSurfaceResized - + " configChanged=" + configChanged); - } - - w.mLastFrame.set(w.mFrame); - w.mLastContentInsets.set(w.mContentInsets); - w.mLastVisibleInsets.set(w.mVisibleInsets); - // If the screen is currently frozen, then keep - // it frozen until this window draws at its new - // orientation. - if (mDisplayFrozen) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Resizing while display frozen: " + w); - w.mOrientationChanging = true; - if (!mWindowsFreezingScreen) { - mWindowsFreezingScreen = true; - // XXX should probably keep timeout from - // when we first froze the display. - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage( - H.WINDOW_FREEZE_TIMEOUT), 2000); - } - } - // If the orientation is changing, then we need to - // hold off on unfreezing the display until this - // window has been redrawn; to do that, we need - // to go through the process of getting informed - // by the application when it has finished drawing. - if (w.mOrientationChanging) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation start waiting for draw in " - + w + ", surface " + w.mSurface); - w.mDrawPending = true; - w.mCommitDrawPending = false; - w.mReadyToShow = false; - if (w.mAppToken != null) { - w.mAppToken.allDrawn = false; - } - } - if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, - "Resizing window " + w + " to " + w.mFrame); - mResizingWindows.add(w); - } else if (w.mOrientationChanging) { - if (!w.mDrawPending && !w.mCommitDrawPending) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation not waiting for draw in " - + w + ", surface " + w.mSurface); - w.mOrientationChanging = false; - } - } - } - - if (w.mAttachedHidden || !w.isReadyForDisplay()) { - if (!w.mLastHidden) { - //dump(); - w.mLastHidden = true; - if (SHOW_TRANSACTIONS) logSurface(w, - "HIDE (performLayout)", null); - if (w.mSurface != null) { - w.mSurfaceShown = false; - try { - w.mSurface.hide(); - } catch (RuntimeException e) { - Slog.w(TAG, "Exception hiding surface in " + w); - } - } - } - // If we are waiting for this window to handle an - // orientation change, well, it is hidden, so - // doesn't really matter. Note that this does - // introduce a potential glitch if the window - // becomes unhidden before it has drawn for the - // new orientation. - if (w.mOrientationChanging) { - w.mOrientationChanging = false; - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation change skips hidden " + w); - } - } else if (w.mLastLayer != w.mAnimLayer - || w.mLastAlpha != w.mShownAlpha - || w.mLastDsDx != w.mDsDx - || w.mLastDtDx != w.mDtDx - || w.mLastDsDy != w.mDsDy - || w.mLastDtDy != w.mDtDy - || w.mLastHScale != w.mHScale - || w.mLastVScale != w.mVScale - || w.mLastHidden) { - displayed = true; - w.mLastAlpha = w.mShownAlpha; - w.mLastLayer = w.mAnimLayer; - w.mLastDsDx = w.mDsDx; - w.mLastDtDx = w.mDtDx; - w.mLastDsDy = w.mDsDy; - w.mLastDtDy = w.mDtDy; - w.mLastHScale = w.mHScale; - w.mLastVScale = w.mVScale; - if (SHOW_TRANSACTIONS) logSurface(w, - "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer - + " matrix=[" + (w.mDsDx*w.mHScale) - + "," + (w.mDtDx*w.mVScale) - + "][" + (w.mDsDy*w.mHScale) - + "," + (w.mDtDy*w.mVScale) + "]", null); - if (w.mSurface != null) { - try { - w.mSurfaceAlpha = w.mShownAlpha; - w.mSurface.setAlpha(w.mShownAlpha); - w.mSurfaceLayer = w.mAnimLayer; - w.mSurface.setLayer(w.mAnimLayer); - w.mSurface.setMatrix( - w.mDsDx*w.mHScale, w.mDtDx*w.mVScale, - w.mDsDy*w.mHScale, w.mDtDy*w.mVScale); - } catch (RuntimeException e) { - Slog.w(TAG, "Error updating surface in " + w, e); - if (!recoveringMemory) { - reclaimSomeSurfaceMemoryLocked(w, "update"); - } - } - } - - if (w.mLastHidden && !w.mDrawPending - && !w.mCommitDrawPending - && !w.mReadyToShow) { - if (SHOW_TRANSACTIONS) logSurface(w, - "SHOW (performLayout)", null); - if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w - + " during relayout"); - if (showSurfaceRobustlyLocked(w)) { - w.mHasDrawn = true; - w.mLastHidden = false; - } else { - w.mOrientationChanging = false; - } - } - if (w.mSurface != null) { - w.mToken.hasVisible = true; - } - } else { - displayed = true; - } - - if (displayed) { - if (!covered) { - if (attrs.width == LayoutParams.MATCH_PARENT - && attrs.height == LayoutParams.MATCH_PARENT) { - covered = true; - } - } - if (w.mOrientationChanging) { - if (w.mDrawPending || w.mCommitDrawPending) { - orientationChangeComplete = false; - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation continue waiting for draw in " + w); - } else { - w.mOrientationChanging = false; - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation change complete in " + w); - } - } - w.mToken.hasVisible = true; - } - } else if (w.mOrientationChanging) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Orientation change skips hidden " + w); - w.mOrientationChanging = false; - } - - if (w.mContentChanged) { - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); - w.mContentChanged = false; - } - - final boolean canBeSeen = w.isDisplayedLw(); - - if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) { - focusDisplayed = true; - } - - final boolean obscuredChanged = w.mObscured != obscured; - - if (mBackgroundFillerTarget != null) { - if (w.isAnimating()) { - // Background filler is below all other windows that - // are animating. - mBackgroundFillerTarget = w; - } else if (w.mIsWallpaper) { - mBackgroundFillerTarget = w; - } - } - - // Update effect. - if (!(w.mObscured=obscured)) { - if (w.mSurface != null) { - if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { - holdScreen = w.mSession; - } - if (!syswin && w.mAttrs.screenBrightness >= 0 - && screenBrightness < 0) { - screenBrightness = w.mAttrs.screenBrightness; - } - if (!syswin && w.mAttrs.buttonBrightness >= 0 - && buttonBrightness < 0) { - buttonBrightness = w.mAttrs.buttonBrightness; - } - if (canBeSeen - && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG - || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD - || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) { - syswin = true; - } - } - - boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); - if (opaqueDrawn && w.isFullscreen(dw, dh)) { - // This window completely covers everything behind it, - // so we want to leave all of them as unblurred (for - // performance reasons). - obscured = true; - } else if (w.needsBackgroundFiller(dw, dh) && (canBeSeen || w.isAnimating())) { - // This window is in compatibility mode, and needs background filler. - obscured = true; - mBackgroundFillerTarget = w; - } else if (canBeSeen && !obscured && - (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { - if (localLOGV) Slog.v(TAG, "Win " + w - + ": blurring=" + blurring - + " obscured=" + obscured - + " displayed=" + displayed); - if ((attrFlags&FLAG_DIM_BEHIND) != 0) { - if (!dimming) { - //Slog.i(TAG, "DIM BEHIND: " + w); - dimming = true; - if (mDimAnimator == null) { - mDimAnimator = new DimAnimator(mFxSession); - } - mDimAnimator.show(dw, dh); - mDimAnimator.updateParameters(mContext.getResources(), - w, currentTime); - } - } - if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { - if (!blurring) { - //Slog.i(TAG, "BLUR BEHIND: " + w); - blurring = true; - if (mBlurSurface == null) { - try { - mBlurSurface = new Surface(mFxSession, 0, - "BlurSurface", - -1, 16, 16, - PixelFormat.OPAQUE, - Surface.FX_SURFACE_BLUR); - } catch (Exception e) { - Slog.e(TAG, "Exception creating Blur surface", e); - } - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " - + mBlurSurface + ": CREATE"); - } - if (mBlurSurface != null) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " - + mBlurSurface + ": pos=(0,0) (" + - dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); - mBlurSurface.setPosition(0, 0); - mBlurSurface.setSize(dw, dh); - mBlurSurface.setLayer(w.mAnimLayer-2); - if (!mBlurShown) { - try { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " - + mBlurSurface + ": SHOW"); - mBlurSurface.show(); - } catch (RuntimeException e) { - Slog.w(TAG, "Failure showing blur surface", e); - } - mBlurShown = true; - } - } - } - } - } - } - - if (obscuredChanged && mWallpaperTarget == w) { - // This is the wallpaper target and its obscured state - // changed... make sure the current wallaper's visibility - // has been updated accordingly. - updateWallpaperVisibilityLocked(); - } - } - - if (mBackgroundFillerTarget != null) { - if (mBackgroundFillerSurface == null) { - try { - mBackgroundFillerSurface = new Surface(mFxSession, 0, - "BackGroundFiller", - 0, dw, dh, - PixelFormat.OPAQUE, - Surface.FX_SURFACE_NORMAL); - } catch (Exception e) { - Slog.e(TAG, "Exception creating filler surface", e); - } - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " - + mBackgroundFillerSurface + ": CREATE"); - } - try { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " - + mBackgroundFillerSurface + " SHOW: pos=(0,0) (" - + dw + "x" + dh + ") layer=" - + (mBackgroundFillerTarget.mLayer - 1)); - mBackgroundFillerSurface.setPosition(0, 0); - mBackgroundFillerSurface.setSize(dw, dh); - // Using the same layer as Dim because they will never be shown at the - // same time. NOTE: we do NOT use mAnimLayer, because we don't - // want this surface dragged up in front of stuff that is animating. - mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer - 1); - mBackgroundFillerSurface.show(); - } catch (RuntimeException e) { - Slog.e(TAG, "Exception showing filler surface"); - } - } else if (backgroundFillerWasShown) { - mBackgroundFillerTarget = null; - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BG FILLER " - + mBackgroundFillerSurface + " HIDE"); - try { - mBackgroundFillerSurface.hide(); - } catch (RuntimeException e) { - Slog.e(TAG, "Exception hiding filler surface", e); - } - } - - if (mDimAnimator != null && mDimAnimator.mDimShown) { - animating |= mDimAnimator.updateSurface(dimming, currentTime, - mDisplayFrozen || !mPolicy.isScreenOn()); - } - - if (!blurring && mBlurShown) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface - + ": HIDE"); - try { - mBlurSurface.hide(); - } catch (IllegalArgumentException e) { - Slog.w(TAG, "Illegal argument exception hiding blur surface"); - } - mBlurShown = false; - } - } catch (RuntimeException e) { - Slog.e(TAG, "Unhandled exception in Window Manager", e); - } - - Surface.closeTransaction(); - - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); - - if (mWatermark != null) { - mWatermark.drawIfNeeded(); - } - - if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, - "With display frozen, orientationChangeComplete=" - + orientationChangeComplete); - if (orientationChangeComplete) { - if (mWindowsFreezingScreen) { - mWindowsFreezingScreen = false; - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - } - stopFreezingDisplayLocked(); - } - - i = mResizingWindows.size(); - if (i > 0) { - do { - i--; - WindowState win = mResizingWindows.get(i); - try { - if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, - "Reporting new frame to " + win + ": " + win.mFrame); - int diff = 0; - boolean configChanged = - win.mConfiguration != mCurConfiguration - && (win.mConfiguration == null - || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0); - if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) - && configChanged) { - Slog.i(TAG, "Sending new config to window " + win + ": " - + win.mFrame.width() + "x" + win.mFrame.height() - + " / " + mCurConfiguration + " / 0x" - + Integer.toHexString(diff)); - } - win.mConfiguration = mCurConfiguration; - win.mClient.resized(win.mFrame.width(), - win.mFrame.height(), win.mLastContentInsets, - win.mLastVisibleInsets, win.mDrawPending, - configChanged ? win.mConfiguration : null); - win.mContentInsetsChanged = false; - win.mVisibleInsetsChanged = false; - win.mSurfaceResized = false; - } catch (RemoteException e) { - win.mOrientationChanging = false; - } - } while (i > 0); - mResizingWindows.clear(); - } - - // Destroy the surface of any windows that are no longer visible. - boolean wallpaperDestroyed = false; - i = mDestroySurface.size(); - if (i > 0) { - do { - i--; - WindowState win = mDestroySurface.get(i); - win.mDestroying = false; - if (mInputMethodWindow == win) { - mInputMethodWindow = null; - } - if (win == mWallpaperTarget) { - wallpaperDestroyed = true; - } - win.destroySurfaceLocked(); - } while (i > 0); - mDestroySurface.clear(); - } - - // Time to remove any exiting tokens? - for (i=mExitingTokens.size()-1; i>=0; i--) { - WindowToken token = mExitingTokens.get(i); - if (!token.hasVisible) { - mExitingTokens.remove(i); - if (token.windowType == TYPE_WALLPAPER) { - mWallpaperTokens.remove(token); - } - } - } - - // Time to remove any exiting applications? - for (i=mExitingAppTokens.size()-1; i>=0; i--) { - AppWindowToken token = mExitingAppTokens.get(i); - if (!token.hasVisible && !mClosingApps.contains(token)) { - // Make sure there is no animation running on this token, - // so any windows associated with it will be removed as - // soon as their animations are complete - token.animation = null; - token.animating = false; - if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, - "performLayout: App token exiting now removed" + token); - mAppTokens.remove(token); - mExitingAppTokens.remove(i); - } - } - - boolean needRelayout = false; - - if (!animating && mAppTransitionRunning) { - // We have finished the animation of an app transition. To do - // this, we have delayed a lot of operations like showing and - // hiding apps, moving apps in Z-order, etc. The app token list - // reflects the correct Z-order, but the window list may now - // be out of sync with it. So here we will just rebuild the - // entire app window list. Fun! - mAppTransitionRunning = false; - needRelayout = true; - rebuildAppWindowListLocked(); - assignLayersLocked(); - // Clear information about apps that were moving. - mToBottomApps.clear(); - } - - if (focusDisplayed) { - mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); - } - if (wallpaperDestroyed) { - needRelayout = adjustWallpaperWindowsLocked() != 0; - } - if (needRelayout) { - requestAnimationLocked(0); - } else if (animating) { - requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); - } - - // Finally update all input windows now that the window changes have stabilized. - mInputMonitor.updateInputWindowsLw(true /*force*/); - - setHoldScreenLocked(holdScreen != null); - if (!mDisplayFrozen) { - if (screenBrightness < 0 || screenBrightness > 1.0f) { - mPowerManager.setScreenBrightnessOverride(-1); - } else { - mPowerManager.setScreenBrightnessOverride((int) - (screenBrightness * Power.BRIGHTNESS_ON)); - } - if (buttonBrightness < 0 || buttonBrightness > 1.0f) { - mPowerManager.setButtonBrightnessOverride(-1); - } else { - mPowerManager.setButtonBrightnessOverride((int) - (buttonBrightness * Power.BRIGHTNESS_ON)); - } - } - if (holdScreen != mHoldingScreenOn) { - mHoldingScreenOn = holdScreen; - Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); - mH.sendMessage(m); - } - - if (mTurnOnScreen) { - if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!"); - mPowerManager.userActivity(SystemClock.uptimeMillis(), false, - LocalPowerManager.BUTTON_EVENT, true); - mTurnOnScreen = false; - } - - if (screenRotationFinished && mScreenRotationAnimation != null) { - mScreenRotationAnimation.kill(); - mScreenRotationAnimation = null; - } - - if (updateRotation) { - if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - boolean changed = setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - if (changed) { - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - } - - // Check to see if we are now in a state where the screen should - // be enabled, because the window obscured flags have changed. - enableScreenIfNeededLocked(); - } - - /** - * Must be called with the main window manager lock held. - */ - void setHoldScreenLocked(boolean holding) { - boolean state = mHoldingScreenWakeLock.isHeld(); - if (holding != state) { - if (holding) { - mHoldingScreenWakeLock.acquire(); - } else { - mPolicy.screenOnStoppedLw(); - mHoldingScreenWakeLock.release(); - } - } - } - - void requestAnimationLocked(long delay) { - if (!mAnimationPending) { - mAnimationPending = true; - mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay); - } - } - - /** - * Have the surface flinger show a surface, robustly dealing with - * error conditions. In particular, if there is not enough memory - * to show the surface, then we will try to get rid of other surfaces - * in order to succeed. - * - * @return Returns true if the surface was successfully shown. - */ - boolean showSurfaceRobustlyLocked(WindowState win) { - try { - if (win.mSurface != null) { - win.mSurfaceShown = true; - win.mSurface.show(); - if (win.mTurnOnScreen) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "Show surface turning screen on: " + win); - win.mTurnOnScreen = false; - mTurnOnScreen = true; - } - } - return true; - } catch (RuntimeException e) { - Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e); - } - - reclaimSomeSurfaceMemoryLocked(win, "show"); - - return false; - } - - void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) { - final Surface surface = win.mSurface; - - EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(), - win.mSession.mPid, operation); - - if (mForceRemoves == null) { - mForceRemoves = new ArrayList<WindowState>(); - } - - long callingIdentity = Binder.clearCallingIdentity(); - try { - // There was some problem... first, do a sanity check of the - // window list to make sure we haven't left any dangling surfaces - // around. - int N = mWindows.size(); - boolean leakedSurface = false; - Slog.i(TAG, "Out of memory for surface! Looking for leaks..."); - for (int i=0; i<N; i++) { - WindowState ws = mWindows.get(i); - if (ws.mSurface != null) { - if (!mSessions.contains(ws.mSession)) { - Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): " - + ws + " surface=" + ws.mSurface - + " token=" + win.mToken - + " pid=" + ws.mSession.mPid - + " uid=" + ws.mSession.mUid); - if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); - ws.mSurface.destroy(); - ws.mSurfaceShown = false; - ws.mSurface = null; - mForceRemoves.add(ws); - i--; - N--; - leakedSurface = true; - } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) { - Slog.w(TAG, "LEAKED SURFACE (app token hidden): " - + ws + " surface=" + ws.mSurface - + " token=" + win.mAppToken); - if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null); - ws.mSurface.destroy(); - ws.mSurfaceShown = false; - ws.mSurface = null; - leakedSurface = true; - } - } - } - - boolean killedApps = false; - if (!leakedSurface) { - Slog.w(TAG, "No leaked surfaces; killing applicatons!"); - SparseIntArray pidCandidates = new SparseIntArray(); - for (int i=0; i<N; i++) { - WindowState ws = mWindows.get(i); - if (ws.mSurface != null) { - pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid); - } - } - if (pidCandidates.size() > 0) { - int[] pids = new int[pidCandidates.size()]; - for (int i=0; i<pids.length; i++) { - pids[i] = pidCandidates.keyAt(i); - } - try { - if (mActivityManager.killPids(pids, "Free memory")) { - killedApps = true; - } - } catch (RemoteException e) { - } - } - } - - if (leakedSurface || killedApps) { - // We managed to reclaim some memory, so get rid of the trouble - // surface and ask the app to request another one. - Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); - if (surface != null) { - if (SHOW_TRANSACTIONS) logSurface(win, "RECOVER DESTROY", null); - surface.destroy(); - win.mSurfaceShown = false; - win.mSurface = null; - } - - try { - win.mClient.dispatchGetNewSurface(); - } catch (RemoteException e) { - } - } - } finally { - Binder.restoreCallingIdentity(callingIdentity); - } - } - - private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { - WindowState newFocus = computeFocusedWindowLocked(); - if (mCurrentFocus != newFocus) { - // This check makes sure that we don't already have the focus - // change message pending. - mH.removeMessages(H.REPORT_FOCUS_CHANGE); - mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE); - if (localLOGV) Slog.v( - TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus); - final WindowState oldFocus = mCurrentFocus; - mCurrentFocus = newFocus; - mLosingFocus.remove(newFocus); - - final WindowState imWindow = mInputMethodWindow; - if (newFocus != imWindow && oldFocus != imWindow) { - if (moveInputMethodWindowsIfNeededLocked( - mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && - mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { - mLayoutNeeded = true; - } - if (mode == UPDATE_FOCUS_PLACING_SURFACES) { - performLayoutLockedInner(true /*initial*/, updateInputWindows); - } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) { - // Client will do the layout, but we need to assign layers - // for handleNewWindowLocked() below. - assignLayersLocked(); - } - } - - if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { - // If we defer assigning layers, then the caller is responsible for - // doing this part. - finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows); - } - return true; - } - return false; - } - - private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) { - mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows); - } - - private WindowState computeFocusedWindowLocked() { - WindowState result = null; - WindowState win; - - int i = mWindows.size() - 1; - int nextAppIndex = mAppTokens.size()-1; - WindowToken nextApp = nextAppIndex >= 0 - ? mAppTokens.get(nextAppIndex) : null; - - while (i >= 0) { - win = mWindows.get(i); - - if (localLOGV || DEBUG_FOCUS) Slog.v( - TAG, "Looking for focus: " + i - + " = " + win - + ", flags=" + win.mAttrs.flags - + ", canReceive=" + win.canReceiveKeys()); - - AppWindowToken thisApp = win.mAppToken; - - // If this window's application has been removed, just skip it. - if (thisApp != null && thisApp.removed) { - i--; - continue; - } - - // If there is a focused app, don't allow focus to go to any - // windows below it. If this is an application window, step - // through the app tokens until we find its app. - if (thisApp != null && nextApp != null && thisApp != nextApp - && win.mAttrs.type != TYPE_APPLICATION_STARTING) { - int origAppIndex = nextAppIndex; - while (nextAppIndex > 0) { - if (nextApp == mFocusedApp) { - // Whoops, we are below the focused app... no focus - // for you! - if (localLOGV || DEBUG_FOCUS) Slog.v( - TAG, "Reached focused app: " + mFocusedApp); - return null; - } - nextAppIndex--; - nextApp = mAppTokens.get(nextAppIndex); - if (nextApp == thisApp) { - break; - } - } - if (thisApp != nextApp) { - // Uh oh, the app token doesn't exist! This shouldn't - // happen, but if it does we can get totally hosed... - // so restart at the original app. - nextAppIndex = origAppIndex; - nextApp = mAppTokens.get(nextAppIndex); - } - } - - // Dispatch to this window if it is wants key events. - if (win.canReceiveKeys()) { - if (DEBUG_FOCUS) Slog.v( - TAG, "Found focus @ " + i + " = " + win); - result = win; - break; - } - - i--; - } - - return result; - } - - private void startFreezingDisplayLocked(boolean inTransaction) { - if (mDisplayFrozen) { - return; - } - - mScreenFrozenLock.acquire(); - - long now = SystemClock.uptimeMillis(); - //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now); - if (mFreezeGcPending != 0) { - if (now > (mFreezeGcPending+1000)) { - //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000)); - mH.removeMessages(H.FORCE_GC); - Runtime.getRuntime().gc(); - mFreezeGcPending = now; - } - } else { - mFreezeGcPending = now; - } - - mDisplayFrozen = true; - - mInputMonitor.freezeInputDispatchingLw(); - - if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; - mNextAppTransitionPackage = null; - mAppTransitionReady = true; - } - - if (PROFILE_ORIENTATION) { - File file = new File("/data/system/frozen"); - Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); - } - - if (CUSTOM_SCREEN_ROTATION) { - if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { - mScreenRotationAnimation.kill(); - mScreenRotationAnimation = null; - } - if (mScreenRotationAnimation == null) { - mScreenRotationAnimation = new ScreenRotationAnimation(mContext, - mDisplay, mFxSession, inTransaction); - } - } else { - Surface.freezeDisplay(0); - } - } - - private void stopFreezingDisplayLocked() { - if (!mDisplayFrozen) { - return; - } - - if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) { - return; - } - - mDisplayFrozen = false; - mH.removeMessages(H.APP_FREEZE_TIMEOUT); - if (PROFILE_ORIENTATION) { - Debug.stopMethodTracing(); - } - - boolean updateRotation = false; - - if (CUSTOM_SCREEN_ROTATION) { - if (mScreenRotationAnimation != null) { - if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, - mTransitionAnimationScale)) { - requestAnimationLocked(0); - } else { - mScreenRotationAnimation = null; - updateRotation = true; - } - } - } else { - Surface.unfreezeDisplay(0); - } - - mInputMonitor.thawInputDispatchingLw(); - - boolean configChanged; - - // While the display is frozen we don't re-compute the orientation - // to avoid inconsistent states. However, something interesting - // could have actually changed during that time so re-evaluate it - // now to catch that. - configChanged = updateOrientationFromAppTokensLocked(false); - - // A little kludge: a lot could have happened while the - // display was frozen, so now that we are coming back we - // do a gc so that any remote references the system - // processes holds on others can be released if they are - // no longer needed. - mH.removeMessages(H.FORCE_GC); - mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), - 2000); - - mScreenFrozenLock.release(); - - if (updateRotation) { - if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - configChanged |= setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - } - - if (configChanged) { - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } - } - - static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, - DisplayMetrics dm) { - if (index < tokens.length) { - String str = tokens[index]; - if (str != null && str.length() > 0) { - try { - int val = Integer.parseInt(str); - return val; - } catch (Exception e) { - } - } - } - if (defUnits == TypedValue.COMPLEX_UNIT_PX) { - return defDps; - } - int val = (int)TypedValue.applyDimension(defUnits, defDps, dm); - return val; - } - - static class Watermark { - final String[] mTokens; - final String mText; - final Paint mTextPaint; - final int mTextWidth; - final int mTextHeight; - final int mTextAscent; - final int mTextDescent; - final int mDeltaX; - final int mDeltaY; - - Surface mSurface; - int mLastDW; - int mLastDH; - boolean mDrawNeeded; - - Watermark(Display display, SurfaceSession session, String[] tokens) { - final DisplayMetrics dm = new DisplayMetrics(); - display.getMetrics(dm); - - if (false) { - Log.i(TAG, "*********************** WATERMARK"); - for (int i=0; i<tokens.length; i++) { - Log.i(TAG, " TOKEN #" + i + ": " + tokens[i]); - } - } - - mTokens = tokens; - - StringBuilder builder = new StringBuilder(32); - int len = mTokens[0].length(); - len = len & ~1; - for (int i=0; i<len; i+=2) { - int c1 = mTokens[0].charAt(i); - int c2 = mTokens[0].charAt(i+1); - if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10; - else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10; - else c1 -= '0'; - if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10; - else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10; - else c2 -= '0'; - builder.append((char)(255-((c1*16)+c2))); - } - mText = builder.toString(); - if (false) { - Log.i(TAG, "Final text: " + mText); - } - - int fontSize = getPropertyInt(tokens, 1, - TypedValue.COMPLEX_UNIT_DIP, 20, dm); - - mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mTextPaint.setTextSize(fontSize); - mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); - - FontMetricsInt fm = mTextPaint.getFontMetricsInt(); - mTextWidth = (int)mTextPaint.measureText(mText); - mTextAscent = fm.ascent; - mTextDescent = fm.descent; - mTextHeight = fm.descent - fm.ascent; - - mDeltaX = getPropertyInt(tokens, 2, - TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm); - mDeltaY = getPropertyInt(tokens, 3, - TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm); - int shadowColor = getPropertyInt(tokens, 4, - TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm); - int color = getPropertyInt(tokens, 5, - TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm); - int shadowRadius = getPropertyInt(tokens, 6, - TypedValue.COMPLEX_UNIT_PX, 7, dm); - int shadowDx = getPropertyInt(tokens, 8, - TypedValue.COMPLEX_UNIT_PX, 0, dm); - int shadowDy = getPropertyInt(tokens, 9, - TypedValue.COMPLEX_UNIT_PX, 0, dm); - - mTextPaint.setColor(color); - mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor); - - try { - mSurface = new Surface(session, 0, - "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0); - mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100); - mSurface.setPosition(0, 0); - mSurface.show(); - } catch (OutOfResourcesException e) { - } - } - - void positionSurface(int dw, int dh) { - if (mLastDW != dw || mLastDH != dh) { - mLastDW = dw; - mLastDH = dh; - mSurface.setSize(dw, dh); - mDrawNeeded = true; - } - } - - void drawIfNeeded() { - if (mDrawNeeded) { - final int dw = mLastDW; - final int dh = mLastDH; - - mDrawNeeded = false; - Rect dirty = new Rect(0, 0, dw, dh); - Canvas c = null; - try { - c = mSurface.lockCanvas(dirty); - } catch (IllegalArgumentException e) { - } catch (OutOfResourcesException e) { - } - if (c != null) { - c.drawColor(0, PorterDuff.Mode.CLEAR); - - int deltaX = mDeltaX; - int deltaY = mDeltaY; - - // deltaX shouldn't be close to a round fraction of our - // x step, or else things will line up too much. - int div = (dw+mTextWidth)/deltaX; - int rem = (dw+mTextWidth) - (div*deltaX); - int qdelta = deltaX/4; - if (rem < qdelta || rem > (deltaX-qdelta)) { - deltaX += deltaX/3; - } - - int y = -mTextHeight; - int x = -mTextWidth; - while (y < (dh+mTextHeight)) { - c.drawText(mText, x, y, mTextPaint); - x += deltaX; - if (x >= dw) { - x -= (dw+mTextWidth); - y += deltaY; - } - } - mSurface.unlockCanvasAndPost(c); - } - } - } - } - - void createWatermark() { - if (mWatermark != null) { - return; - } - - File file = new File("/system/etc/setup.conf"); - FileInputStream in = null; - try { - in = new FileInputStream(file); - DataInputStream ind = new DataInputStream(in); - String line = ind.readLine(); - if (line != null) { - String[] toks = line.split("%"); - if (toks != null && toks.length > 0) { - mWatermark = new Watermark(mDisplay, mFxSession, toks); - } - } - } catch (FileNotFoundException e) { - } catch (IOException e) { - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - } - } - } - } - - @Override - public void statusBarVisibilityChanged(int visibility) { - synchronized (mWindowMap) { - final int N = mWindows.size(); - for (int i = 0; i < N; i++) { - WindowState ws = mWindows.get(i); - try { - if (ws.getAttrs().hasSystemUiListeners) { - ws.mClient.dispatchSystemUiVisibilityChanged(visibility); - } - } catch (RemoteException e) { - // so sorry - } - } - } - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission("android.permission.DUMP") - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump WindowManager from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - mInputManager.dump(pw); - pw.println(" "); - - synchronized(mWindowMap) { - pw.println("Current Window Manager state:"); - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - pw.print(" Window #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - if (mInputMethodDialogs.size() > 0) { - pw.println(" "); - pw.println(" Input method dialogs:"); - for (int i=mInputMethodDialogs.size()-1; i>=0; i--) { - WindowState w = mInputMethodDialogs.get(i); - pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w); - } - } - if (mPendingRemove.size() > 0) { - pw.println(" "); - pw.println(" Remove pending for:"); - for (int i=mPendingRemove.size()-1; i>=0; i--) { - WindowState w = mPendingRemove.get(i); - pw.print(" Remove #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - } - if (mForceRemoves != null && mForceRemoves.size() > 0) { - pw.println(" "); - pw.println(" Windows force removing:"); - for (int i=mForceRemoves.size()-1; i>=0; i--) { - WindowState w = mForceRemoves.get(i); - pw.print(" Removing #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - } - if (mDestroySurface.size() > 0) { - pw.println(" "); - pw.println(" Windows waiting to destroy their surface:"); - for (int i=mDestroySurface.size()-1; i>=0; i--) { - WindowState w = mDestroySurface.get(i); - pw.print(" Destroy #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - } - if (mLosingFocus.size() > 0) { - pw.println(" "); - pw.println(" Windows losing focus:"); - for (int i=mLosingFocus.size()-1; i>=0; i--) { - WindowState w = mLosingFocus.get(i); - pw.print(" Losing #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - } - if (mResizingWindows.size() > 0) { - pw.println(" "); - pw.println(" Windows waiting to resize:"); - for (int i=mResizingWindows.size()-1; i>=0; i--) { - WindowState w = mResizingWindows.get(i); - pw.print(" Resizing #"); pw.print(i); pw.print(' '); - pw.print(w); pw.println(":"); - w.dump(pw, " "); - } - } - if (mSessions.size() > 0) { - pw.println(" "); - pw.println(" All active sessions:"); - Iterator<Session> it = mSessions.iterator(); - while (it.hasNext()) { - Session s = it.next(); - pw.print(" Session "); pw.print(s); pw.println(':'); - s.dump(pw, " "); - } - } - if (mTokenMap.size() > 0) { - pw.println(" "); - pw.println(" All tokens:"); - Iterator<WindowToken> it = mTokenMap.values().iterator(); - while (it.hasNext()) { - WindowToken token = it.next(); - pw.print(" Token "); pw.print(token.token); pw.println(':'); - token.dump(pw, " "); - } - } - if (mWallpaperTokens.size() > 0) { - pw.println(" "); - pw.println(" Wallpaper tokens:"); - for (int i=mWallpaperTokens.size()-1; i>=0; i--) { - WindowToken token = mWallpaperTokens.get(i); - pw.print(" Wallpaper #"); pw.print(i); - pw.print(' '); pw.print(token); pw.println(':'); - token.dump(pw, " "); - } - } - if (mAppTokens.size() > 0) { - pw.println(" "); - pw.println(" Application tokens in Z order:"); - for (int i=mAppTokens.size()-1; i>=0; i--) { - pw.print(" App #"); pw.print(i); pw.print(": "); - pw.println(mAppTokens.get(i)); - } - } - if (mFinishedStarting.size() > 0) { - pw.println(" "); - pw.println(" Finishing start of application tokens:"); - for (int i=mFinishedStarting.size()-1; i>=0; i--) { - WindowToken token = mFinishedStarting.get(i); - pw.print(" Finished Starting #"); pw.print(i); - pw.print(' '); pw.print(token); pw.println(':'); - token.dump(pw, " "); - } - } - if (mExitingTokens.size() > 0) { - pw.println(" "); - pw.println(" Exiting tokens:"); - for (int i=mExitingTokens.size()-1; i>=0; i--) { - WindowToken token = mExitingTokens.get(i); - pw.print(" Exiting #"); pw.print(i); - pw.print(' '); pw.print(token); pw.println(':'); - token.dump(pw, " "); - } - } - if (mExitingAppTokens.size() > 0) { - pw.println(" "); - pw.println(" Exiting application tokens:"); - for (int i=mExitingAppTokens.size()-1; i>=0; i--) { - WindowToken token = mExitingAppTokens.get(i); - pw.print(" Exiting App #"); pw.print(i); - pw.print(' '); pw.print(token); pw.println(':'); - token.dump(pw, " "); - } - } - pw.println(" "); - pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); - pw.print(" mLastFocus="); pw.println(mLastFocus); - pw.print(" mFocusedApp="); pw.println(mFocusedApp); - pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); - pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); - pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget); - if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) { - pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget); - pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget); - } - if (mWindowDetachedWallpaper != null) { - pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); - } - pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration); - pw.print(" mInTouchMode="); pw.print(mInTouchMode); - pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); - pw.print(" mSystemBooted="); pw.print(mSystemBooted); - pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); - pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); - pw.print(" mBlurShown="); pw.println(mBlurShown); - if (mDimAnimator != null) { - mDimAnimator.printTo(pw); - } else { - pw.println( " no DimAnimator "); - } - pw.print(" mInputMethodAnimLayerAdjustment="); - pw.print(mInputMethodAnimLayerAdjustment); - pw.print(" mWallpaperAnimLayerAdjustment="); - pw.println(mWallpaperAnimLayerAdjustment); - pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX); - pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY); - pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); - pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); - pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); - pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); - pw.print(" mRotation="); pw.print(mRotation); - pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation); - pw.print(", mRequestedRotation="); pw.println(mRequestedRotation); - pw.print(" mDeferredRotation="); pw.print(mDeferredRotation); - pw.print(", mDeferredRotationAnimFlags="); pw.print(mDeferredRotationAnimFlags); - pw.print(" mAnimationPending="); pw.print(mAnimationPending); - pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); - pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); - pw.print(" mNextAppTransition=0x"); - pw.print(Integer.toHexString(mNextAppTransition)); - pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady); - pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning); - pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout); - if (mNextAppTransitionPackage != null) { - pw.print(" mNextAppTransitionPackage="); - pw.print(mNextAppTransitionPackage); - pw.print(", mNextAppTransitionEnter=0x"); - pw.print(Integer.toHexString(mNextAppTransitionEnter)); - pw.print(", mNextAppTransitionExit=0x"); - pw.print(Integer.toHexString(mNextAppTransitionExit)); - } - pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); - pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); - if (mOpeningApps.size() > 0) { - pw.print(" mOpeningApps="); pw.println(mOpeningApps); - } - if (mClosingApps.size() > 0) { - pw.print(" mClosingApps="); pw.println(mClosingApps); - } - if (mToTopApps.size() > 0) { - pw.print(" mToTopApps="); pw.println(mToTopApps); - } - if (mToBottomApps.size() > 0) { - pw.print(" mToBottomApps="); pw.println(mToBottomApps); - } - if (mDisplay != null) { - pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth()); - pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight()); - } else { - pw.println(" NO DISPLAY"); - } - pw.println(" Policy:"); - mPolicy.dump(" ", fd, pw, args); - } - } - - // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection). - public void monitor() { - synchronized (mWindowMap) { } - synchronized (mKeyguardTokenWatcher) { } - } - - /** - * DimAnimator class that controls the dim animation. This holds the surface and - * all state used for dim animation. - */ - private static class DimAnimator { - Surface mDimSurface; - boolean mDimShown = false; - float mDimCurrentAlpha; - float mDimTargetAlpha; - float mDimDeltaPerMs; - long mLastDimAnimTime; - - int mLastDimWidth, mLastDimHeight; - - DimAnimator (SurfaceSession session) { - if (mDimSurface == null) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " - + mDimSurface + ": CREATE"); - try { - mDimSurface = new Surface(session, 0, - "DimSurface", - -1, 16, 16, PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM); - mDimSurface.setAlpha(0.0f); - } catch (Exception e) { - Slog.e(TAG, "Exception creating Dim surface", e); - } - } - } - - /** - * Show the dim surface. - */ - void show(int dw, int dh) { - if (!mDimShown) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + - dw + "x" + dh + ")"); - mDimShown = true; - try { - mLastDimWidth = dw; - mLastDimHeight = dh; - mDimSurface.setPosition(0, 0); - mDimSurface.setSize(dw, dh); - mDimSurface.show(); - } catch (RuntimeException e) { - Slog.w(TAG, "Failure showing dim surface", e); - } - } else if (mLastDimWidth != dw || mLastDimHeight != dh) { - mLastDimWidth = dw; - mLastDimHeight = dh; - mDimSurface.setSize(dw, dh); - } - } - - /** - * Set's the dim surface's layer and update dim parameters that will be used in - * {@link updateSurface} after all windows are examined. - */ - void updateParameters(Resources res, WindowState w, long currentTime) { - mDimSurface.setLayer(w.mAnimLayer-1); - - final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface - + ": layer=" + (w.mAnimLayer-1) + " target=" + target); - if (mDimTargetAlpha != target) { - // If the desired dim level has changed, then - // start an animation to it. - mLastDimAnimTime = currentTime; - long duration = (w.mAnimating && w.mAnimation != null) - ? w.mAnimation.computeDurationHint() - : DEFAULT_DIM_DURATION; - if (target > mDimTargetAlpha) { - TypedValue tv = new TypedValue(); - res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration, - tv, true); - if (tv.type == TypedValue.TYPE_FRACTION) { - duration = (long)tv.getFraction((float)duration, (float)duration); - } else if (tv.type >= TypedValue.TYPE_FIRST_INT - && tv.type <= TypedValue.TYPE_LAST_INT) { - duration = tv.data; - } - } - if (duration < 1) { - // Don't divide by zero - duration = 1; - } - mDimTargetAlpha = target; - mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; - } - } - - /** - * Updating the surface's alpha. Returns true if the animation continues, or returns - * false when the animation is finished and the dim surface is hidden. - */ - boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { - if (!dimming) { - if (mDimTargetAlpha != 0) { - mLastDimAnimTime = currentTime; - mDimTargetAlpha = 0; - mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; - } - } - - boolean animating = false; - if (mLastDimAnimTime != 0) { - mDimCurrentAlpha += mDimDeltaPerMs - * (currentTime-mLastDimAnimTime); - boolean more = true; - if (displayFrozen) { - // If the display is frozen, there is no reason to animate. - more = false; - } else if (mDimDeltaPerMs > 0) { - if (mDimCurrentAlpha > mDimTargetAlpha) { - more = false; - } - } else if (mDimDeltaPerMs < 0) { - if (mDimCurrentAlpha < mDimTargetAlpha) { - more = false; - } - } else { - more = false; - } - - // Do we need to continue animating? - if (more) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " - + mDimSurface + ": alpha=" + mDimCurrentAlpha); - mLastDimAnimTime = currentTime; - mDimSurface.setAlpha(mDimCurrentAlpha); - animating = true; - } else { - mDimCurrentAlpha = mDimTargetAlpha; - mLastDimAnimTime = 0; - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " - + mDimSurface + ": final alpha=" + mDimCurrentAlpha); - mDimSurface.setAlpha(mDimCurrentAlpha); - if (!dimming) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface - + ": HIDE"); - try { - mDimSurface.hide(); - } catch (RuntimeException e) { - Slog.w(TAG, "Illegal argument exception hiding dim surface"); - } - mDimShown = false; - } - } - } - return animating; - } - - public void printTo(PrintWriter pw) { - pw.print(" mDimShown="); pw.print(mDimShown); - pw.print(" current="); pw.print(mDimCurrentAlpha); - pw.print(" target="); pw.print(mDimTargetAlpha); - pw.print(" delta="); pw.print(mDimDeltaPerMs); - pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); - } - } - - /** - * Animation that fade in after 0.5 interpolate time, or fade out in reverse order. - * This is used for opening/closing transition for apps in compatible mode. - */ - private static class FadeInOutAnimation extends Animation { - boolean mFadeIn; - - public FadeInOutAnimation(boolean fadeIn) { - setInterpolator(new AccelerateInterpolator()); - setDuration(DEFAULT_FADE_IN_OUT_DURATION); - mFadeIn = fadeIn; - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - float x = interpolatedTime; - if (!mFadeIn) { - x = 1.0f - x; // reverse the interpolation for fade out - } - t.setAlpha(x); - } - } - - public interface OnHardKeyboardStatusChangeListener { - public void onHardKeyboardStatusChange(boolean available, boolean enabled); - } -} |